pax_global_header00006660000000000000000000000064147570644240014527gustar00rootroot0000000000000052 comment=d142ed29e1b709eeda23f2a31431cd13ae5836ad xilinx-bootgen-2024.2/000077500000000000000000000000001475706442400145665ustar00rootroot00000000000000xilinx-bootgen-2024.2/FlexLexer.h000077500000000000000000000141111475706442400166360ustar00rootroot00000000000000// -*-C++-*- // FlexLexer.h -- define interfaces for lexical analyzer classes generated // by flex // Copyright (c) 1993 The Regents of the University of California. // All rights reserved. // // This code is derived from software contributed to Berkeley by // Kent Williams and Tom Epperly. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // Neither the name of the University nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE. // This file defines FlexLexer, an abstract class which specifies the // external interface provided to flex C++ lexer objects, and yyFlexLexer, // which defines a particular lexer class. // // If you want to create multiple lexer classes, you use the -P flag // to rename each yyFlexLexer to some other xxFlexLexer. You then // include "FlexLexer.h" in your other sources once per lexer class: // // #undef yyFlexLexer // #define yyFlexLexer xxFlexLexer // #include "FlexLexer.h" // // #undef yyFlexLexer // #define yyFlexLexer zzFlexLexer // #include "FlexLexer.h" // ... #ifndef __FLEX_LEXER_H // Never included before - need to define base class. #define __FLEX_LEXER_H #include # ifndef FLEX_STD # define FLEX_STD std:: # endif extern "C++" { struct yy_buffer_state; typedef int yy_state_type; class FlexLexer { public: virtual ~FlexLexer() { } const char* YYText() const { return yytext; } int YYLeng() const { return yyleng; } virtual void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0; virtual struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size ) = 0; virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0; virtual void yyrestart( FLEX_STD istream* s ) = 0; virtual int yylex() = 0; // Call yylex with new input/output sources. int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 ) { switch_streams( new_in, new_out ); return yylex(); } // Switch to new input/output streams. A nil stream pointer // indicates "keep the current one". virtual void switch_streams( FLEX_STD istream* new_in = 0, FLEX_STD ostream* new_out = 0 ) = 0; int lineno() const { return yylineno; } int debug() const { return yy_flex_debug; } void set_debug( int flag ) { yy_flex_debug = flag; } protected: char* yytext; int yyleng; int yylineno; // only maintained if you use %option yylineno int yy_flex_debug; // only has effect with -d or "%option debug" }; } #endif // FLEXLEXER_H #if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) // Either this is the first time through (yyFlexLexerOnce not defined), // or this is a repeated include to define a different flavor of // yyFlexLexer, as discussed in the flex manual. #define yyFlexLexerOnce extern "C++" { class yyFlexLexer : public FlexLexer { public: // arg_yyin and arg_yyout default to the cin and cout, but we // only make that assignment when initializing in yylex(). yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 ); virtual ~yyFlexLexer(); void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ); struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size ); void yy_delete_buffer( struct yy_buffer_state* b ); void yyrestart( FLEX_STD istream* s ); void yypush_buffer_state( struct yy_buffer_state* new_buffer ); void yypop_buffer_state(); virtual int yylex(); virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 ); virtual int yywrap(); protected: virtual int LexerInput( char* buf, int max_size ); virtual void LexerOutput( const char* buf, int size ); virtual void LexerError( const char* msg ); void yyunput( int c, char* buf_ptr ); int yyinput(); void yy_load_buffer_state(); void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s ); void yy_flush_buffer( struct yy_buffer_state* b ); int yy_start_stack_ptr; int yy_start_stack_depth; int* yy_start_stack; void yy_push_state( int new_state ); void yy_pop_state(); int yy_top_state(); yy_state_type yy_get_previous_state(); yy_state_type yy_try_NUL_trans( yy_state_type current_state ); int yy_get_next_buffer(); FLEX_STD istream* yyin; // input source for default LexerInput FLEX_STD ostream* yyout; // output sink for default LexerOutput // yy_hold_char holds the character lost when yytext is formed. char yy_hold_char; // Number of characters read into yy_ch_buf. int yy_n_chars; // Points to current character in buffer. char* yy_c_buf_p; int yy_init; // whether we need to initialize int yy_start; // start state number // Flag which is used to allow yywrap()'s to do buffer switches // instead of setting up a fresh yyin. A bit of a hack ... int yy_did_buffer_switch_on_eof; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */ void yyensure_buffer_stack(void); // The following are not always needed, but may be depending // on use of certain flex features (like REJECT or yymore()). yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; yy_state_type* yy_state_buf; yy_state_type* yy_state_ptr; char* yy_full_match; int* yy_full_state; int yy_full_lp; int yy_lp; int yy_looking_for_trail_begin; int yy_more_flag; int yy_more_len; int yy_more_offset; int yy_prev_more_offset; }; } #endif // yyFlexLexer || ! yyFlexLexerOnce xilinx-bootgen-2024.2/Keccak-compact-settings.h000077500000000000000000000001341475706442400214030ustar00rootroot00000000000000#define cKeccakB 1600 #define cKeccakR 832 #define cKeccakFixedOutputLengthInBytes 48 xilinx-bootgen-2024.2/Keccak-compact-versal.cpp000077500000000000000000000072721475706442400214040ustar00rootroot00000000000000/* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. For more information, feedback or questions, please refer to our website: http://keccak.noekeon.org/ Implementation by Ronny Van Keer, hereby denoted as "the implementer". To the extent possible under law, the implementer has waived all copyright and related or neighboring rights to the source code in this file. http://creativecommons.org/publicdomain/zero/1.0/ */ #include #include "Keccak-compact-settings.h" #include "Keccak-compact-versal.h" #define cKeccakR_SizeInBytes (cKeccakR / 8) //#include "crypto_hash.h" #ifndef crypto_hash_BYTES #ifdef cKeccakFixedOutputLengthInBytes #define crypto_hash_BYTES cKeccakFixedOutputLengthInBytes #else #define crypto_hash_BYTES cKeccakR_SizeInBytes #endif #endif #if (crypto_hash_BYTES > cKeccakR_SizeInBytes) #error "Full squeezing not yet implemented" #endif #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN /* WARNING: This implementation works on little-endian platform. Support for big-endinanness is implemented, but not tested. */ #if (cKeccakB == 1600) typedef unsigned long long UINT64; typedef UINT64 tKeccakLane; #define cKeccakNumberOfRounds 24 #elif (cKeccakB == 800) typedef unsigned int UINT32; // WARNING: on 8-bit and 16-bit platforms, this should be replaced by: //typedef unsigned long UINT32; typedef UINT32 tKeccakLane; #define cKeccakNumberOfRounds 22 #elif (cKeccakB == 400) typedef unsigned short UINT16; typedef UINT16 tKeccakLane; #define cKeccakNumberOfRounds 20 #elif (cKeccakB == 200) typedef unsigned char UINT8; typedef UINT8 tKeccakLane; #define cKeccakNumberOfRounds 18 #else #error "Unsupported Keccak-f width" #endif typedef unsigned int tSmallUInt; /*INFO It could be more optimized to use "unsigned char" on an 8-bit CPU */ #define cKeccakLaneSizeInBits (sizeof(tKeccakLane) * 8) #define ROL(a, offset) (tKeccakLane)((((tKeccakLane)a) << ((offset) % cKeccakLaneSizeInBits)) ^ (((tKeccakLane)a) >> (cKeccakLaneSizeInBits-((offset) % cKeccakLaneSizeInBits)))) void KeccakF(tKeccakLane * state, const tKeccakLane *in, int laneCount); int Versalcrypto_hash(unsigned char *out, const unsigned char *in, unsigned long long inlen, bool padding) { tKeccakLane state[5 * 5]; #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #define temp out #else unsigned char temp[cKeccakR_SizeInBytes]; #endif memset(state, 0, sizeof(state)); for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes) { KeccakF(state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane)); } if (padding) { /*Last data and padding*/ memcpy(temp, in, (size_t)inlen); temp[inlen++] = 6; if (inlen < cKeccakR_SizeInBytes) { memset(temp + inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen); } temp[cKeccakR_SizeInBytes - 1] |= 0x80; KeccakF(state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane)); } #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) memcpy(out, state, crypto_hash_BYTES); #else for (i = 0; i < (crypto_hash_BYTES / sizeof(tKeccakLane)); ++i) { tSmallUInt j; tKeccakLane t; t = state[i]; for (j = 0; j < sizeof(tKeccakLane); ++j) { *(out++) = (unsigned char)t; t >>= 8; } } #endif #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #undef temp #endif return (0); } xilinx-bootgen-2024.2/Keccak-compact-versal.h000077500000000000000000000013731475706442400210450ustar00rootroot00000000000000/* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. For more information, feedback or questions, please refer to our website: http://keccak.noekeon.org/ Implementation by Ronny Van Keer, hereby denoted as "the implementer". To the extent possible under law, the implementer has waived all copyright and related or neighboring rights to the source code in this file. http://creativecommons.org/publicdomain/zero/1.0/ */ #ifndef _Keccak_compact_versal_h_ #define _Keccak_compact_versal_h_ #include "Keccak-compact-settings.h" int Versalcrypto_hash(unsigned char *out, const unsigned char *in, unsigned long long inlen, bool padding); /* ** API with message queue (inspired from NIST's API) */ #endif xilinx-bootgen-2024.2/Keccak-compact.cpp000077500000000000000000000246021475706442400201060ustar00rootroot00000000000000/* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. For more information, feedback or questions, please refer to our website: http://keccak.noekeon.org/ Implementation by Ronny Van Keer, hereby denoted as "the implementer". To the extent possible under law, the implementer has waived all copyright and related or neighboring rights to the source code in this file. http://creativecommons.org/publicdomain/zero/1.0/ */ #include #include "Keccak-compact-settings.h" #include "Keccak-compact.h" #define cKeccakR_SizeInBytes (cKeccakR / 8) //#include "crypto_hash.h" #ifndef crypto_hash_BYTES #ifdef cKeccakFixedOutputLengthInBytes #define crypto_hash_BYTES cKeccakFixedOutputLengthInBytes #else #define crypto_hash_BYTES cKeccakR_SizeInBytes #endif #endif #if (crypto_hash_BYTES > cKeccakR_SizeInBytes) #error "Full squeezing not yet implemented" #endif #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN /* WARNING: This implementation works on little-endian platform. Support for big-endinanness is implemented, but not tested. */ #if (cKeccakB == 1600) typedef unsigned long long UINT64; typedef UINT64 tKeccakLane; #define cKeccakNumberOfRounds 24 #elif (cKeccakB == 800) typedef unsigned int UINT32; // WARNING: on 8-bit and 16-bit platforms, this should be replaced by: //typedef unsigned long UINT32; typedef UINT32 tKeccakLane; #define cKeccakNumberOfRounds 22 #elif (cKeccakB == 400) typedef unsigned short UINT16; typedef UINT16 tKeccakLane; #define cKeccakNumberOfRounds 20 #elif (cKeccakB == 200) typedef unsigned char UINT8; typedef UINT8 tKeccakLane; #define cKeccakNumberOfRounds 18 #else #error "Unsupported Keccak-f width" #endif typedef unsigned int tSmallUInt; /*INFO It could be more optimized to use "unsigned char" on an 8-bit CPU */ #define cKeccakLaneSizeInBits (sizeof(tKeccakLane) * 8) #define ROL(a, offset) (tKeccakLane)((((tKeccakLane)a) << ((offset) % cKeccakLaneSizeInBits)) ^ (((tKeccakLane)a) >> (cKeccakLaneSizeInBits-((offset) % cKeccakLaneSizeInBits)))) void KeccakF( tKeccakLane * state, const tKeccakLane *in, int laneCount ); int crypto_hash_NIST_SHA3(unsigned char *out, const unsigned char *in, unsigned long long inlen) { tKeccakLane state[5 * 5]; #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #define temp out #else unsigned char temp[cKeccakR_SizeInBytes]; #endif memset(state, 0, sizeof(state)); for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes) { KeccakF(state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane)); } /* Last data and padding */ memcpy(temp, in, (size_t)inlen); //temp[inlen++] = 1; temp[inlen++] = 6; if (inlen < cKeccakR_SizeInBytes) { memset(temp + inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen); } temp[cKeccakR_SizeInBytes - 1] |= 0x80; KeccakF(state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane)); #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) memcpy(out, state, crypto_hash_BYTES); #else for (i = 0; i < (crypto_hash_BYTES / sizeof(tKeccakLane)); ++i) { tSmallUInt j; tKeccakLane t; t = state[i]; for (j = 0; j < sizeof(tKeccakLane); ++j) { *(out++) = (unsigned char)t; t >>= 8; } } #endif #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #undef temp #endif return (0); } int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ) { tKeccakLane state[5 * 5]; #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #define temp out #else unsigned char temp[cKeccakR_SizeInBytes]; #endif memset( state, 0, sizeof(state) ); for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes ) { KeccakF( state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); } /* Last data and padding */ memcpy( temp, in, (size_t)inlen ); temp[inlen++] = 1; if (inlen < cKeccakR_SizeInBytes) { memset( temp+inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen ); } temp[cKeccakR_SizeInBytes-1] |= 0x80; KeccakF( state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) memcpy( out, state, crypto_hash_BYTES ); #else for ( i = 0; i < (crypto_hash_BYTES / sizeof(tKeccakLane)); ++i ) { tSmallUInt j; tKeccakLane t; t = state[i]; for ( j = 0; j < sizeof(tKeccakLane); ++j ) { *(out++) = (unsigned char)t; t >>= 8; } } #endif #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #undef temp #endif return ( 0 ); } const tKeccakLane KeccakF_RoundConstants[cKeccakNumberOfRounds] = { (tKeccakLane)0x0000000000000001ULL, (tKeccakLane)0x0000000000008082ULL, (tKeccakLane)0x800000000000808aULL, (tKeccakLane)0x8000000080008000ULL, (tKeccakLane)0x000000000000808bULL, (tKeccakLane)0x0000000080000001ULL, (tKeccakLane)0x8000000080008081ULL, (tKeccakLane)0x8000000000008009ULL, (tKeccakLane)0x000000000000008aULL, (tKeccakLane)0x0000000000000088ULL, (tKeccakLane)0x0000000080008009ULL, (tKeccakLane)0x000000008000000aULL, (tKeccakLane)0x000000008000808bULL, (tKeccakLane)0x800000000000008bULL, (tKeccakLane)0x8000000000008089ULL, (tKeccakLane)0x8000000000008003ULL, (tKeccakLane)0x8000000000008002ULL, (tKeccakLane)0x8000000000000080ULL #if (cKeccakB >= 400) , (tKeccakLane)0x000000000000800aULL, (tKeccakLane)0x800000008000000aULL #if (cKeccakB >= 800) , (tKeccakLane)0x8000000080008081ULL, (tKeccakLane)0x8000000000008080ULL #if (cKeccakB == 1600) , (tKeccakLane)0x0000000080000001ULL, (tKeccakLane)0x8000000080008008ULL #endif #endif #endif }; const tSmallUInt KeccakF_RotationConstants[25] = { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 }; const tSmallUInt KeccakF_PiLane[25] = { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 }; const tSmallUInt KeccakF_Mod5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 }; void KeccakF( tKeccakLane * state, const tKeccakLane *in, int laneCount ) { tSmallUInt x, y; tKeccakLane temp; tKeccakLane BC[5]; #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) while ( --laneCount >= 0 ) { state[laneCount] ^= in[laneCount]; } #else temp = 0; /* please compiler */ while ( --laneCount >= 0 ) { for ( x = 0; x < sizeof(tKeccakLane); ++x ) { temp <<= 8; temp |= ((char*)&in[laneCount])[x]; } state[laneCount] = temp; } #endif #define round laneCount for( round = 0; round < cKeccakNumberOfRounds; ++round ) { // Theta for ( x = 0; x < 5; ++x ) { BC[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^ state[15 + x] ^ state[20 + x]; } for ( x = 0; x < 5; ++x ) { temp = BC[KeccakF_Mod5[x+4]] ^ ROL(BC[KeccakF_Mod5[x+1]], 1); for ( y = 0; y < 25; y += 5 ) { state[y + x] ^= temp; } } // Rho Pi temp = state[1]; for ( x = 0; x < 24; ++x ) { BC[0] = state[KeccakF_PiLane[x]]; state[KeccakF_PiLane[x]] = ROL( temp, KeccakF_RotationConstants[x] ); temp = BC[0]; } // Chi for ( y = 0; y < 25; y += 5 ) { BC[0] = state[y + 0]; BC[1] = state[y + 1]; BC[2] = state[y + 2]; BC[3] = state[y + 3]; BC[4] = state[y + 4]; for ( x = 0; x < 5; ++x ) { state[y + x] = BC[x] ^((~BC[KeccakF_Mod5[x+1]]) & BC[KeccakF_Mod5[x+2]]); } } // Iota state[0] ^= KeccakF_RoundConstants[round]; } #undef round } HashReturn Init(hashState *state) { state->bitsInQueue = 0; memset( state->state, 0, sizeof(state->state) ); return ( SUCCESS ); } HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) { if ( (state->bitsInQueue < 0) || ((state->bitsInQueue % 8) != 0) ) { /* Final() already called or bits already in queue not modulo 8. */ return ( FAIL ); } /* If already data in queue, continue queuing first */ for ( /* empty */; (databitlen >= 8) && (state->bitsInQueue != 0); databitlen -= 8 ) { state->state[state->bitsInQueue / 8] ^= *(data++); if ( (state->bitsInQueue += 8) == cKeccakR ) { KeccakF( (tKeccakLane *)state->state, 0, 0 ); state->bitsInQueue = 0; } } /* Absorb complete blocks */ for ( /* */; databitlen >= cKeccakR; databitlen -= cKeccakR, data += cKeccakR_SizeInBytes ) { KeccakF( (tKeccakLane *)state->state, (const tKeccakLane *)data, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); } /* Queue remaining data bytes */ for ( /* empty */; databitlen >=8; databitlen -= 8, state->bitsInQueue += 8 ) { state->state[state->bitsInQueue / 8] ^= *(data++); } /* Queue eventual remaining data bits plus add first padding bit */ if ( databitlen != 0 ) { state->state[state->bitsInQueue / 8] ^= (*data >> (8 - databitlen)); state->bitsInQueue += (int)databitlen; } return ( SUCCESS ); } HashReturn Final(hashState *state, BitSequence *hashval, tSmallUInt hashbytelen) { tSmallUInt i; if ( state->bitsInQueue < 0 ) { /* Final() already called. */ return ( FAIL ); } // Padding if (state->bitsInQueue + 1 == cKeccakR_SizeInBytes*8) { state->state[cKeccakR_SizeInBytes-1] ^= 0x80; KeccakF( (tKeccakLane *)state->state, 0, 0 ); } else { state->state[state->bitsInQueue/8] ^= 1 << (state->bitsInQueue % 8); } state->state[cKeccakR_SizeInBytes-1] ^= 0x80; KeccakF( (tKeccakLane *)state->state, 0, 0 ); // Output for ( /* empty */; hashbytelen != 0; hashval += i, hashbytelen -= i ) { i = (hashbytelen < cKeccakR_SizeInBytes) ? hashbytelen : cKeccakR_SizeInBytes; #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) memcpy( hashval, state->state, i ); #else for ( offset = 0; offset < i; offset += sizeof(tKeccakLane) ) { tSmallUInt j; for ( j = 0; j < sizeof(tKeccakLane); ++j ) { hashval[offset + j] = state->state[offset + (sizeof(tKeccakLane) - 1) - j]; } } #endif if ( i != hashbytelen ) { KeccakF( (tKeccakLane *)state->state, 0, 0 ); } } state->bitsInQueue = -1; /* flag final state */ return ( SUCCESS ); } xilinx-bootgen-2024.2/Keccak-compact.h000077500000000000000000000026511475706442400175530ustar00rootroot00000000000000/* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. For more information, feedback or questions, please refer to our website: http://keccak.noekeon.org/ Implementation by Ronny Van Keer, hereby denoted as "the implementer". To the extent possible under law, the implementer has waived all copyright and related or neighboring rights to the source code in this file. http://creativecommons.org/publicdomain/zero/1.0/ */ #ifndef _Keccak_compact_h_ #define _Keccak_compact_h_ #include "Keccak-compact-settings.h" int crypto_hash_NIST_SHA3(unsigned char *out, const unsigned char *in, unsigned long long inlen); int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ); /* ** API with message queue (inspired from NIST's API) */ typedef unsigned char BitSequence; typedef unsigned long long DataLength; typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; #if defined(__GNUC__) #define ALIGN __attribute__ ((aligned(32))) #elif defined(_MSC_VER) #define ALIGN __declspec(align(32)) #else #define ALIGN #endif ALIGN typedef struct hashStateStruct { ALIGN unsigned char state[cKeccakB / 8]; int bitsInQueue; } hashState; HashReturn Init(hashState *state); HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); HashReturn Final(hashState *state, BitSequence *hashval, unsigned int hashbytelen); #endif xilinx-bootgen-2024.2/LICENSE000077500000000000000000000134331475706442400156020ustar00rootroot00000000000000Components: bootgen /****************************************************************************** * Copyright 2015-2020 Xilinx, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ Components: bison 2.7 /* Skeleton interface for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ Copyright 2002-2012 Free Software Foundation Inc Components: flex 2.5.35 // This code is derived from software contributed to Berkeley by // Kent Williams and Tom Epperly. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // Neither the name of the University nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE. Copyright (c) 1993 The Regents of the University of California. All rights reserved. Components: keccak 3.3 /* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, Micha??l Peeters and Gilles Van Assche. For more information, feedback or questions, please refer to our website: http://keccak.noekeon.org/ Implementation by Ronny Van Keer, hereby denoted as "the implementer". To the extent possible under law, the implementer has waived all copyright and related or neighboring rights to the source code in this file. http://creativecommons.org/publicdomain/zero/1.0/ */ Copyright (c) 1994 Hewlett-Packard Company Copyright (c) 1993 The Regents of the University of California. Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. Copyright 2002-2012 Free Software Foundation Inc Components: stdint.h 0.1.5 * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must not misrepresent the orignal * source in the documentation and/or other materials provided * with the distribution. * * The names of the authors not its contributors may be used to * endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************** Copyright (c) 2005 Paul Hsieh xilinx-bootgen-2024.2/Makefile000077500000000000000000000045741475706442400162430ustar00rootroot00000000000000############################################################################## # # Copyright 2015-2022 Xilinx, Inc. # Copyright 2022-2023 Advanced Micro Devices, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## # # Building Bootgen for x86 Host: # 'make "LIBS= -ldl # -lpthread" "INCLUDE_USER=-I"' # # Building Bootgen for ARM v8: # 'make "CROSS_COMPILE=aarch64-linux-gnu-" "LIBS= \ # -ldl -lpthread" # "INCLUDE_USER=-I"' # ############################################################################## ifneq ($(CROSS_COMPILE), ) CXX = $(CROSS_COMPILE)g++ CC = $(CROSS_COMPILE)gcc else ifneq ($(CROSS_COMPILER), ) CXX = $(CROSS_COMPILER) CC = $(subst g++,gcc,$(CROSS_COMPILER)) else CXX = g++ CC = gcc endif OBJ = o CXXFLAGS ?= -std=c++0x -O -Wall -Wno-reorder -Wno-deprecated-declarations CFLAGS ?= -O -Wall GCCVERSIONGTEQ9 := $(shell expr `${CXX} -dumpversion | cut -f1 -d.` \>= 9) ifeq "$(GCCVERSIONGTEQ9)" "1" CXXFLAGS += -Wno-aligned-new -Wno-misleading-indentation -Wno-class-memaccess endif EXEC = bootgen UNAME := $(shell uname) ifeq ($(UNAME), Linux) INCLUDE_SYS = -I. LIBS = -lssl -lcrypto RTLIBS = OPTIONS_USER = endif INCLUDE = $(INCLUDE_USER) $(INCLUDE_SYS) OPTIONS = $(OPTIONS_USER) all: $(EXEC) $(RTLIBS) OBJECTS = $(addsuffix .o, $(basename $(wildcard *.cpp))) OBJECTS += $(addsuffix .o, $(basename $(wildcard *.c))) %.${OBJ} : %.cpp ${CXX} -c ${CXXFLAGS} $(OPTIONS) ${INCLUDE} $< %.${OBJ} : %.c ${CC} -c ${CFLAGS} $(OPTIONS) ${INCLUDE} $< ${EXEC}: $(OBJECTS) echo Building executable file: $@... ${CXX} $(CXXFLAGS) $(LDFLAGS) $(OPTIONS_USER) -o $@ $(OBJECTS) $(LIBS) execs: ${EXEC} clean: echo rm -rf ${EXEC} rm -f $(OBJECTS) xilinx-bootgen-2024.2/README.md000077500000000000000000000114031475706442400160470ustar00rootroot00000000000000bootgen.git - Source code for Xilinx Bootgen # Overview This repository contains source code to build Bootgen for SoC devices. This repository provides _NO_ support for traditional FPGA devices (Artix, Kintex, and Virtex families). These features are only available as part of Bootgen shipped with Vivado tools. For SoC devices (Zynq-7000, Zynq UltraScale+ MPSoC, etc), this repository includes support for all features of BootGen, including BIN file construction and boot-time authentication and encryption based on OpenSSL (see details below). For more details about Bootgen usage, please refer to Xilinx UG1283. ## Obfuscated Key generation Bootgen also supports Obfuscated Key generation using a Xilinx proprietary software. If you are using this proprietary flow, please contact a Xilinx® representative at 'secure.solutions@xilinx.com'for details and to ensure export compliance. # Build instructions ## Platform Support Bootgen can be built for both Linux and Windows operating systems. It can be compiled natively for x86-based computers as well as cross-compiled for ARM-based platforms. The following 3rd party packages are required to build Bootgen: * OpenSSL v1.1.1b libraries * Windows libraries are available at http://slproweb.com/products/Win32OpenSSL.html * Linux libraries are part of libssl-dev package ## Linux Builds A Makefile is included along with the code to build Bootgen for Linux. This Makefile creates an executable named bootgen, when run. 1. Install OpenSSL libraries. 2. In the bootgen directory, run make 3. If OpenSSL libraries are located at a custom path, you can link with these libraries as given below. Assuming OpenSSL libraries are located at /home/$USER/local/openssl, make "LIBS=/home/\$USER/local/openssl/lib/libssl.a /home/\$USER/local/openssl/lib/libcrypto.a -ldl -lpthread" \ "INCLUDE_USER=-I/home/\$USER/local/openssl/include" ## Windows Builds 1. Download and install "Win64 OpenSSL v1.1.1b", from http://slproweb.com/products/Win32OpenSSL.html. 2. Use Microsoft Visual Studio 2015 to build Bootgen source code and link it . with OpenSSL libraries downloaded in previous step. ## Cross-compiling Bootgen Bootgen can be cross-compiled to run on Xilinx processors. 1. Cross-compile openssl libraries. 2. Cross-compile Bootgen code and link against the libraries built above make "CROSS_COMPILER=aarch64-linux-gnu-g++" "LIBS= \ -ldl -lpthread" "INCLUDE_USER=-I"' # OpenSSL License Bootgen links with openssl libraries. Below is openssl copyright. ``` Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` xilinx-bootgen-2024.2/attributes.h000077500000000000000000000054241475706442400171350ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _ATTRIBUTES_LIST_H_ #define _ATTRIBUTES_LIST_H_ #include #include #include std::pair > type ( "type", { "bootloader", "cdo", "pmcdata", "bootimage", "raw", "cfi", "cfi-gsc", "slr-boot", "slr-config" } ); std::pair > core ( "core", { "psm", "a72-0", "a72-1", "r5-0", "r5-1", "r5-lockstep", "aie" } ); std::pair > encryption ( "encryption", { "none", "aes" } ); std::pair > authentication ( "authentication", { "none", "rsa", "ecdsa-p384" // This is similar to "ecdsa" option we currently support. As there is a request for another ecdsa algo, we had to rename this. "ecdsa-p521" } ); std::pair > keysrc ( "keysrc", { /* Options for bootloader/pmcdata/metaheader and other partitions */ "efuse_red_key", "efuse_blk_key", "bbram_red_key", "bbram_blk_key", "bh_blk_key", /* Options for other partitions - these are invalid for bootloader/pmcdata/metaheader*/ "user_key0", "user_key1", "user_key2", "user_key3", "user_key4", "user_key5", "user_key6", "user_key7", "efuse_user_key0", "efuse_user_blk_key0", "efuse_user_key1", "efuse_user_blk_key1", "kup_key" } ); std::pair > checksum ( "checksum", { "none", "sha3" } ); /* List of all attributes */ std::vector>> bootgen_options { type, core, encryption, authentication, keysrc, checksum }; #endifxilinx-bootgen-2024.2/authentication-versal.cpp000077500000000000000000001730151475706442400216150ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "authentication-versal.h" #include "authentication.h" #include "bootgenexception.h" #include "stringutils.h" #include "binary.h" #include "bootimage.h" #include #include #include "string.h" #include "options.h" #include #include "partitionheadertable-versal.h" #include "imageheadertable-versal.h" #include "Keccak-compact-versal.h" #include "encryptutils.h" #include /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalAuthenticationContext::VersalAuthenticationContext(Authentication::Type type) { signatureLength = SIGN_LENGTH_VERSAL; spksignature = new uint8_t[signatureLength]; bHsignature = new uint8_t[signatureLength]; spkSignLoaded = false; memset(udf_data, 0, UDF_DATA_SIZE); memset(bHsignature, 0, signatureLength); bhSignLoaded = false; certSize = sizeof(AuthCertificate4096Sha3PaddingStructure); hashType = AuthHash::Sha3; authAlgorithm = GetAuthenticationAlgorithm(type); if (type == Authentication::RSA) { primaryKey = new Key4096Sha3Padding("Primary Key"); secondaryKey = new Key4096Sha3Padding("Secondary Key"); primaryKey->authType = Authentication::RSA; secondaryKey->authType = Authentication::RSA; } else if (type == Authentication::ECDSA) { primaryKey = new KeyECDSA("Primary Key"); secondaryKey = new KeyECDSA("Secondary Key"); primaryKey->authType = Authentication::ECDSA; secondaryKey->authType = Authentication::ECDSA; } else { primaryKey = new KeyECDSAp521("Primary Key"); secondaryKey = new KeyECDSAp521("Secondary Key"); primaryKey->authType = Authentication::ECDSAp521; secondaryKey->authType = Authentication::ECDSAp521; } } /******************************************************************************/ VersalAuthenticationContext::VersalAuthenticationContext(const AuthenticationContext* refAuthContext, Authentication::Type authtype) { signatureLength = SIGN_LENGTH_VERSAL; spksignature = new uint8_t[signatureLength]; bHsignature = new uint8_t[signatureLength]; authAlgorithm = GetAuthenticationAlgorithm(authtype); hashType = AuthHash::Sha3; ppkFile = refAuthContext->ppkFile; pskFile = refAuthContext->pskFile; spkFile = refAuthContext->spkFile; sskFile = refAuthContext->sskFile; spkSignFile = refAuthContext->spkSignFile; bhSignFile = refAuthContext->bhSignFile; spkSelect = refAuthContext->spkSelect; spkIdentification = refAuthContext->spkIdentification; if (authtype == Authentication::RSA) { primaryKey = new Key4096Sha3Padding("Primary Key"); secondaryKey = new Key4096Sha3Padding("Secondary Key"); primaryKey->authType = Authentication :: RSA; secondaryKey->authType = Authentication :: RSA; } else if(authtype == Authentication::ECDSA) { primaryKey = new KeyECDSA("Primary Key"); secondaryKey = new KeyECDSA("Secondary Key"); primaryKey->authType = Authentication :: ECDSA; secondaryKey->authType = Authentication :: ECDSA; } else { primaryKey = new KeyECDSAp521("Primary Key"); secondaryKey = new KeyECDSAp521("Secondary Key"); primaryKey->authType = Authentication :: ECDSAp521; secondaryKey->authType = Authentication :: ECDSAp521; } if (pskFile != "" || ppkFile != "") { if (pskFile != "") { primaryKey->ParseSecret(pskFile); } if (ppkFile != "") { primaryKey->ParsePublic(ppkFile); } } else { primaryKey = refAuthContext->primaryKey; } if (spkFile != "" || sskFile != "") { if (sskFile != "") { secondaryKey->ParseSecret(sskFile); } if (spkFile != "") { secondaryKey->ParsePublic(spkFile); } } else { secondaryKey = refAuthContext->secondaryKey; } if (spkSignFile != "") { SetSPKSignatureFile(spkSignFile); } else { memcpy(spksignature, refAuthContext->spksignature, signatureLength); } if (bhSignFile != "") { SetBHSignatureFile(bhSignFile); } else { memcpy(bHsignature, refAuthContext->bHsignature, signatureLength); } memcpy(udf_data, refAuthContext->udf_data, sizeof(udf_data)); bhSignLoaded = refAuthContext->bhSignLoaded; spkSignLoaded = refAuthContext->spkSignLoaded; spkSignRequested = refAuthContext->spkSignRequested; certSize = sizeof(AuthCertificate4096Sha3PaddingStructure); preSigned = refAuthContext->preSigned; } /******************************************************************************/ VersalAuthenticationContext::VersalAuthenticationContext(const AuthCertificate4096Sha3PaddingStructure* existingCert, Authentication::Type authtype) { signatureLength = SIGN_LENGTH_VERSAL; spksignature = new uint8_t[signatureLength]; spkSignLoaded = true; bHsignature = new uint8_t[signatureLength]; bhSignLoaded = true; authAlgorithm = GetAuthenticationAlgorithm(authtype); if (authtype == Authentication::RSA) { primaryKey = new Key4096Sha3Padding("Primary Key"); secondaryKey = new Key4096Sha3Padding("Secondary Key"); primaryKey->authType = Authentication::RSA; secondaryKey->authType = Authentication::RSA; } else if (authtype == Authentication::ECDSA) { primaryKey = new KeyECDSA("Primary Key"); secondaryKey = new KeyECDSA("Secondary Key"); primaryKey->authType = Authentication::ECDSA; secondaryKey->authType = Authentication::ECDSA; } else { primaryKey = new KeyECDSAp521("Primary Key"); secondaryKey = new KeyECDSAp521("Secondary Key"); primaryKey->authType = Authentication::ECDSAp521; secondaryKey->authType = Authentication::ECDSAp521; } primaryKey->Import(&existingCert->acPpk, "Primary Key"); secondaryKey->Import(&existingCert->acSpk, "Secondary Key"); hashType = AuthHash::Sha3; authAlgorithm->RearrangeEndianess(primaryKey->N, sizeof(existingCert->acPpk.N)); authAlgorithm->RearrangeEndianess(primaryKey->N_ext, sizeof(existingCert->acPpk.N_extension)); authAlgorithm->RearrangeEndianess(primaryKey->E, sizeof(existingCert->acPpk.E)); authAlgorithm->RearrangeEndianess(secondaryKey->N, sizeof(existingCert->acSpk.N)); authAlgorithm->RearrangeEndianess(secondaryKey->N_ext, sizeof(existingCert->acSpk.N_extension)); authAlgorithm->RearrangeEndianess(secondaryKey->E, sizeof(existingCert->acSpk.E)); memcpy(spksignature, existingCert->acSpkSignature.Signature, signatureLength); memcpy(bHsignature, existingCert->acHeaderSignature.Signature, signatureLength); memcpy(udf_data, existingCert->acUdf, UDF_DATA_SIZE); spkIdentification = existingCert->spkId; certSize = sizeof(AuthCertificate4096Sha3PaddingStructure); } /******************************************************************************/ AuthenticationAlgorithm* VersalAuthenticationContext::GetAuthenticationAlgorithm(Authentication::Type type) { if (type == Authentication::ECDSA) { SetAuthenticationKeyLength(EC_P384_KEY_LENGTH); return new ECDSAAuthenticationAlgorithm(); } else if (type == Authentication::ECDSAp521) { //SetAuthenticationKeyLength(EC_P521_KEY_LENGTH); return new ECDSAP521AuthenticationAlgorithm(); } else { SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); return new RSA4096Sha3PaddingAuthenticationAlgorithm(); } } /******************************************************************************/ uint32_t VersalAuthenticationContext::GetCertificateSize(void) { return certSize; } /******************************************************************************/ VersalAuthenticationContext::~VersalAuthenticationContext() { if (spksignature != NULL) { delete[] spksignature; spksignature = nullptr; } if (bHsignature != NULL) { delete[] bHsignature; bHsignature = nullptr; } if (primaryKey != NULL) { delete primaryKey; primaryKey = nullptr; } if (secondaryKey != NULL) { delete secondaryKey; secondaryKey = nullptr; } } /******************************************************************************/ ECDSAAuthenticationAlgorithm::ECDSAAuthenticationAlgorithm() { certSize = sizeof(AuthCertificateECDSAStructure); authType = Authentication::ECDSA; } /******************************************************************************/ ECDSAAuthenticationAlgorithm::~ECDSAAuthenticationAlgorithm() { } /******************************************************************************/ ECDSAP521AuthenticationAlgorithm::ECDSAP521AuthenticationAlgorithm() { certSize = sizeof(AuthCertificateECDSAp521Structure); authType = Authentication::ECDSAp521; } /******************************************************************************/ ECDSAP521AuthenticationAlgorithm::~ECDSAP521AuthenticationAlgorithm() { } /******************************************************************************/ RSA4096Sha3PaddingAuthenticationAlgorithm::RSA4096Sha3PaddingAuthenticationAlgorithm() { certSize = sizeof(AuthCertificate4096Sha3PaddingStructure); authType = Authentication::RSA; } /******************************************************************************/ RSA4096Sha3PaddingAuthenticationAlgorithm::~RSA4096Sha3PaddingAuthenticationAlgorithm() { } /******************************************************************************/ static void FillSha3Padding(uint8_t* pad, uint32_t sha3PadLength) { uint8_t *sha3 = new uint8_t[sha3PadLength]; memset(sha3, 0, sha3PadLength); sha3[0] = 0x6; sha3[(sha3PadLength)-1] |= 0x80; memcpy(pad, sha3, sha3PadLength); delete[] sha3; } /******************************************************************************/ uint8_t* RSA4096Sha3PaddingAuthenticationAlgorithm::AttachSHA3Padding(uint8_t* data, const Binary::Length_t datalength) { uint8_t sha3padding = SHA3_PAD_LENGTH - (datalength % SHA3_PAD_LENGTH); uint8_t *dataSha3 = new uint8_t[datalength + sha3padding]; memset(dataSha3, 0, datalength + sha3padding); memcpy(dataSha3, data, datalength); dataSha3[datalength] = 0x6; dataSha3[(datalength + sha3padding) - 1] |= 0x80; return dataSha3; } /******************************************************************************/ int RSA4096Sha3PaddingAuthenticationAlgorithm::MaskGenerationFunction(unsigned char *mask, long len, const unsigned char *seed, long seedlen, const EVP_MD *dgst) { long i, outlen = 0; unsigned char cnt[4]; unsigned char md[SHA3_LENGTH_BYTES]; int mdlen = SHA3_LENGTH_BYTES; int rv = -1; uint8_t* c = new uint8_t[52]; uint8_t* cSha3Pad = NULL; if (mdlen < 0) goto err; for (i = 0; outlen < len; i++) { cnt[0] = (unsigned char)((i >> 24) & 255); cnt[1] = (unsigned char)((i >> 16) & 255); cnt[2] = (unsigned char)((i >> 8)) & 255; cnt[3] = (unsigned char)(i & 255); memcpy(c, seed, seedlen); memcpy(c + seedlen, cnt, 4); cSha3Pad = AttachSHA3Padding(c, (seedlen + 4)); if (outlen + mdlen <= len) { Versalcrypto_hash(mask + outlen, cSha3Pad, 104, false); outlen += mdlen; } else { Versalcrypto_hash(md, cSha3Pad, 104, false); memcpy(mask + outlen, md, len - outlen); outlen = len; } } rv = 0; delete[] c; delete[] cSha3Pad; err: return rv; } /******************************************************************************/ Section* VersalAuthenticationContext::CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection) { LOG_INFO("Creating Authentication Certificate for section - %s", dataSection->Name.c_str()); hashType = bi.GetAuthHashAlgo(); hash = bi.hash; hashLength = hash->GetHashLength(); std::string hashExtension = hash->GetHashFileExtension(); /* Partition size must be 64-byte aligned */ if ((dataSection->Length & 0x3F) != 0) { //LOG_ERROR("Authentication Error !!!\n Partition %s's length %d bytes - is not 64-byte aligned - %s", dataSection->Name.c_str(), dataSection->Length); } /* Secondary key is must for authenticating */ if (!secondaryKey->Loaded) { LOG_ERROR("Authentication Error !!!\n Secondary key must be specified in BIF file for %s", dataSection->Name.c_str()); } if (!secondaryKey->isSecret) { if (presignFile != "") { // ok } else if (bi.options.GetNonBootingFlag() && (dataSection->Name.find("MetaHeader") != std::string::npos)) { // ok } else if (bi.options.DoGenerateHashes() || bi.options.GetNonBootingFlag()) { static bool warningGiven = false; std::list outFilename = bi.options.GetOutputFileNames(); if (outFilename.size() > 0) { if (!warningGiven) { LOG_WARNING("SSK is needed to authenticate a boot image. Because the key provided is not secret, the bootimage will not be usable. However, the sha hash files will be generated for offline signing"); warningGiven = true; } } } else if (bi.currentAuthCtx->spkSignRequested != "") { LOG_WARNING("SSK is needed to authenticate a boot image. Because the key provided is not secret, the bootimage will not be usable. However, SPK signature will be generated as requested."); } else { LOG_ERROR("Authentication Error !!!\n SSK or partition must have [presign=xxx] attribute in BIF file for section %s", dataSection->Name.c_str()); } } if (!(primaryKey->Loaded && primaryKey->isSecret) && !spkSignLoaded) { if (bi.options.DoGenerateHashes()) { LOG_WARNING("Either PSK or spksignature is needed to authenticate bootimage or generate partition hashes. Because they are not provided, the bootimage and partition hashes will not be usable. However SPK hash and bootheader hash files generated can be used for offline signing."); } else { LOG_ERROR("Authentication Error !!!\n Either PSK or SPK signature file must be specified in BIF file."); } } std::string name = dataSection->Name; if (dataSection->index == 0) { name = GetCertificateName(name); } Section* acSection = new Section(name + hashExtension, certSize); acSection->isCertificate = true; acSection->index = dataSection->index; cache.Sections.push_back(acSection); uint8_t* authCert = acSection->Data; LOG_TRACE("Creating new section for certificate - %s", acSection->Name.c_str()); uint32_t x = sizeof(AuthCertificate4096Sha3PaddingStructure); if (x != certSize) { LOG_DEBUG(DEBUG_STAMP, "Bad Authentication Certificate Size"); LOG_ERROR("Authentication Error !!!"); } memset(authCert, 0, certSize); uint32_t acHdr = authAlgorithm->GetAuthHeader(); acHdr |= ((bi.GetAuthHashAlgo()) ? 0 : 1) << AC_HDR_SHA_2_3_BIT_SHIFT; WriteLittleEndian32(authCert+AC_HEADER_OFFSET, acHdr); WriteLittleEndian32(authCert+AC_SPK_ID_OFFSET, spkIdentification); if (udfFile != "") { LoadUdfData(udfFile, udf_data); authAlgorithm->RearrangeEndianess(udf_data, sizeof(udf_data)); memcpy(authCert+AC_UDF_OFFSET, udf_data, UDF_DATA_SIZE); } primaryKey->Export(authCert+AC_PPK_KEY_OFFSET); authAlgorithm->RearrangeEndianess(authCert+AC_PPK_KEY_OFFSET + RSA_4096_N, RSA_4096_N_SIZE); authAlgorithm->RearrangeEndianess(authCert + AC_PPK_KEY_OFFSET + RSA_4096_N_EXT, RSA_4096_N_EXT_SIZE); authAlgorithm->RearrangeEndianess(authCert + AC_PPK_KEY_OFFSET + RSA_4096_E, RSA_4096_E_SIZE); FillSha3Padding(authCert+AC_PPK_SHA3PAD_OFFSET, AC_PPK_SHA3PAD_SIZE); secondaryKey->Export(authCert+AC_SPK_KEY_OFFSET); authAlgorithm->RearrangeEndianess(authCert + AC_SPK_KEY_OFFSET + RSA_4096_N, RSA_4096_N_SIZE); authAlgorithm->RearrangeEndianess(authCert + AC_SPK_KEY_OFFSET + RSA_4096_N_EXT, RSA_4096_N_EXT_SIZE); authAlgorithm->RearrangeEndianess(authCert + AC_SPK_KEY_OFFSET + RSA_4096_E, RSA_4096_E_SIZE); FillSha3Padding(authCert+AC_SPK_SHA3PAD_OFFSET, AC_SPK_SHA3PAD_SIZE); memset(authCert+AC_ALLIGNMENT_OFFSET, 0, AC_ALLIGNMENT_SIZE); CopySPKSignature(authCert+AC_SPK_SIGN_OFFSET); certIndex++; return acSection; } /******************************************************************************/ static uint32_t ComputeWordChecksum(void* firstWordPtr, size_t length) { uint32_t checksum = 0; size_t numChecksumedWords = length / sizeof(uint32_t); for (size_t i = 0; i< numChecksumedWords; i++) { checksum += ((uint32_t*)firstWordPtr)[i]; } /* Invert the Checksum value */ checksum ^= 0xFFFFFFFF; return checksum; } /******************************************************************************/ void VersalAuthenticationContext::SetHashinOptionalData(BootImage& bi) { uint32_t sectn_size_id = 0; /* Optional Data Header + Optional Data Actual size (32 bit(4Bytes) partition Number + Hash Length in bytes) + Checksum */ uint16_t sectn_length = sizeof(uint32_t) + (bi.hashTable.size() * (sizeof(uint32_t) + SHA3_LENGTH_BYTES)) + sizeof(uint32_t); /* Data ID for Hash block is fixed to 3 */ sectn_size_id = (uint32_t)((sectn_length / 4) << 16) | DATA_ID_PARTITION_HASHES; memcpy(bi.iht_optional_data + (bi.copied_iht_optional_data_length / 4), §n_size_id, sizeof(uint32_t)); bi.copied_iht_optional_data_length += sizeof(uint32_t); for (size_t i = 0; i < bi.hashTable.size(); i++) { uint32_t partition_num = bi.hashTable[i].first; memcpy(bi.iht_optional_data + (bi.copied_iht_optional_data_length / 4), &partition_num, sizeof(uint32_t)); bi.copied_iht_optional_data_length += sizeof(uint32_t); memcpy(bi.iht_optional_data + (bi.copied_iht_optional_data_length / 4), bi.hashTable[i].second, SHA3_LENGTH_BYTES); bi.copied_iht_optional_data_length += SHA3_LENGTH_BYTES; } uint32_t checksum = ComputeWordChecksum(bi.iht_optional_data + ((bi.copied_iht_optional_data_length - sectn_length + sizeof(uint32_t)) / 4), sectn_length - sizeof(uint32_t)); memcpy(bi.iht_optional_data + (bi.copied_iht_optional_data_length / 4), &checksum, sizeof(uint32_t)); bi.copied_iht_optional_data_length += sizeof(uint32_t); if (bi.copied_iht_optional_data_length != 0) { uint32_t padLength = (bi.copied_iht_optional_data_length % 64 != 0) ? 64 - (bi.copied_iht_optional_data_length % 64) : 0; if (bi.copied_iht_optional_data_length + padLength != bi.iht_optional_data_length) { LOG_ERROR("Optional Data Length doen't match the calculated length"); } } memcpy(bi.imageHeaderTable->section->Data + sizeof(VersalImageHeaderTableStructure) + (bi.copied_iht_optional_data_length - sectn_length), bi.iht_optional_data + (bi.copied_iht_optional_data_length - sectn_length) / 4, sectn_length); //bi.copied_iht_optional_data_length += sectn_length; LOG_TRACE("Partition Hash processed to optional data"); } /******************************************************************************/ void VersalAuthenticationContext::Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert) { /* Copy bhSignature when bootloader */ memset(cert->section->Data + AC_BH_SIGN_OFFSET, 0, signatureLength); /*check*/ if (sections.front()->isBootloader) { CopybHSignature(bi, cert->section->Data + AC_BH_SIGN_OFFSET); } /* Copy meta header Signature when headers */ /* With authentication optimization */ if(bi.options.IsAuthOptimizationEnabled()){ if (sections.front()->Name == "Headers") { CopyPartitionSignature(bi, sections, cert->section->Data + AC_PARTITION_SIGN_OFFSET, cert->section); SetHashinOptionalData(bi); CopyIHTSignature(bi, cert->section->Data + AC_BH_SIGN_OFFSET); } if (presignFile == "") { if(sections.front()->Name != "Headers"){ CopyPartitionSignature(bi, sections, cert->section->Data + AC_PARTITION_SIGN_OFFSET, cert->section); } } else { int index = acIndex; if (cert->section->index != 0) { index = cert->section->index; } GetPresign(presignFile, cert->section->Data + AC_PARTITION_SIGN_OFFSET, index); acIndex++; } } /* Normal flow -- Without authentication optimization */ else { if (sections.front()->Name == "Headers") { CopyIHTSignature(bi, cert->section->Data + AC_BH_SIGN_OFFSET); } if (presignFile == "") { CopyPartitionSignature(bi, sections, cert->section->Data + AC_PARTITION_SIGN_OFFSET, cert->section); } else { int index = acIndex; if (cert->section->index != 0) { index = cert->section->index; } GetPresign(presignFile, cert->section->Data + AC_PARTITION_SIGN_OFFSET, index); acIndex++; } } } /******************************************************************************/ void VersalAuthenticationContext::CopybHSignature(BootImage& bi, uint8_t* ptr) { uint8_t* sha_hash_padded = new uint8_t[signatureLength]; uint8_t* bHsignaturetmp = new uint8_t[signatureLength]; memset(bHsignaturetmp, 0, signatureLength); memset(sha_hash_padded, 0, signatureLength); GenerateBHHash(bi, sha_hash_padded); if (bi.options.DoGenerateHashes()) { std::string hashfilename = "bootheader" + hash->GetHashFileExtension(); WritePaddedSHAFile(sha_hash_padded, hashfilename); } if (primaryKey->Loaded && primaryKey->isSecret) { LOG_TRACE("Creating Boot Header Signature"); authAlgorithm->RearrangeEndianess(sha_hash_padded, signatureLength); authAlgorithm->CreateSignature(sha_hash_padded, (uint8_t*)secondaryKey, bHsignaturetmp); authAlgorithm->RearrangeEndianess(bHsignaturetmp, signatureLength); if (bhSignLoaded) { if (memcmp(bHsignature, bHsignaturetmp, signatureLength) != 0) { LOG_ERROR("Authentication Error !!!\n Loaded BH Signature does not match calculated BH Signature"); } } memcpy(ptr, bHsignaturetmp, signatureLength); } else if (bhSignLoaded) { memcpy(ptr, bHsignature, signatureLength); } else if (bi.options.DoGenerateHashes() && !bhSignLoaded) { static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("Either SSK or (bhsignature and presign) is needed to authenticate a boot image or generate partition hashes. Because they are not provided, the bootimage and partition hashes will not be usable. However, the boot header hash file generated can be used for offline signing"); warningGiven = true; } } else { LOG_ERROR("Authentication Error !!!\n Either Secret Key Pair or BH signature file must be specified in BIF file"); } // Clean up if (sha_hash_padded) { delete[] sha_hash_padded; } if (bHsignaturetmp) { delete[] bHsignaturetmp; } LOG_TRACE("Boot Header Signature copied into Authentication Certificate"); } /******************************************************************************/ void VersalAuthenticationContext::CopyIHTSignature(BootImage & bi, uint8_t * ptr) { uint8_t* sha_hash_padded = new uint8_t[signatureLength]; uint8_t* signaturetmp = new uint8_t[signatureLength]; memset(signaturetmp, 0, signatureLength); memset(sha_hash_padded, 0, signatureLength); GenerateIHTHash(bi, sha_hash_padded); if (bi.options.DoGenerateHashes()) { std::string hashfilename = "imageheadertable" + hash->GetHashFileExtension(); WritePaddedSHAFile(sha_hash_padded, hashfilename); } if (primaryKey->Loaded && primaryKey->isSecret) { LOG_TRACE("Creating Image Header Table Signature"); if (authAlgorithm->Type() != Authentication::ECDSA) { authAlgorithm->RearrangeEndianess(sha_hash_padded, signatureLength); } authAlgorithm->CreateSignature(sha_hash_padded, (uint8_t*)secondaryKey, signaturetmp); if (authAlgorithm->Type() != Authentication::ECDSA) { authAlgorithm->RearrangeEndianess(signaturetmp, signatureLength); } /* if (bhSignLoaded) { if (memcmp(bHsignature, bHsignaturetmp, rsaKeyLength) != 0) { LOG_ERROR("Authentication Error !!!\n Loaded BH Signature does not match calculated BH Signature"); } } */ memcpy(ptr, signaturetmp, signatureLength); } else if (bi.bifOptions->GetHeaderSignatureFile() != "") { GetPresign(bi.bifOptions->GetHeaderSignatureFile(), signaturetmp, 0); memcpy(ptr, signaturetmp, signatureLength); } else if (bi.options.DoGenerateHashes() && (bi.bifOptions->GetHeaderSignatureFile() == "")) { static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("Either SSK or presign) is needed to authenticate a boot image or generate partition hashes. Because they are not provided, the bootimage and partition hashes will not be usable. However, the boot header hash file generated can be used for offline signing"); warningGiven = true; } } else { LOG_ERROR("Authentication Error !!!\n Either Secret Key Pair or BH signature file must be specified in BIF file"); } // Clean up if (sha_hash_padded) { delete[] sha_hash_padded; } if (signaturetmp) { delete[] signaturetmp; } LOG_TRACE("Image Header Table Signature copied into Authentication Certificate"); } /******************************************************************************/ void RSA4096Sha3PaddingAuthenticationAlgorithm::CreateSignature(const uint8_t* base, uint8_t* primaryKey, uint8_t* result0) { AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); RSA_Exponentiation(base, ((VersalKey*) primaryKey)->N, ((VersalKey*) primaryKey)->N_ext, ((VersalKey*) primaryKey)->D, result0); } /******************************************************************************/ void ECDSAAuthenticationAlgorithm::CreateSignature(const uint8_t* base, uint8_t* primaryKey, uint8_t* result0) { ECDSASignature(base, ((VersalKey*)primaryKey)->eckey, result0); } /******************************************************************************/ void ECDSAP521AuthenticationAlgorithm::CreateSignature(const uint8_t* base, uint8_t* primaryKey, uint8_t* result0) { ECDSASignature(base, ((VersalKey*)primaryKey)->eckey, result0); } /******************************************************************************/ void VersalAuthenticationContext::GenerateIHTHash(BootImage& bi, uint8_t* sha_hash_padded) { LOG_TRACE("Calculating Image Header Table Hash"); uint8_t* tmpIht = bi.imageHeaderTable->section->Data; uint8_t* sha_hash = new uint8_t[hashLength]; hash->CalculateVersalHash(true,tmpIht, bi.imageHeaderTable->section->Length, sha_hash); authAlgorithm->CreatePadding(sha_hash_padded, sha_hash, hashLength); delete[] sha_hash; } /******************************************************************************/ void VersalAuthenticationContext::GenerateBHHash(BootImage& bi, uint8_t* sha_hash_padded) { LOG_TRACE("Calculating the Boot Header Hash"); /* Donot include SMAP data to calculate BH hash */ uint8_t* tmpBh = bi.bootHeader->section->Data + 0x10; uint8_t* sha_hash = new uint8_t[hashLength]; hash->CalculateVersalHash(false, tmpBh, bi.bootHeader->section->Length, sha_hash); authAlgorithm->CreatePadding(sha_hash_padded, sha_hash, hashLength); delete[] sha_hash; } /******************************************************************************/ void VersalAuthenticationContext::GenerateSPKHash(uint8_t* sha_hash_padded) { LOG_TRACE("Calculating the SPK Hash"); uint8_t* spkFull = new uint8_t[VERSAL_ACKEY_STRUCT_SIZE]; uint8_t spkSHA3Padding[4] = { 0,0,0,0 }; FillSha3Padding(spkSHA3Padding, sizeof(spkSHA3Padding)); if (!secondaryKey->Loaded) { ParseSPKeyFile(spkFile); } secondaryKey->Export(spkFull); hashLength = hash->GetHashLength(); uint8_t* shaHash = new uint8_t[hashLength]; uint32_t acHdr = authAlgorithm->GetAuthHeader(); acHdr |= ((hashType == AuthHash::Sha2) ? 0 : 1) << AC_HDR_SHA_2_3_BIT_SHIFT; uint8_t* tempBuffer = new uint8_t[VERSAL_ACKEY_STRUCT_SIZE + sizeof(acHdr) + sizeof(spkIdentification) + sizeof(spkSHA3Padding)]; WriteLittleEndian32(tempBuffer, acHdr); WriteLittleEndian32(tempBuffer + sizeof(acHdr), spkIdentification); authAlgorithm->RearrangeEndianess(spkFull+ RSA_4096_N, RSA_4096_N_SIZE); authAlgorithm->RearrangeEndianess(spkFull+ RSA_4096_N_EXT, RSA_4096_N_EXT_SIZE); authAlgorithm->RearrangeEndianess(spkFull+RSA_4096_E, RSA_4096_E_SIZE); memcpy(tempBuffer + sizeof(acHdr) + sizeof(spkIdentification), (uint8_t*)spkFull, VERSAL_ACKEY_STRUCT_SIZE); memcpy(tempBuffer + sizeof(acHdr) + sizeof(spkIdentification) + VERSAL_ACKEY_STRUCT_SIZE, spkSHA3Padding, sizeof(spkSHA3Padding)); hash->CalculateVersalHash(false,(uint8_t*)tempBuffer, VERSAL_ACKEY_STRUCT_SIZE + sizeof(acHdr) + sizeof(spkIdentification) + sizeof(spkSHA3Padding), shaHash); // Create PKCS padding authAlgorithm->CreatePadding(sha_hash_padded, shaHash, hashLength); delete[] shaHash; delete[] tempBuffer; } /******************************************************************************/ void VersalAuthenticationContext::CopySPKSignature(uint8_t* ptr) { CreateSPKSignature(); LOG_TRACE("Copying the SPK signature into the Authentication Certificate"); memcpy(ptr, spksignature, signatureLength); } /******************************************************************************/ std::string VersalAuthenticationContext::GetCertificateName(std::string name) { if (certIndex != 0) { size_t x = name.find(".0"); if (std::string::npos != name.find(".0")) { name[x + 1] = (char)(name[x + 1] + certIndex); // nudge the '0' to '1' ... '9'. } } return name; } /******************************************************************************/ void VersalAuthenticationContext::GeneratePPKHash(const std::string& filename) { int ppkSize = VERSAL_ACKEY_STRUCT_SIZE; uint8_t* ppkTemp = new uint8_t[ppkSize]; hashLength = hash->GetHashLength(); primaryKey->Export(ppkTemp); authAlgorithm->RearrangeEndianess(ppkTemp + RSA_4096_N, RSA_4096_N_SIZE); authAlgorithm->RearrangeEndianess(ppkTemp + RSA_4096_N_EXT, RSA_4096_N_EXT_SIZE); authAlgorithm->RearrangeEndianess(ppkTemp + RSA_4096_E, RSA_4096_E_SIZE); uint8_t ppkSHA3Padding[12] = { 0 }; FillSha3Padding(ppkSHA3Padding, sizeof(ppkSHA3Padding)); uint8_t* tempBuffer = new uint8_t[ppkSize + sizeof(ppkSHA3Padding)]; memcpy(tempBuffer, (uint8_t*)ppkTemp, ppkSize); memcpy(tempBuffer + ppkSize, ppkSHA3Padding, sizeof(ppkSHA3Padding)); uint8_t* ppkHash = new uint8_t[hashLength]; hash->CalculateVersalHash(false,tempBuffer, ppkSize + sizeof(ppkSHA3Padding), ppkHash); FILE* filePtr; if ((filePtr = fopen(filename.c_str(), "w")) == NULL) { LOG_ERROR("-efuseppkbits error !!! Failure writing to hash file %s", StringUtils::BaseName(filename).c_str()); } /* For Versal, the efuses are available only for 256 bits. So the upper 256 bits(0x20 bytes) of the hash is dumped, which will be programmed to efuse.*/ for (int index = 0; index < 0x20; index++) { fprintf(filePtr, "%02X", ppkHash[index]); } fprintf(filePtr, "\r\n"); fclose(filePtr); LOG_INFO("Efuse PPK bits written to file %s successfully", filename.c_str()); delete[] tempBuffer; } /******************************************************************************/ void RSA4096Sha3PaddingAuthenticationAlgorithm::CreatePadding(uint8_t * signature, uint8_t * hash, uint8_t hashLength) { /* RSA PSS Padding */ char* rsaLocalENV = getenv("TEST_RSA_LOCAL"); int hLen = hashLength; uint8_t padding1[PAD1_LENGTH]; memset(padding1, 0, PAD1_LENGTH); uint8_t padding2[PAD2_LENGTH]; memset(padding2, 0, PAD2_LENGTH); padding2[PAD2_LENGTH - 1] |= 0x01; //Set the leftmost 8emLen - emBits bits of the leftmost octet in maskedDB to zero int MSBits = ((SIGN_LENGTH_VERSAL * 8) - 1) & 0x7; int emLen = SIGN_LENGTH_VERSAL; if (MSBits == 0) { emLen--; } uint8_t *salt = NULL; salt = new uint8_t[SALT_LENGTH]; if (rsaLocalENV != NULL) { uint8_t defsalt[SALT_LENGTH] = { 0x71, 0x5d, 0x74, 0xeb, 0x06, 0xcb, 0x2f, 0xfa, 0xed, 0x09, 0x3d, 0xd3, 0x9b, 0xa0, 0xb8, 0x57, 0xa3, 0x01, 0xcd, 0xd7, 0x52, 0x2a, 0x82, 0xc9, 0x71, 0x06, 0x8a, 0x6b, 0xb1, 0x99, 0x83, 0x52, 0x49, 0x49, 0x2b, 0xdb, 0xc8, 0x50, 0x20, 0x5e, 0x44, 0xb2, 0xc8, 0xbe, 0xbf, 0x77, 0x98, 0x22 }; memcpy(salt, defsalt, SALT_LENGTH); } else { RAND_bytes(salt, SALT_LENGTH); } //calculate mHash - hash on message(m) uint8_t mHash[48] = { 0 }; memcpy(mHash, hash, 48); //calculate mPad - add padding1 and salt to mHash uint8_t mPad[104]; memset(mPad, 0, 104); memcpy(mPad, padding1, PAD1_LENGTH); memcpy(mPad + PAD1_LENGTH, mHash, 48); memcpy(mPad + PAD1_LENGTH + 48, salt, SALT_LENGTH); //calculate hash on mPad uint8_t *m1; uint8_t mPadHash[48]; m1 = AttachSHA3Padding(mPad, 104); Versalcrypto_hash(mPadHash, m1, 208, false); int maskedDBLen = emLen - hLen - 1; //463 uint8_t mask[463] = { 0 }; if (MaskGenerationFunction(mask, maskedDBLen, mPadHash, 48, EVP_sha384()) == -1) { LOG_ERROR("Internal Error : Mask generation failed during authentication."); } //DB Padding uint8_t *DB; DB = new uint8_t[463]; memset(DB, 0x0, 463); memcpy(DB, padding2, PAD2_LENGTH); memcpy(DB + PAD2_LENGTH, salt, 48); uint8_t EM[512] = { 0 }; for (int i = 0; i < 463; i++) { EM[i] = (mask[i] ^ DB[i]); } if (MSBits == 0) { EM[0] = 0; } if (MSBits) EM[0] &= 0xFF >> (8 - MSBits); memcpy(EM + 463, mPadHash, 48); EM[512 - 1] = 0xbc; memcpy(signature, EM, 512); delete[] m1; delete[] DB; delete[] salt; } /******************************************************************************/ void ECDSAAuthenticationAlgorithm::CreatePadding(uint8_t * signature, uint8_t * hash, uint8_t hashLength) { memcpy(signature, hash, hashLength); } /******************************************************************************/ void ECDSAP521AuthenticationAlgorithm::CreatePadding(uint8_t * signature, uint8_t * hash, uint8_t hashLength) { memcpy(signature, hash, hashLength); } /******************************************************************************/ void VersalAuthenticationContext::CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection) { LOG_TRACE("Copying the partition (%s) signature into Authentication Certificate", acSection->Name.c_str()); /* calculate hash first */ uint8_t* shaHash = new uint8_t[hashLength]; std::list::iterator section = sections.begin(); size_t hashSecLen = (*section)->Length; //If !bootloader AND !headers if ((*section)->firstChunkSize != 0 && !((*section)->isBootloader && !bi.options.IsVersalNetSeries()) && (*section)->isPartitionData) { hashSecLen = (*section)->firstChunkSize + hashLength; } /* Update with AC and then Partition */ int signSecLength = acSection->Length - signatureLength; /*Remove the IHT signature length from sign section in case of auth optimization*/ if (bi.options.IsAuthOptimizationEnabled() && (*section)->Name == "Headers") { signSecLength -= signatureLength; (*section)->partitionNum = 0x00; } uint8_t *partitionAc = new uint8_t[hashSecLen + signSecLength]; /* Update with authentication certificate except the last 256 bytes - which is the partition signature that we are calculating now. Once calculated, the partition signature will sit there */ memcpy(partitionAc, acSection->Data, signSecLength); /* Update with Partition */ memcpy(partitionAc + signSecLength, (*section)->Data, hashSecLen); /* Calculate the final hash */ Versalcrypto_hash(shaHash, partitionAc, hashSecLen + signSecLength, !((*section)->isBootloader && !bi.options.IsVersalNetSeries())); LOG_TRACE("Hash of %s (LE):", acSection->Name.c_str()); LOG_DUMP_BYTES(shaHash, hashLength); if (bi.options.IsAuthOptimizationEnabled() && !((*section)->isBootloader)) { uint8_t* hash = new uint8_t[hashLength]; bi.hashTable.push_back(std::pair((*section)->partitionNum, hash)); memcpy(hash, shaHash, hashLength); } /* Create the PKCS padding for the hash */ uint8_t* shaHashPadded = new uint8_t[signatureLength]; memset(shaHashPadded, 0, signatureLength); authAlgorithm->CreatePadding(shaHashPadded, shaHash, hashLength); /* Generate hashes, if requested from command line option "-generate_hashes" */ if (bi.options.DoGenerateHashes()) { std::string hashfilename = acSection->Name; WritePaddedSHAFile(shaHashPadded, hashfilename); } authAlgorithm->RearrangeEndianess(shaHashPadded, signatureLength); /* Now sign the hash */ authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)secondaryKey, signatureBlock); authAlgorithm->RearrangeEndianess(signatureBlock, signatureLength); LOG_TRACE("The partition signature is copied into Authentication Certificate"); /* Delete the temporarily created arrays */ delete[] shaHash; delete[] shaHashPadded; acIndex++; } /******************************************************************************/ void RSA4096Sha3PaddingAuthenticationAlgorithm::RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; // If array is NULL, return if (!array) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /******************************************************************************/ void ECDSAAuthenticationAlgorithm::RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; // If array is NULL, return if (!array) { return; } if (size != UDF_DATA_SIZE && (size != EC_P384_KEY_LENGTH)) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /******************************************************************************/ void ECDSAP521AuthenticationAlgorithm::RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; // If array is NULL, return if (!array) { return; } if (size != UDF_DATA_SIZE && size != EC_P521_KEY_LENGTH1 && size != EC_P521_KEY_LENGTH2) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /******************************************************************************/ void ECDSAAuthenticationAlgorithm::ECDSASignature(const uint8_t *base, EC_KEY *eckeyU, uint8_t *result0) { EC_KEY* eckeyN = EC_KEY_new(); EC_GROUP* ecgroup = EC_GROUP_new_by_curve_name(NID_secp384r1); EC_KEY_set_group(eckeyN, ecgroup); EC_KEY_set_asn1_flag(eckeyN, OPENSSL_EC_NAMED_CURVE); const BIGNUM* prv = BN_new(); prv = EC_KEY_get0_private_key(eckeyU); const EC_POINT *pub = EC_KEY_get0_public_key(eckeyU); /* add the private & public key to the EC_KEY structure */ EC_KEY_set_private_key(eckeyN, prv); EC_KEY_set_public_key(eckeyN, pub); /* create and verify signature */ ECDSA_SIG* signature = ECDSA_do_sign(base, 48, eckeyN); #if 0 if (1 != ECDSA_do_verify(base, 48, signature, eckeyN)) { LOG_ERROR("Failed to verify EC Signature\n"); } else { LOG_TRACE("Verified EC Signature\n"); } #endif if (signature != NULL) { #if OPENSSL_VERSION_NUMBER > 0x10100000L const BIGNUM *sig_r = NULL, *sig_s = NULL; ECDSA_SIG_get0(signature, &sig_r, &sig_s); memcpy(result0, sig_r->d, EC_P384_KEY_LENGTH); RearrangeEndianess(result0, EC_P384_KEY_LENGTH); memcpy(result0 + EC_P384_KEY_LENGTH, sig_s->d, EC_P384_KEY_LENGTH); RearrangeEndianess(result0 + EC_P384_KEY_LENGTH, EC_P384_KEY_LENGTH); #else memcpy(result0, signature->r->d, EC_P384_KEY_LENGTH); RearrangeEndianess(result0, EC_P384_KEY_LENGTH); memcpy(result0 + EC_P384_KEY_LENGTH, signature->s->d, EC_P384_KEY_LENGTH); RearrangeEndianess(result0 + EC_P384_KEY_LENGTH, EC_P384_KEY_LENGTH); #endif } EC_GROUP_free(ecgroup); EC_KEY_free(eckeyN); ECDSA_SIG_free(signature); } /******************************************************************************/ void ECDSAP521AuthenticationAlgorithm::ECDSASignature(const uint8_t *base, EC_KEY *eckeyU, uint8_t *result0) { EC_KEY* eckeyN = EC_KEY_new(); EC_GROUP* ecgroup = EC_GROUP_new_by_curve_name(NID_secp521r1); EC_KEY_set_group(eckeyN, ecgroup); EC_KEY_set_asn1_flag(eckeyN, OPENSSL_EC_NAMED_CURVE); const BIGNUM* prv = BN_new(); prv = EC_KEY_get0_private_key(eckeyU); const EC_POINT *pub = EC_KEY_get0_public_key(eckeyU); /* add the private & public key to the EC_KEY structure */ EC_KEY_set_private_key(eckeyN, prv); EC_KEY_set_public_key(eckeyN, pub); /* create and verify signature */ ECDSA_SIG* signature = ECDSA_do_sign(base, 48, eckeyN); #if 0 if (1 != ECDSA_do_verify(base, 48, signature, eckeyN)) { LOG_ERROR("Failed to verify EC Signature\n"); } else { LOG_TRACE("Verified EC Signature\n"); } #endif if (signature != NULL) { uint8_t *x1 = new uint8_t[EC_P521_KEY_LENGTH2]; uint8_t *y1 = new uint8_t[EC_P521_KEY_LENGTH2]; memset(x1, 0, EC_P521_KEY_LENGTH2); memset(y1, 0, EC_P521_KEY_LENGTH2); uint32_t signSzR; uint32_t signSzS; #if OPENSSL_VERSION_NUMBER > 0x10100000L const BIGNUM *sig_r = NULL, *sig_s = NULL; ECDSA_SIG_get0(signature, &sig_r, &sig_s); signSzR = BN_num_bytes(sig_r); signSzS = BN_num_bytes(sig_s); if (signSzR == EC_P521_KEY_LENGTH1) { memcpy(x1 + 1, sig_r->d, signSzR); RearrangeEndianess(x1 + 1, signSzR); } else { memcpy(x1, sig_r->d, signSzR); RearrangeEndianess(x1, signSzR); } if (signSzS == EC_P521_KEY_LENGTH1) { memcpy(y1 + 1, sig_s->d, signSzS); RearrangeEndianess(y1 + 1, signSzS); } else { memcpy(y1, sig_s->d, signSzS); RearrangeEndianess(y1, signSzS); } memcpy(result0, x1, EC_P521_KEY_LENGTH2); memcpy(result0 + EC_P521_KEY_LENGTH2, y1, EC_P521_KEY_LENGTH2); #else signSzR = BN_num_bytes(signature->r); signSzS = BN_num_bytes(signature->s); if (signSzR == EC_P521_KEY_LENGTH1) { memcpy(x1 + 1, signature->r->d, signSzR); RearrangeEndianess(x1 + 1, signSzR); } else { memcpy(x1, signature->r->d, signSzR); RearrangeEndianess(x1, signSzR); } if (signSzS == EC_P521_KEY_LENGTH1) { memcpy(y1 + 1, signature->s->d, signSzS); RearrangeEndianess(y1 + 1, signSzS); } else { memcpy(y1, signature->s->d, signSzS); RearrangeEndianess(y1, signSzS); } memcpy(result0, x1, EC_P521_KEY_LENGTH2); memcpy(result0 + EC_P521_KEY_LENGTH2, y1, EC_P521_KEY_LENGTH2); #endif if (x1 != NULL) { delete[] x1; } if (y1 != NULL) { delete[] y1; } } EC_GROUP_free(ecgroup); EC_KEY_free(eckeyN); ECDSA_SIG_free(signature); } /******************************************************************************/ void VersalAuthenticationContext::AddAuthCertSizeToTotalFSBLSize(PartitionHeader* header) { for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { if (*acs && (*acs)->section) { if (header->imageHeader->IsBootloader() == true) { header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + (*acs)->section->Length); } } } } /******************************************************************************/ void VersalAuthenticationContext::GetPresign(const std::string& presignFilename, uint8_t* signature, uint32_t index) { std::string filename(presignFilename); std::string baseFile = StringUtils::BaseName(filename); if (index > 9) { LOG_DEBUG(DEBUG_STAMP, "Partition index count %d too high", index); LOG_ERROR("Presign file should have proper index (0-9)"); } if (index != 0) { size_t x = filename.find(".0."); if (x == std::string::npos) { LOG_ERROR("Presign file %s does not have partition index (*.0.*)", baseFile.c_str()); } filename[x + 1] = (char)(filename[x + 1] + index); // nudge the '0' to '1' ... '9'. } LOG_TRACE("Reading presign file - %s", filename.c_str()); FILE* filePtr; filePtr = fopen(filename.c_str(), "rb"); if (filePtr) { fseek(filePtr, 0, SEEK_END); // non-portable long size = ftell(filePtr); fclose(filePtr); if (size == SIGN_LENGTH_VERSAL) { // read binary filePtr = fopen(filename.c_str(), "rb"); long read_size = fread(signature, 1, SIGN_LENGTH_VERSAL, filePtr); if (read_size != SIGN_LENGTH_VERSAL) { LOG_ERROR("Authentication Error !!!\n Presign file %s should be of %d bytes", baseFile.c_str(), SIGN_LENGTH_VERSAL); } fclose(filePtr); } else { // read ascii filePtr = fopen(filename.c_str(), "r"); for (int i = 0; iLoaded && primaryKey->isSecret) { uint8_t* shaHashPadded = new uint8_t[signatureLength]; uint8_t* spkSignatureTemp = new uint8_t[signatureLength]; memset(shaHashPadded, 0, signatureLength); memset(spkSignatureTemp, 0, signatureLength); GenerateSPKHash(shaHashPadded); authAlgorithm->RearrangeEndianess(shaHashPadded, signatureLength); authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)primaryKey, spkSignatureTemp); authAlgorithm->RearrangeEndianess(spkSignatureTemp, signatureLength); LOG_INFO("SPK Signature generated successfully"); if (filename != "") { FILE* filePtr; filePtr = fopen(filename.c_str(), "w"); if (filePtr) { for (uint32_t i = 0; iLength + 63) & 0xFFFFFFC0; section->IncreaseLengthAndPadTo(dataSizePadded, 0xFF); } /******************************************************************************/ void VersalAuthenticationContext::LoadUdfData(const std::string& udfFilename, uint8_t* signature) { std::string filename(udfFilename); std::string baseFile = StringUtils::BaseName(udfFilename); FILE* filePtr; int datum, ret, nbytes; nbytes = 0; filePtr = fopen(filename.c_str(), "r"); if (filePtr) { while ((ret = fscanf(filePtr, "%2X", &datum)) != EOF) { if (ret == 1) { if (datum < 0 || datum > 255) { LOG_ERROR("Bad hex conversion %x - %s", datum, baseFile.c_str()); } if (nbytes == UDF_DATA_SIZE) { LOG_ERROR("More than %d bytes in the UDF Data file %s is not allowed.", UDF_DATA_SIZE, baseFile.c_str()); } signature[nbytes++] = datum; } else { LOG_ERROR("Failure reading UDF file - %s", baseFile.c_str()); } } } else { LOG_ERROR("Failure opening UDF file - %s", baseFile.c_str()); } fclose(filePtr); LOG_TRACE("UDF data is loaded successfully in the Authentication Certificate from file - %s", udfFilename.c_str()); } /******************************************************************************/ void VersalAuthenticationContext::CreateSPKSignature(void) { LOG_TRACE("Creating the SPK signature"); /* SPK is signed with PSK (Primary Secret Key) Check if PSK is given */ if (primaryKey->Loaded && primaryKey->isSecret) { uint8_t* shaHashPadded = new uint8_t[signatureLength]; memset(shaHashPadded, 0, signatureLength); memset(spksignature, 0, signatureLength); // Calulate the SPK hash with PKCS padding GenerateSPKHash(shaHashPadded); authAlgorithm->RearrangeEndianess(shaHashPadded, signatureLength); // Sign the SPK hash authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)primaryKey, spksignature); authAlgorithm->RearrangeEndianess(spksignature, signatureLength); delete[] shaHashPadded; } /* If SPK signature file or PSK is not given in BIF file, cannot get SPK signature for the auth certificate Throw error */ else if (!spkSignLoaded) { LOG_ERROR("Authentication Error !!!\n PSK or SPK signature missing, must specify atleast one"); } LOG_INFO("SPK signature created successfully"); } /******************************************************************************/ uint32_t ECDSAAuthenticationAlgorithm::GetAuthHeader(void) { return AUTH_HDR_VERSAL_ECDSA; } /******************************************************************************/ uint32_t ECDSAP521AuthenticationAlgorithm::GetAuthHeader(void) { return AUTH_HDR_VERSAL_ECDSA_P521; } /******************************************************************************/ uint32_t RSA4096Sha3PaddingAuthenticationAlgorithm::GetAuthHeader(void) { return AUTH_HDR_VERSAL; } /******************************************************************************/ void static SetDeviceDNA(const uint8_t* dnaValue, uint32_t* deviceDNA) { for (uint32_t index = 0; index < WORDS_PER_DEVICE_DNA; index++) { deviceDNA[WORDS_PER_DEVICE_DNA - (index+1)] = ReadBigEndian32(dnaValue); dnaValue += sizeof(uint32_t); } } /******************************************************************************/ void VersalAuthenticationContext::CreateAuthJtagImage(uint8_t* buffer, AuthJtagInfo authJtagAttributes) { LOG_TRACE("Creating the Authentication Header signature"); AuthenticatedJtagImageStructure* authJtagImage = (AuthenticatedJtagImageStructure*)buffer; if (primaryKey->Loaded && primaryKey->isSecret) { hashLength = hash->GetHashLength(); uint8_t* shaHash = new uint8_t[hashLength]; uint8_t* shaHashPadded = new uint8_t[signatureLength]; memset(shaHash, 0, hashLength); memset(shaHashPadded, 0, signatureLength); uint32_t acHdr = authAlgorithm->GetAuthHeader(); acHdr |= ((hashType == AuthHash::Sha2) ? 0 : 1) << AC_HDR_SHA_2_3_BIT_SHIFT; WriteLittleEndian32(&authJtagImage->acHeader, acHdr); if (!authJtagAttributes.userRevokeId) { LOG_WARNING("revoke_id is not specified in BIF, default revoke id is assigned as '0'."); } WriteLittleEndian32(&authJtagImage->spkId, authJtagAttributes.revokeId); authJtagInfoStructurev2* v2 = (authJtagInfoStructurev2*)authJtagImage->authJtagInfo; if (authJtagAttributes.userDeviceDNA) { WriteLittleEndian32(&v2->attributes, vauthJtagMessagenMask << vauthJtagMessageShift); } SetDeviceDNA(authJtagAttributes.deviceDNA, (uint32_t*)v2->deviceDNA); WriteLittleEndian32(&v2->jtagTimeOut, authJtagAttributes.jtagTimeout); FillSha3Padding(v2->SHA3Padding, sizeof(v2->SHA3Padding)); primaryKey->Export(authJtagImage->acPpk); authAlgorithm->RearrangeEndianess(authJtagImage->acPpk + RSA_4096_N, RSA_4096_N_SIZE); authAlgorithm->RearrangeEndianess(authJtagImage->acPpk + RSA_4096_N_EXT, RSA_4096_N_EXT_SIZE); authAlgorithm->RearrangeEndianess(authJtagImage->acPpk + RSA_4096_E, RSA_4096_E_SIZE); FillSha3Padding(authJtagImage->ppkSHA3Padding, sizeof(authJtagImage->ppkSHA3Padding)); hash->CalculateVersalHash(false, (uint8_t*)authJtagImage, sizeof(authJtagImage->acHeader) + sizeof(authJtagImage->spkId) + sizeof(authJtagImage->authJtagInfo), shaHash); authAlgorithm->CreatePadding(shaHashPadded, shaHash, hashLength); authAlgorithm->RearrangeEndianess(shaHashPadded, signatureLength); authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)primaryKey, authJtagImage->authJtagSignature); authAlgorithm->RearrangeEndianess(authJtagImage->authJtagSignature, signatureLength); memset(authJtagImage->padto2KB, 0, sizeof(authJtagImage->padto2KB)); delete[] shaHash; delete[] shaHashPadded; } else { LOG_ERROR("Authentication Error !!!\n PSK must be specified to generate Authenticated Jtag Image"); } } /******************************************************************************/ void VersalAuthenticationCertificate::Link(BootImage& bi, Section* dataSection) { /* Gather up all the sections that will be used to calculate the authentication hash */ std::list sections; Section* headers = NULL; /* If the section is a header table section */ if (isTableHeader) { size_t size = 0; if (bi.options.bifOptions->GetHeaderEncyption()) { size = bi.encryptedHeaders->Length; headers = new Section("Headers", size); memset(headers->Data, bi.options.GetOutputFillByte(), headers->Length); memcpy(headers->Data, bi.encryptedHeaders->Data, bi.encryptedHeaders->Length); sections.push_back(headers); } else { if (bi.createSubSystemPdis == true) { for (std::list::iterator image = bi.subSysImageList.begin(); image != bi.subSysImageList.end(); image++) { sections.push_back((*image)->section); size += sizeof(VersalImageHeaderStructure); } } else { for (std::list::iterator img = bi.imageList.begin(); img != bi.imageList.end(); img++) { sections.push_back((*img)->section); size += sizeof(VersalImageHeaderStructure); } } // Append all partition headers for (std::list::iterator part = bi.partitionHeaderList.begin(); part != bi.partitionHeaderList.end(); part++) { sections.push_back((*part)->section); size += sizeof(VersalPartitionHeaderTableStructure); } // Append NULL partition header //sections.push_back(bi.nullPartHeaderSection); /* Create one new combined section will all the appended sections above */ headers = new Section("Headers", size); //headers->Address = iHT->section->Address; // not really needed, but useful for debug. memset(headers->Data, bi.options.GetOutputFillByte(), headers->Length); Binary::Address_t start = sections.front()->Address; for (SectionList::iterator i = sections.begin(); i != sections.end(); i++) { Section& section(**i); int offset = section.Address - start; memcpy(headers->Data + offset, section.Data, section.Length); } // replace sections list with the combined new section sections.clear(); sections.push_back(headers); } } // If section is a partition section else { Section* bHSec = AttachBootHeaderToFsbl(bi); if (bHSec != NULL) { sections.push_back(bHSec); } else { sections.push_back(dataSection); } } // Link the certificate - pass for signing this->AuthContext->Link(bi, sections, this); if (headers != NULL) { delete headers; } } /******************************************************************************/ void VersalAuthenticationContext::SetKeyLength(Authentication::Type type) { if (type == Authentication::RSA) { AuthenticationContext::authKeyLength = RSA_4096_KEY_LENGTH; } else if (type == Authentication::ECDSA) { AuthenticationContext::authKeyLength = EC_P384_KEY_LENGTH; } else if (type == Authentication::ECDSAp521) { //AuthenticationContext::authKeyLength = EC_P521_KEY_LENGTH; } } xilinx-bootgen-2024.2/authentication-versal.h000077500000000000000000000266421475706442400212650ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _VERSAL_AUTHENTICATION_CONTEXT_H_ #define _VERSAL_AUTHENTICATION_CONTEXT_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include "binary.h" #include "baseclass.h" #include "bootgenenum.h" #include #include #include #include #include "authkeys-versal.h" #include "hash.h" #include "systemutils.h" #include "authentication.h" #include "bifoptions.h" /* Forward class references */ class BaseThing; class Section; class BootImage; class Binary; class AuthenticationCertificate; class PartitionHeader; class Key; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define AC_SHA3_PADDING_SIZE 64 #define PAD1_LENGTH 8 #define PAD2_LENGTH 415 #define SALT_LENGTH 48 #define AUTH_HDR_VERSAL 0x115 #define AUTH_HDR_VERSAL_ECDSA 0x106 #define AUTH_HDR_VERSAL_ECDSA_P521 0x126 #define AC_HDR_PPK_SELECT_BIT_SHIFT 16 #define AC_HDR_SHA_2_3_BIT_SHIFT 2 #define SHA3_PAD_LENGTH 104 #define WORDS_PER_DEVICE_DNA 4 //Auth Certificate offset defines #define AC_HEADER_OFFSET 0x0 #define AC_SPK_ID_OFFSET 0x4 #define AC_UDF_OFFSET 0x8 #define AC_PPK_KEY_OFFSET 0x40 #define AC_PPK_SHA3PAD_OFFSET 0x444 #define AC_SPK_KEY_OFFSET 0x450 #define AC_SPK_SHA3PAD_OFFSET 0x854 #define AC_ALLIGNMENT_OFFSET 0x858 #define AC_SPK_SIGN_OFFSET 0x860 #define AC_BH_SIGN_OFFSET 0xa60 #define AC_PARTITION_SIGN_OFFSET 0xc60 #define AC_PPK_SHA3PAD_SIZE 12 #define AC_SPK_SHA3PAD_SIZE 4 #define AC_ALLIGNMENT_SIZE 12 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef enum { vauthJtagMessageShift = 0, vauthJtagMessagenMask = 0x3, } AuthJtagAttributes; typedef struct { uint32_t acHeader; // 0x000 uint32_t spkId; // 0x004 uint8_t acUdf[UDF_DATA_SIZE]; // 0x008 ACKey4096Sha3Padding acPpk; // 0x040 uint8_t ppkSHA3Padding[12]; // 0x444 ACKey4096Sha3Padding acSpk; // 0x450 uint8_t spkSHA3Padding[4]; // 0x854 uint8_t allignment[8]; // 0x858 ACSignature4096 acSpkSignature; // 0x860 ACSignature4096 acHeaderSignature; // 0xA60 ACSignature4096 acPartitionSignature; // 0xC60 } AuthCertificate4096Sha3PaddingStructure; /* ECDSA Authentication Certificate */ typedef struct { uint32_t acHeader; // 0x000 uint32_t spkId; // 0x004 uint8_t acUdf[UDF_DATA_SIZE]; // 0x008 ACKeyECDSA acPpk; // 0x040 uint8_t ppkSHA3Padding[12]; // 0x444 ACKeyECDSA acSpk; // 0x450 uint8_t spkSHA3Padding[4]; // 0x854 uint8_t allignment[8]; // 0x858 ACSignatureECDSA acSpkSignature; // 0x860 ACSignatureECDSA acHeaderSignature; // 0xA60 ACSignatureECDSA acPartitionSignature; // 0xC60 } AuthCertificateECDSAStructure; typedef struct { uint32_t acHeader; // 0x000 uint32_t spkId; // 0x004 uint8_t acUdf[UDF_DATA_SIZE]; // 0x008 ACKeyECDSAP521 acPpk; // 0x040 uint8_t ppkSHA3Padding[12]; // 0x444 ACKeyECDSAP521 acSpk; // 0x450 uint8_t spkSHA3Padding[4]; // 0x854 uint8_t allignment[8]; // 0x858 ACSignatureECDSA acSpkSignature; // 0x860 ACSignatureECDSA acHeaderSignature; // 0xA60 ACSignatureECDSA acPartitionSignature; // 0xC60 } AuthCertificateECDSAp521Structure; /* Authenticated-Jtag Image Structure */ typedef struct { uint32_t acHeader; //0x00 uint32_t spkId; //0x04 uint8_t authJtagInfo[96]; //0x08 uint8_t acPpk[VERSAL_ACKEY_STRUCT_SIZE]; //0x68 uint8_t ppkSHA3Padding[12]; //0x46C uint8_t authJtagSignature[SIGN_LENGTH_VERSAL]; //0x478 uint8_t padto2KB[392]; //0x678 /*CR-1143787 : Workaround for ROM*/ } AuthenticatedJtagImageStructure; //0x800 typedef struct { uint32_t attributes; //0x08 uint8_t deviceDNA[16]; //0x0C uint32_t jtagTimeOut; //0x1C uint8_t SHA3Padding[72]; //0x20 } authJtagInfoStructurev2; typedef struct { uint8_t SHA3Padding[96]; } authJtagInfoStructurev1; /******************************************************************************/ class ECDSAAuthenticationAlgorithm : public AuthenticationAlgorithm { public: ECDSAAuthenticationAlgorithm(); ~ECDSAAuthenticationAlgorithm(); Authentication::Type Type() { return Authentication::ECDSA; } int KeySize() { return sizeof(ACKeyECDSA); } void CreateSignature(const uint8_t *base, uint8_t* primaryKey, uint8_t *result0); uint32_t getCertificateSize() { return certSize; } void CreatePadding(uint8_t* signature, uint8_t* hash, uint8_t hashLength); void ECDSASignature(const uint8_t *base, EC_KEY *eckey, uint8_t *result0); Authentication::Type authType; void RearrangeEndianess(uint8_t *array, uint32_t size); uint32_t GetAuthHeader(void); private: uint32_t certSize; }; /******************************************************************************/ class ECDSAP521AuthenticationAlgorithm : public AuthenticationAlgorithm { public: ECDSAP521AuthenticationAlgorithm(); ~ECDSAP521AuthenticationAlgorithm(); Authentication::Type Type() { return Authentication::ECDSAp521; } int KeySize() { return sizeof(ACKeyECDSAP521); } void CreateSignature(const uint8_t *base, uint8_t* primaryKey, uint8_t *result0); uint32_t getCertificateSize() { return certSize; } void CreatePadding(uint8_t* signature, uint8_t* hash, uint8_t hashLength); void ECDSASignature(const uint8_t *base, EC_KEY *eckey, uint8_t *result0); Authentication::Type authType; void RearrangeEndianess(uint8_t *array, uint32_t size); uint32_t GetAuthHeader(void); private: uint32_t certSize; }; /******************************************************************************/ class RSA4096Sha3PaddingAuthenticationAlgorithm : public AuthenticationAlgorithm { public: RSA4096Sha3PaddingAuthenticationAlgorithm(); ~RSA4096Sha3PaddingAuthenticationAlgorithm(); Authentication::Type Type() { return Authentication::RSA; } void CreateSignature(const uint8_t *base, uint8_t* primaryKey, uint8_t *result0); uint32_t getCertificateSize(void) { return certSize; } void CreatePadding(uint8_t* signature, uint8_t* hash, uint8_t hashLength); Authentication::Type authType; void RearrangeEndianess(uint8_t* array, uint32_t size); uint8_t* AttachSHA3Padding(uint8_t * data, const Binary::Length_t datalength); int MaskGenerationFunction(unsigned char *mask, long len, const unsigned char *seed, long seedlen, const EVP_MD *dgst); uint32_t GetAuthHeader(void); private: uint32_t certSize; }; /******************************************************************************/ class VersalAuthenticationContext : public AuthenticationContext { public: VersalAuthenticationContext(Authentication::Type type); VersalAuthenticationContext(const AuthenticationContext* refAuthContext, Authentication::Type authtype); VersalAuthenticationContext(const AuthCertificate4096Sha3PaddingStructure* existingCert, Authentication::Type authtype); ~VersalAuthenticationContext(); void Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert); uint32_t getCertificateSize(void) { return certSize; } void AddAuthCertSizeToTotalFSBLSize(PartitionHeader* header); Section* CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection); void GenerateIHTHash(BootImage& bi, uint8_t* sha_hash_padded); void GenerateBHHash(BootImage& bi, uint8_t* sha_hash_padded); void GenerateSPKHash(uint8_t * sha_hash_padded); void GeneratePPKHash(const std::string& filename); void CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection); static void GetPresign(const std::string& presignFilename, uint8_t* signature, uint32_t index); void SetSPKSignatureFile(const std::string& filename); void SetBHSignatureFile(const std::string& filename); void GenerateSPKSignature(const std::string& filename); void ResizeIfNecessary(Section* section); void LoadUdfData(const std::string& filename, uint8_t* signature); void CreateSPKSignature(void); void CreateAuthJtagImage(uint8_t * buffer, AuthJtagInfo authJtagAttributes); void SetKeyLength(Authentication::Type type); AuthenticationAlgorithm* GetAuthenticationAlgorithm(Authentication::Type type); uint32_t GetCertificateSize(); void SetHashinOptionalData(BootImage& bi); private: void CopybHSignature(BootImage& bi, uint8_t* ptr); void CopyIHTSignature(BootImage& bi, uint8_t* ptr); uint32_t certSize; void CopySPKSignature(uint8_t* ptr); std::string GetCertificateName(std::string name); }; /******************************************************************************/ class VersalAuthenticationCertificate : public AuthenticationCertificate { public: VersalAuthenticationCertificate(AuthenticationContext* context) : AuthenticationCertificate(context) {} Section* AttachBootHeaderToFsbl(BootImage& bi) { return NULL; } void Link(BootImage& bi, Section* section); //AuthCertificate4096Sha3PaddingStructure *acStructure; }; #endif xilinx-bootgen-2024.2/authentication-zynq.cpp000077500000000000000000000350251475706442400213200ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "string.h" #include "authentication-zynq.h" #include "bootgenexception.h" #include "stringutils.h" #include "binary.h" #include "bootimage.h" #include "options.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void ZynqAuthenticationContext::CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection) { LOG_TRACE("Copying the partition signature into Authentication Certificate"); uint8_t* shaHash = new uint8_t[hashLength]; /* Calculate the length of the partiton that is to be hashed,Since bs is authenticated in chunks. This can be changed with authblock[default is 8].*/ std::list::iterator section = sections.begin(); size_t hashSecLen = (*section)->Length; size_t authblocksize = authBlocks * 1024 * 1024; if (authblocksize != 0) { hashSecLen = authblocksize; } if (((*section)->Length) - (authblocksize * acIndex) < authblocksize && (authBlocks != 0)) { hashSecLen = ((*section)->Length) - (authblocksize * acIndex); } uint8_t *partitionAc = new uint8_t[hashSecLen + (acSection->Length - signatureLength)]; /* Update with Partition */ memcpy(partitionAc, (*section)->Data + (authblocksize * acIndex), hashSecLen); /* Update with authentication certificate except the last 256 bytes, which is the partition signature, that we are calculating now. Once calculated, the partition signature will sit there */ memcpy(partitionAc + hashSecLen, acSection->Data, acSection->Length - signatureLength); uint32_t start = (*section)->Address; uint32_t end = (acSection->Address + acSection->Length) - signatureLength; LOG_TRACE("Hashing %s from 0x%x to 0x%x", acSection->Name.c_str(), start, end); LOG_DUMP_BYTES((*section)->Data + (authblocksize * acIndex), 32); LOG_OUT(" ... "); LOG_DUMP_BYTES((*section)->Data + (authblocksize * acIndex) + hashSecLen - hashLength, hashLength); LOG_OUT(" ... \n"); /* Calculate the hash */ /* Partition signatures are used by only FSBL / XilSecure / XilFPGA except BL Sign - so partition hashes - always NIST except for bootloader Bootloader Sign is used by ROM - so Bootloader hash - always Keccak */ hash->CalculateHash(!(*section)->isBootloader, partitionAc, hashSecLen + (acSection->Length - signatureLength), shaHash); LOG_TRACE("Hash of %s (LE):", acSection->Name.c_str()); LOG_DUMP_BYTES(shaHash, hashLength); /* Create the PKCS padding for the hash */ uint8_t* shaHashPadded = new uint8_t[signatureLength]; CreatePadding(shaHashPadded, shaHash); if (bi.options.DoGenerateHashes()) { std::string hashfilename = acSection->Name; WritePaddedSHAFile(shaHashPadded, hashfilename); } /* Sign the hash */ authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)secondaryKey, signatureBlock); RearrangeEndianess(signatureBlock, signatureLength); LOG_TRACE("The partition signature is copied into Authentication Certificate"); /* Delete the temporarily created arrays */ delete[] shaHash; delete[] shaHashPadded; acIndex++; } /******************************************************************************/ ZynqAuthenticationContext::ZynqAuthenticationContext() { signatureLength = RSA_SIGN_LENGTH_ZYNQ; SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); hashType = AuthHash::Sha2; spksignature = new uint8_t[signatureLength]; spkSignLoaded = false; primaryKey = new Key2048("Primary Key"); secondaryKey = new Key2048("Secondary Key"); memset(spksignature, 0, signatureLength); memset(udf_data, 0, UDF_DATA_SIZE); authAlgorithm = new RSAAuthenticationAlgorithm(); authCertificate = new RSA2048AuthenticationCertificate(this); certSize = sizeof(AuthCertificate2048Structure); } /******************************************************************************/ ZynqAuthenticationContext::ZynqAuthenticationContext(const AuthenticationContext* refAuthContext) { signatureLength = RSA_SIGN_LENGTH_ZYNQ; SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); hashType = AuthHash::Sha2; primaryKey = new Key2048("Primary Key"); secondaryKey = new Key2048("Secondary Key"); spksignature = new uint8_t[signatureLength]; spkSignLoaded = refAuthContext->spkSignLoaded; primaryKey = refAuthContext->primaryKey; secondaryKey = refAuthContext->secondaryKey; memcpy(spksignature, refAuthContext->spksignature, signatureLength); memcpy(udf_data, refAuthContext->udf_data, sizeof(udf_data)); authAlgorithm = refAuthContext->authAlgorithm; authCertificate = refAuthContext->authCertificate; spkSignRequested = refAuthContext->spkSignRequested; presignFile = refAuthContext->presignFile; udfFile = refAuthContext->udfFile; certSize = sizeof(AuthCertificate2048Structure); } /******************************************************************************/ ZynqAuthenticationContext::ZynqAuthenticationContext(const AuthCertificate2048Structure* existingCert) { signatureLength = RSA_SIGN_LENGTH_ZYNQ; SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); hashType = AuthHash::Sha2; spksignature = new uint8_t[signatureLength]; spkSignLoaded = true; primaryKey = new Key2048("Primary Key"); secondaryKey = new Key2048("Secondary Key"); primaryKey->Import(&existingCert->acPpk, "Primary Key"); secondaryKey->Import(&existingCert->acSpk, "Secondary Key"); memcpy(spksignature, existingCert->acSpkSignature.Signature, signatureLength); memcpy(udf_data, existingCert->acUdf, UDF_DATA_SIZE); certSize = sizeof(AuthCertificate2048Structure); authAlgorithm = new RSAAuthenticationAlgorithm(); } /******************************************************************************/ ZynqAuthenticationContext::~ZynqAuthenticationContext() { if (spksignature != NULL) { delete spksignature; } if (primaryKey != NULL) { delete primaryKey; } if (secondaryKey != NULL) { delete secondaryKey; } } /******************************************************************************/ void ZynqAuthenticationContext::CreatePadding(uint8_t * signature, const uint8_t * hash) { /* Padding scheme MSB-------------------------------------------------------- - LSB 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || tPad || SHA256 Hash */ uint8_t tPad[T_PAD_LENGTH] = { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; uint8_t* sigPtr; uint32_t index; /* Signature array is padded in reverse way - Go to end of the array */ sigPtr = signature + signatureLength; *--sigPtr = 0x00; *--sigPtr = 0x01; /* Fill up 0xFFs for 202 bytes 202bytes = 256bytes (Total) - 19bytes (tPad) - 32bytes (Hash) - 1byte (0x0 MSB) - 1byte (0x1 next to MSB) - 1byte (0x0 before tPad) total FFs = 256 - 19 - 32 - 1 - 1 - 1 = 202 */ uint8_t totalFfs = signatureLength - sizeof(tPad) - hashLength - 1 - 1 - 1; for (index = 0; index < totalFfs; ++index) { *--sigPtr = 0xFF; } *--sigPtr = 0x00; for (index = 0; index < sizeof(tPad); ++index) { *--sigPtr = tPad[index]; } for (index = 0; index < 32; ++index) { *--sigPtr = hash[index]; } } /******************************************************************************/ Section* ZynqAuthenticationContext::CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection) { LOG_INFO("Creating Authentication Certificate for section - %s", dataSection->Name.c_str()); hash = bi.hash; hashLength = hash->GetHashLength(); /* Partition size must be 64-byte aligned */ if ((dataSection->Length & 0x3F) != 0) { LOG_ERROR("Authentication Error !!!\n Partition %s's length %d bytes - is not 64-byte aligned - %s", dataSection->Name.c_str(), dataSection->Length); } if (!secondaryKey->Loaded) { LOG_ERROR("Authentication Error !!!\n Secondary key must be specified in BIF file for %s", dataSection->Name.c_str()); } if (!secondaryKey->isSecret) { if (presignFile != "") { // ok } else if (bi.options.GetNonBootingFlag() && (dataSection->Name.find("ImageHeaderTable") != std::string::npos)) { // ok } else if (bi.options.DoGenerateHashes() || bi.options.GetNonBootingFlag()) { static bool warningGiven = false; std::list outFilename = bi.options.GetOutputFileNames(); if (outFilename.size() > 0) { if (!warningGiven) { LOG_WARNING("A secondary secret key (SSK) is needed to authenticate a boot image. Because the key provided is not secret, the bootimage will not be usable. However, the sha256 hash files will be generated for offline signing"); warningGiven = true; } } } else { LOG_ERROR("Authentication Error !!!\n Secondary key must be secret (SSK) or partition must have [presign=xxx] attribute in BIF file for section %s", dataSection->Name.c_str()); } } if (!(primaryKey->Loaded && primaryKey->isSecret) && !spkSignLoaded) { LOG_ERROR("Authentication Error !!!\n Either PSK or SPK signature file must be specified in BIF file."); } Section* acSection = new Section(dataSection->Name + ".sha256", certSize); acSection->isCertificate = true; acSection->index = dataSection->index; cache.Sections.push_back(acSection); AuthCertificate2048Structure* authCert = (AuthCertificate2048Structure*)acSection->Data; LOG_TRACE("Creating new section for certificate - %s", acSection->Name.c_str()); uint32_t x = sizeof(AuthCertificate2048Structure); if (x != certSize) { LOG_DEBUG(DEBUG_STAMP, "Bad Authentication Certificate Size"); LOG_ERROR("Authentication Error !!!"); } memset(authCert, 0, certSize); WriteLittleEndian32(&authCert->acHeader, AUTH_HDR_ZYNQ); WriteLittleEndian32(&authCert->acSize, certSize); if (udfFile != "") { LoadUdfData(udfFile, udf_data); memcpy(authCert->acUdf, udf_data, UDF_DATA_SIZE); } primaryKey->Export(&authCert->acPpk); secondaryKey->Export(&authCert->acSpk); CopySPKSignature(&authCert->acSpkSignature); return acSection; } /******************************************************************************/ void ZynqAuthenticationContext::Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert) { ::AuthCertificate2048Structure* authCert = (AuthCertificate2048Structure*)cert->section->Data; uint8_t* signatureBlock = (uint8_t*)&authCert->acPartitionSignature; if (presignFile == "") { /* If the parition is not presigned / presign file not present */ CopyPartitionSignature(bi, sections, signatureBlock, cert->section); } else { /* If the parition is presigned / presign file present */ GetPresign(presignFile, signatureBlock, cert->section->index); } } /******************************************************************************/ void ZynqAuthenticationContext::GenerateSPKHash(uint8_t* shaHashPadded) { LOG_TRACE("Calculating the SPK hash"); ACKey2048 spkFull; secondaryKey->Export(&spkFull); uint8_t* shaHash = new uint8_t[hashLength]; hash->CalculateHash(false, (uint8_t*)&spkFull, sizeof(spkFull), shaHash); CreatePadding(shaHashPadded, shaHash); delete[] shaHash; } /******************************************************************************/ void ZynqAuthenticationContext::CopySPKSignature(ACSignature2048* ptr) { CreateSPKSignature(); LOG_TRACE("Copying the SPK signature into the Authentication Certificate"); memcpy(ptr, spksignature, signatureLength); } /******************************************************************************/ void ZynqAuthenticationContext::GeneratePPKHash(const std::string& filename) { ACKey2048 ppkTemp; primaryKey->Export(&ppkTemp); hashLength = hash->GetHashLength(); uint8_t* rsa_signature = new uint8_t[hashLength]; hash->CalculateHash(false, (uint8_t*)&ppkTemp, sizeof(ACKey2048), rsa_signature); FILE* filePtr; if ((filePtr = fopen(filename.c_str(), "w")) == NULL) { LOG_ERROR("-efuseppkbits error !!! Failure writing to hash file %s", StringUtils::BaseName(filename).c_str()); } for (int index = 0; index < hashLength; index++) { fprintf(filePtr, "%02X", rsa_signature[index]); } fprintf(filePtr, "\r\n"); fclose(filePtr); LOG_INFO("PPK Hash is written to file %s successfully", filename.c_str()); } /******************************************************************************/ void ZynqAuthenticationContext::SetKeyLength(Authentication::Type type) { if (type == Authentication::RSA) { AuthenticationContext::authKeyLength = RSA_2048_KEY_LENGTH; } } xilinx-bootgen-2024.2/authentication-zynq.h000077500000000000000000000062221475706442400207620ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _AUTHENTICATION_ZYNQ_H_ #define _AUTHENTICATION_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "authentication.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define AUTH_HDR_ZYNQ 0x00000101 typedef struct { uint32_t acHeader; // 0x000 uint32_t acSize; // 0x004 uint8_t acUdf[UDF_DATA_SIZE]; // 0x008 ACKey2048 acPpk; // 0x040 ACKey2048 acSpk; // 0x280 ACSignature2048 acSpkSignature; // 0x4C0 ACSignature2048 acPartitionSignature; // 0x5C0 } AuthCertificate2048Structure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqAuthenticationContext : public AuthenticationContext { public: ZynqAuthenticationContext(); ZynqAuthenticationContext(const AuthenticationContext* refAuthContext); ZynqAuthenticationContext(const AuthCertificate2048Structure* existingCert); ~ZynqAuthenticationContext(); uint32_t GetCertificateSize(void) { return certSize; } Section* CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection); void Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert); void GeneratePPKHash(const std::string& filename); void SetKeyLength(Authentication::Type type); void GenerateSPKHash(uint8_t* sha256_hash_padded); void CreatePadding(uint8_t* signature, const uint8_t* hash); void CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection); void RearrangeEndianess(uint8_t *array, uint32_t size) {}; private: uint32_t certSize; void CopySPKSignature(ACSignature2048* ptr); }; #endif xilinx-bootgen-2024.2/authentication-zynqmp.cpp000077500000000000000000000650311475706442400216550ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "string.h" #include "authentication-zynqmp.h" #include "bootgenexception.h" #include "stringutils.h" #include "binary.h" #include "bootimage.h" #include "options.h" /*------------------------------------------------------------------------------ * BH Hash is always Keccak - Irrespective of SPK-eFuse/User-eFuse - Since BH Sign used by BootRoM - BH Hash is same for any partition as its always calculated on same data * SPK can vary from Partition to Partition - Keccak/NIST is based of SPK-eFuse/User-eFuse selected for that partition. * For Bootloader Partition - always authenticated by BootRoM - Always SPK-eFuse is used for Bootloader, so SPK Hash is always Keccak. * Partition signatures are always authenticated by only FSBL/XilSecure/XilFPGA - Partition hashes - always NIST -----------------------------------------------------------------------------*/ /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void ZynqMpAuthenticationContext::CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection) { /* Calculate the length of the partiton that is to be hashed,Since bs is authenticated in chunks. This can be changed with authblock[default is 8].*/ LOG_TRACE("Copying the partition signature into Authentication Certificate"); uint8_t* shaHash = new uint8_t[hashLength]; std::list::iterator section = sections.begin(); size_t hashSecLen = (*section)->Length; size_t authblocksize = authBlocks * 1024 * 1024; if (authblocksize != 0) { hashSecLen = authblocksize; } if (((*section)->Length) - (authblocksize * acIndex) < authblocksize && (authBlocks != 0)) { hashSecLen = ((*section)->Length) - (authblocksize * acIndex); } /* Update with Partition and then AC */ uint8_t *partitionAc = new uint8_t[hashSecLen + (acSection->Length - signatureLength)]; /* Update with Partition */ memcpy(partitionAc, (*section)->Data + (authblocksize * acIndex), hashSecLen); /* Update with authentication certificate except the last 256 bytes, which is the partition signature, that we are calculating now. Once calculated, the partition signature will sit there */ memcpy(partitionAc + hashSecLen, acSection->Data, acSection->Length - signatureLength); uint32_t start = (*section)->Address; uint32_t end = (acSection->Address + acSection->Length) - signatureLength; LOG_TRACE("Hashing %s from 0x%x to 0x%x", acSection->Name.c_str(), start, end); LOG_DUMP_BYTES((*section)->Data + (authblocksize * acIndex), 32); LOG_OUT(" ... "); LOG_DUMP_BYTES((*section)->Data + (authblocksize * acIndex) + hashSecLen - hashLength, hashLength); LOG_OUT(" ... \n"); /* Calculate the hash */ /* Partition signatures are used by FSBL/XilSecure/XilFPGA except BL Sign-So partition hashes always NIST except for bootloader Bootloader Sign is used by ROM - so Bootloader hash - always Keccak */ hash->CalculateHash(!(*section)->isBootloader, partitionAc, hashSecLen + (acSection->Length - signatureLength), shaHash); LOG_TRACE("Hash of %s (LE):", acSection->Name.c_str()); LOG_DUMP_BYTES(shaHash, hashLength); /* Create the PKCS padding for the hash */ uint8_t* shaHashPadded = new uint8_t[signatureLength]; CreatePadding(shaHashPadded, shaHash); if (bi.options.DoGenerateHashes()) { std::string hashfilename = acSection->Name; WritePaddedSHAFile(shaHashPadded, hashfilename); } RearrangeEndianess(shaHashPadded, signatureLength); /*Sign the hash */ authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)secondaryKey, signatureBlock); RearrangeEndianess(signatureBlock, signatureLength); LOG_TRACE("The partition signature is copied into Authentication Certificate"); /* Delete the temporarily created arrays */ delete[] shaHash; delete[] shaHashPadded; delete[] partitionAc; acIndex++; } /******************************************************************************/ ZynqMpAuthenticationContext::ZynqMpAuthenticationContext() { signatureLength = RSA_SIGN_LENGTH_ZYNQMP; SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); hashType = AuthHash::Sha3; spksignature = new uint8_t[signatureLength]; spkSignLoaded = false; primaryKey = new Key4096("Primary Key"); secondaryKey = new Key4096("Secondary Key"); memset(spksignature, 0, signatureLength); memset(udf_data, 0, UDF_DATA_SIZE); bHsignature = new uint8_t[signatureLength]; memset(bHsignature, 0, signatureLength); bhSignLoaded = false; authAlgorithm = new RSAAuthenticationAlgorithm(); authCertificate = new RSA4096AuthenticationCertificate(); certSize = sizeof(AuthCertificate4096Structure); } /******************************************************************************/ ZynqMpAuthenticationContext::ZynqMpAuthenticationContext(const AuthenticationContext* refAuthContext) { signatureLength = RSA_SIGN_LENGTH_ZYNQMP; SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); hashType = AuthHash::Sha3; spksignature = new uint8_t[signatureLength]; bHsignature = new uint8_t[signatureLength]; ppkFile = refAuthContext->ppkFile; pskFile = refAuthContext->pskFile; spkFile = refAuthContext->spkFile; sskFile = refAuthContext->sskFile; spkSignFile = refAuthContext->spkSignFile; bhSignFile = refAuthContext->bhSignFile; ppkSelect = refAuthContext->ppkSelect; spkSelect = refAuthContext->spkSelect; spkIdentification = refAuthContext->spkIdentification; primaryKey = new Key4096("Primary Key"); secondaryKey = new Key4096("Secondary Key"); primaryKey = refAuthContext->primaryKey; if (spkFile != "" || sskFile != "") { if (sskFile != "") { secondaryKey->ParseSecret(sskFile); } if (spkFile != "") { secondaryKey->ParsePublic(spkFile); } } else { secondaryKey = refAuthContext->secondaryKey; } if (spkSignFile != "") { SetSPKSignatureFile(spkSignFile); } else { memcpy(spksignature, refAuthContext->spksignature, signatureLength); } if (bhSignFile != "") { SetBHSignatureFile(bhSignFile); } else { memcpy(bHsignature, refAuthContext->bHsignature, signatureLength); } memcpy(udf_data, refAuthContext->udf_data, sizeof(udf_data)); bhSignLoaded = refAuthContext->bhSignLoaded; spkSignLoaded = refAuthContext->spkSignLoaded; spkSignRequested = refAuthContext->spkSignRequested; certSize = sizeof(AuthCertificate4096Structure); preSigned = refAuthContext->preSigned; authAlgorithm = refAuthContext->authAlgorithm; authCertificate = refAuthContext->authCertificate; } /******************************************************************************/ ZynqMpAuthenticationContext::ZynqMpAuthenticationContext(const AuthCertificate4096Structure* existingCert) { signatureLength = RSA_SIGN_LENGTH_ZYNQMP; SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); hashType = AuthHash::Sha3; spksignature = new uint8_t[signatureLength]; spkSignLoaded = true; bHsignature = new uint8_t[signatureLength]; bhSignLoaded = true; primaryKey = new Key4096("Primary Key"); secondaryKey = new Key4096("Secondary Key"); primaryKey->Import(&existingCert->acPpk, "Primary Key"); secondaryKey->Import(&existingCert->acSpk, "Secondary Key"); RearrangeEndianess(primaryKey->N, sizeof(existingCert->acPpk.N)); RearrangeEndianess(primaryKey->N_ext, sizeof(existingCert->acPpk.N_extension)); RearrangeEndianess(primaryKey->E, sizeof(existingCert->acPpk.E)); RearrangeEndianess(secondaryKey->N, sizeof(existingCert->acSpk.N)); RearrangeEndianess(secondaryKey->N_ext, sizeof(existingCert->acSpk.N_extension)); RearrangeEndianess(secondaryKey->E, sizeof(existingCert->acSpk.E)); memcpy(spksignature, existingCert->acSpkSignature.Signature, signatureLength); memcpy(bHsignature, existingCert->acBhSignature.Signature, signatureLength); memcpy(udf_data, existingCert->acUdf, UDF_DATA_SIZE); uint32_t acHdr = existingCert->acHeader; ppkSelect = 3 & (acHdr >> AC_HDR_PPK_SELECT_BIT_SHIFT); spkSelect = acHdr >> AC_HDR_SPK_SELECT_BIT_SHIFT; spkIdentification = existingCert->spkId; certSize = sizeof(AuthCertificate4096Structure); authAlgorithm = new RSAAuthenticationAlgorithm(); } /******************************************************************************/ ZynqMpAuthenticationContext::~ZynqMpAuthenticationContext() { if (spksignature != NULL) { delete[] spksignature; } if (bHsignature != NULL) { delete[] bHsignature; } if (primaryKey != NULL) { delete primaryKey; } if (secondaryKey != NULL) { delete secondaryKey; } } /******************************************************************************/ void ZynqMpAuthenticationContext::CreatePadding(uint8_t * signature, const uint8_t * hash) { /* SHA2 PKCS#1v1.5 Padding LSB------------------------------------------------------MSB 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || tPad || SHA Hash SHA3 PKCS#1v1.5 Padding LSB------------------------------------------------------MSB 0x0 || 0x1 || 0xFF(for 384 bytes) || 0x0 || tPad || SHA Hash */ uint8_t tPadSha2[T_PAD_LENGTH] = { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; /* Older SHA3 ID used before 2016.1 */ uint8_t tPadSha3[T_PAD_LENGTH] = { 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; /* New SHA3 ID as per NIST */ uint8_t tPadSha3new[T_PAD_LENGTH] = { 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30 }; uint8_t* sigPtr; uint8_t* tempSigPtr; uint32_t index; uint8_t* tPad; tempSigPtr = signature; if (hashType == AuthHash::Sha2) { tPad = tPadSha2; } else { /* If -zynqmpes1 is used, then old sha3 id is used, otherwise new id will be used */ tPad = tPadSha3new; static bool warningGiven = false; if (AuthenticationContext::GetZynpMpVerEs1Flag()) { tPad = tPadSha3; if (!warningGiven) { LOG_TRACE("ZynqMp silicon set to (1.0)ES1 using -zynqmpes1"); LOG_WARNING("Authentication padding scheme is as per silicon (1.0)ES1. The image generated will NOT work for 2.0(ES2) and above."); warningGiven = true; } } else { if (!warningGiven) { LOG_WARNING("Authentication padding scheme will be as per silicon 2.0(ES2) and above. The image generated will NOT work for 1.0(ES1). \n Use '-zynqmpes1' to generate image for 1.0(ES1)"); warningGiven = true; } } } sigPtr = signature; *sigPtr++ = 0x00; *sigPtr++ = 0x01; uint32_t totalFfs = signatureLength - T_PAD_LENGTH - hashLength - 1 - 1 - 1; for (index = 0; index < totalFfs; ++index) { *sigPtr++ = 0xFF; } *sigPtr++ = 0x00; for (index = 0; index < T_PAD_LENGTH; ++index) { *sigPtr++ = tPad[index]; } for (index = 0; index < hashLength; ++index) { *sigPtr++ = hash[index]; } signature = tempSigPtr; } /******************************************************************************/ Section* ZynqMpAuthenticationContext::CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection) { LOG_INFO("Creating Authentication Certificate for section - %s", dataSection->Name.c_str()); hashType = bi.GetAuthHashAlgo(); hash = bi.hash; hashLength = hash->GetHashLength(); std::string hashExtension = hash->GetHashFileExtension(); /* Partition size must be 64-byte aligned */ if ((dataSection->Length & 0x3F) != 0) { LOG_ERROR("Authentication Error !!!\n Partition %s's length %d bytes - is not 64-byte aligned - %s", dataSection->Name.c_str(), dataSection->Length); } /* Secondary key is must for authenticating */ if (!secondaryKey->Loaded) { if (acFile != "") { // ok } else { LOG_ERROR("Authentication Error !!!\n Secondary key must be specified in BIF file for %s", dataSection->Name.c_str()); } } if (!secondaryKey->isSecret) { if (presignFile != "") { // ok } else if (acFile != "") { // ok } else if (bi.options.GetNonBootingFlag() && (dataSection->Name.find("ImageHeaderTable") != std::string::npos)) { // ok } else if (bi.options.DoGenerateHashes() || bi.options.GetNonBootingFlag()) { static bool warningGiven = false; std::list outFilename = bi.options.GetOutputFileNames(); if (outFilename.size() > 0) { if (!warningGiven) { LOG_WARNING("SSK is needed to authenticate a boot image. Because the key provided is not secret, the bootimage will not be usable. However, the sha hash files will be generated for offline signing"); warningGiven = true; } } } else if (bi.currentAuthCtx->spkSignRequested != "") { LOG_WARNING("SSK is needed to authenticate a boot image. Because the key provided is not secret, the bootimage will not be usable. However, SPK signature will be generated as requested."); } else { LOG_ERROR("Authentication Error !!!\n SSK or partition must have [presign=xxx] attribute in BIF file for section %s", dataSection->Name.c_str()); } } if (!(primaryKey->Loaded && primaryKey->isSecret) && !spkSignLoaded) { if (bi.options.DoGenerateHashes()) { LOG_WARNING("Either PSK or spksignature is needed to authenticate bootimage or generate partition hashes. Because they are not provided, the bootimage and partition hashes will not be usable. However SPK hash and bootheader hash files generated can be used for offline signing."); } else if (acFile != "") { // ok } else { LOG_ERROR("Authentication Error !!!\n Either PSK or SPK signature file must be specified in BIF file."); } } std::string name = dataSection->Name; if (dataSection->index == 0) { name = GetCertificateName(name); } Section* acSection = new Section(name + hashExtension, certSize); acSection->isCertificate = true; acSection->index = dataSection->index; cache.Sections.push_back(acSection); AuthCertificate4096Structure* authCert = (AuthCertificate4096Structure*)acSection->Data; LOG_TRACE("Creating new section for certificate - %s", acSection->Name.c_str()); uint32_t x = sizeof(AuthCertificate4096Structure); if (x != certSize) { LOG_DEBUG(DEBUG_STAMP, "Bad Authentication Certificate Size"); LOG_ERROR("Authentication Error !!!"); } memset(authCert, 0, certSize); if (acFile != "") { // ok } else { uint32_t acHdr = AUTH_HDR_ZYNQMP; acHdr |= ppkSelect << AC_HDR_PPK_SELECT_BIT_SHIFT; acHdr |= spkSelect << AC_HDR_SPK_SELECT_BIT_SHIFT; acHdr |= ((bi.GetAuthHashAlgo()) ? 0 : 1) << AC_HDR_SHA_2_3_BIT_SHIFT; WriteLittleEndian32(&authCert->acHeader, acHdr); WriteLittleEndian32(&authCert->spkId, spkIdentification); if (udfFile != "") { LoadUdfData(udfFile, udf_data); RearrangeEndianess(udf_data, sizeof(udf_data)); memcpy(authCert->acUdf, udf_data, UDF_DATA_SIZE); } primaryKey->Export(&authCert->acPpk); RearrangeEndianess(authCert->acPpk.N, sizeof(authCert->acPpk.N)); RearrangeEndianess(authCert->acPpk.N_extension, sizeof(authCert->acPpk.N_extension)); RearrangeEndianess(authCert->acPpk.E, sizeof(authCert->acPpk.E)); secondaryKey->Export(&authCert->acSpk); RearrangeEndianess(authCert->acSpk.N, sizeof(authCert->acSpk.N)); RearrangeEndianess(authCert->acSpk.N_extension, sizeof(authCert->acSpk.N_extension)); RearrangeEndianess(authCert->acSpk.E, sizeof(authCert->acSpk.E)); CopySPKSignature(&authCert->acSpkSignature); } certIndex++; return acSection; } /******************************************************************************/ void ZynqMpAuthenticationContext::Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert) { ::AuthCertificate4096Structure* authCert = (AuthCertificate4096Structure*)cert->section->Data; uint8_t* signatureBlock = (uint8_t*)&authCert->acPartitionSignature; CopyBHSignature(bi, &authCert->acBhSignature); if (acFile != "") { /* If the parition AC file present */ int index = acIndex; if (cert->section->index != 0) { index = cert->section->index; } GetAC(acFile, cert->section->Data, index); acIndex++; } else if (presignFile == "") { /* If the parition is not presigned / presign file not present */ std::list::iterator section = sections.begin(); (*section)->isBootloader = cert->fsbl; CopyPartitionSignature(bi, sections, signatureBlock, cert->section); } else { /* If the parition is presigned / presign file present */ int index = acIndex; if (cert->section->index != 0) { index = cert->section->index; } GetPresign(presignFile, signatureBlock, index); acIndex++; } } /******************************************************************************/ void ZynqMpAuthenticationContext::CopyBHSignature(BootImage& bi, ACSignature4096* ptr) { uint8_t* sha_hash_padded = new uint8_t[signatureLength]; uint8_t* bHsignaturetmp = new uint8_t[signatureLength]; GenerateBHHash(bi, sha_hash_padded); if (bi.options.DoGenerateHashes()) { std::string hashfilename = "bootheader" + hash->GetHashFileExtension(); WritePaddedSHAFile(sha_hash_padded, hashfilename); } if (secondaryKey->Loaded && secondaryKey->isSecret) { LOG_TRACE("Creating Boot Header Signature"); RearrangeEndianess(sha_hash_padded, signatureLength); authAlgorithm->CreateSignature(sha_hash_padded, (uint8_t*)secondaryKey, bHsignaturetmp); RearrangeEndianess(bHsignaturetmp, signatureLength); if (bhSignLoaded) { if (memcmp(bHsignature, bHsignaturetmp, signatureLength) != 0) { LOG_ERROR("Authentication Error !!!\n Loaded BH Signature does not match calculated BH Signature"); } } memcpy(ptr, bHsignaturetmp, signatureLength); } else if (bhSignLoaded) { memcpy(ptr, bHsignature, signatureLength); } else if (bi.options.DoGenerateHashes() && !bhSignLoaded) { static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("Either SSK or (bhsignature and presign) is needed to authenticate a boot image or generate partition hashes. Because they are not provided, the bootimage and partition hashes will not be usable. However, the boot header hash file generated can be used for offline signing"); warningGiven = true; } } else if (acFile != "") { // ok } else { LOG_ERROR("Authentication Error !!!\n Either SSK or BH signature file must be specified in the BIF file."); } if (sha_hash_padded) { delete[] sha_hash_padded; } if (bHsignaturetmp) { delete[] bHsignaturetmp; } LOG_TRACE("Boot Header Signature copied into Authentication Certificate"); } /******************************************************************************/ void ZynqMpAuthenticationContext::GenerateBHHash(BootImage& bi, uint8_t* sha_hash_padded) { LOG_TRACE("Calculating the Boot Header Hash"); uint8_t* tmpBh = bi.bootHeader->section->Data; uint8_t* sha_hash = new uint8_t[hashLength]; hash->CalculateHash(false, tmpBh, bi.bootHeader->section->Length, sha_hash); CreatePadding(sha_hash_padded, sha_hash); delete[] sha_hash; } /******************************************************************************/ void ZynqMpAuthenticationContext::GenerateSPKHash(uint8_t* shaHashPadded) { LOG_TRACE("Calculating the SPK Hash"); ACKey4096 spkFull; if (!secondaryKey->Loaded) { ParseSPKeyFile(spkFile); } secondaryKey->Export(&spkFull); hashLength = hash->GetHashLength(); uint8_t* shaHash = new uint8_t[hashLength]; uint32_t acHdr = AUTH_HDR_ZYNQMP; acHdr |= ppkSelect << AC_HDR_PPK_SELECT_BIT_SHIFT; acHdr |= spkSelect << AC_HDR_SPK_SELECT_BIT_SHIFT; acHdr |= ((hashType == AuthHash::Sha2) ? 0 : 1) << AC_HDR_SHA_2_3_BIT_SHIFT; uint8_t* tempBuffer = new uint8_t[sizeof(spkFull) + sizeof(acHdr) + sizeof(spkIdentification)]; WriteLittleEndian32(tempBuffer, acHdr); WriteLittleEndian32(tempBuffer + sizeof(acHdr), spkIdentification); RearrangeEndianess(spkFull.N, sizeof(spkFull.N)); RearrangeEndianess(spkFull.N_extension, sizeof(spkFull.N_extension)); RearrangeEndianess(spkFull.E, sizeof(spkFull.E)); memcpy(tempBuffer + sizeof(acHdr) + sizeof(spkIdentification), (uint8_t*)&spkFull, sizeof(spkFull)); bool nist = false; if (spkSelect == 1) { nist = false; } else if (spkSelect == 2) { nist = true; } hash->CalculateHash(nist, (uint8_t*)tempBuffer, sizeof(spkFull) + sizeof(acHdr) + sizeof(spkIdentification), shaHash); CreatePadding(shaHashPadded, shaHash); delete[] shaHash; delete[] tempBuffer; } /******************************************************************************/ void ZynqMpAuthenticationContext::CopySPKSignature(ACSignature4096* ptr) { CreateSPKSignature(); LOG_TRACE("Copying the SPK signature into the Authentication Certificate"); memcpy(ptr, spksignature, signatureLength); } /******************************************************************************/ std::string ZynqMpAuthenticationContext::GetCertificateName(std::string name) { if (certIndex != 0) { size_t x = name.find(".0"); if (std::string::npos != name.find(".0")) { name[x + 1] = (char)(name[x + 1] + certIndex); } } return name; } /******************************************************************************/ void ZynqMpAuthenticationContext::GeneratePPKHash(const std::string& filename) { ACKey4096 ppkTemp; primaryKey->Export(&ppkTemp); RearrangeEndianess(ppkTemp.N, sizeof(ppkTemp.N)); RearrangeEndianess(ppkTemp.N_extension, sizeof(ppkTemp.N_extension)); RearrangeEndianess(ppkTemp.E, sizeof(ppkTemp.E)); hashLength = hash->GetHashLength(); uint8_t* rsa_signature = new uint8_t[hashLength]; hash->CalculateHash(false, (uint8_t*)&ppkTemp, sizeof(ACKey4096), rsa_signature); FILE* filePtr; if ((filePtr = fopen(filename.c_str(), "w")) == NULL) { LOG_ERROR("-efuseppkbits error !!! Failure writing to hash file %s", StringUtils::BaseName(filename).c_str()); } for (int index = 0; index < hashLength; index++) { fprintf(filePtr, "%02X", rsa_signature[index]); } fprintf(filePtr, "\r\n"); fclose(filePtr); LOG_INFO("PPK Hash is written to file %s successfully", filename.c_str()); } /******************************************************************************/ void ZynqMpAuthenticationContext::RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; if (!array) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /******************************************************************************/ void ZynqMpAuthenticationContext::AddAuthCertSizeToTotalFSBLSize(PartitionHeader* header) { for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { if (*acs && (*acs)->section) { if (header->imageHeader->IsBootloader() == true) { header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + (*acs)->section->Length); } } } } /******************************************************************************/ void ZynqMpAuthenticationContext::SetKeyLength(Authentication::Type type) { if (type == Authentication::RSA) { AuthenticationContext::authKeyLength = RSA_4096_KEY_LENGTH; } } xilinx-bootgen-2024.2/authentication-zynqmp.h000077500000000000000000000070531475706442400213220ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _AUTHENTICATION_ZYNQMP_H_ #define _AUTHENTICATION_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "authentication.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define AUTH_HDR_ZYNQMP 0x115 #define AC_HDR_SHA_2_3_BIT_SHIFT 2 #define AC_HDR_PPK_SELECT_BIT_SHIFT 16 #define AC_HDR_SPK_SELECT_BIT_SHIFT 18 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ /* RSA 4096 Authentication Certificate */ typedef struct { uint32_t acHeader; // 0x000 uint32_t spkId; // 0x004 uint8_t acUdf[UDF_DATA_SIZE]; // 0x008 ACKey4096 acPpk; // 0x040 ACKey4096 acSpk; // 0x480 ACSignature4096 acSpkSignature; // 0x8C0 ACSignature4096 acBhSignature; // 0xAC0 ACSignature4096 acPartitionSignature; // 0xCC0 } AuthCertificate4096Structure; class ZynqMpAuthenticationContext : public AuthenticationContext { public: ZynqMpAuthenticationContext(); ZynqMpAuthenticationContext(const AuthenticationContext* refAuthContext); ZynqMpAuthenticationContext(const AuthCertificate4096Structure* existingCert); ~ZynqMpAuthenticationContext(); uint32_t GetCertificateSize(void) { return certSize; } Section* CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection); void Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert); void GeneratePPKHash(const std::string& filename); void GenerateSPKHash(uint8_t* sha256_hash_padded); void GenerateBHHash(BootImage& bi, uint8_t* sha_hash_padded); void CreatePadding(uint8_t* signature, const uint8_t* hash); void CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection); void RearrangeEndianess(uint8_t *array, uint32_t size); void AddAuthCertSizeToTotalFSBLSize(PartitionHeader* header); void SetKeyLength(Authentication::Type type); private: uint32_t certSize; void CopySPKSignature(ACSignature4096* ptr); std::string GetCertificateName(std::string name); void CopyBHSignature(BootImage& bi, ACSignature4096* ptr); }; #endif xilinx-bootgen-2024.2/authentication.cpp000077500000000000000000000573071475706442400203300ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "authentication.h" #include "bootgenexception.h" #include "stringutils.h" #include "binary.h" #include "bootimage.h" #include "string.h" #include "options.h" uint16_t AuthenticationContext::authKeyLength = 0; uint8_t AuthenticationContext::hashLength = 0; bool AuthenticationContext::zynpmpVerEs1 = false; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void AuthenticationContext::SetPresignFile(const std::string& filename) { presignFile = filename; } /******************************************************************************/ void AuthenticationContext::SetACFile(const std::string& filename) { acFile = filename; } /******************************************************************************/ void AuthenticationContext::SetUdfFile(const std::string& filename) { udfFile = filename; } /******************************************************************************/ void AuthenticationContext::SetPSKeyFile(const std::string& filename) { pskFile = filename; } /******************************************************************************/ void AuthenticationContext::ParsePSKeyFile(const std::string & filename) { primaryKey->ParseSecret(filename); } /******************************************************************************/ void AuthenticationContext::SetPPKeyFile(const std::string& filename) { ppkFile = filename; } /******************************************************************************/ void AuthenticationContext::ParsePPKeyFile(const std::string& filename) { if (ppkFile != "") { primaryKey->ParsePublic(filename); } } /******************************************************************************/ void AuthenticationContext::SetSSKeyFile(const std::string& filename) { sskFile = filename; } /******************************************************************************/ void AuthenticationContext::ParseSSKeyFile(const std::string& filename) { if (sskFile != "") { secondaryKey->ParseSecret(filename); } } /******************************************************************************/ void AuthenticationContext::SetSPKeyFile(const std::string& filename) { spkFile = filename; } /******************************************************************************/ void AuthenticationContext::ParseSPKeyFile(const std::string& filename) { if (spkFile != "") { secondaryKey->ParsePublic(filename); } } /******************************************************************************/ void AuthenticationContext::SetPpkSelect(uint32_t ppk) { ppkSelect = ppk; } /******************************************************************************/ void AuthenticationContext::SetSpkSelect(uint32_t spk) { spkSelect = spk; } /******************************************************************************/ void AuthenticationContext::SetSpkIdentification(uint32_t spkid) { spkIdentification = spkid; } /******************************************************************************/ void AuthenticationContext::SetHeaderAuthentication(uint32_t headerauth) { isHeaderAuthentication = headerauth; } /******************************************************************************/ void AuthenticationContext::SetAuthenticationKeyLength(uint16_t keylen) { AuthenticationContext::authKeyLength = keylen; } /******************************************************************************/ uint16_t AuthenticationContext::GetRsaKeyLength(void) { return AuthenticationContext::authKeyLength; } /******************************************************************************/ void AuthenticationContext::SetSignatureLength(uint16_t length) { signatureLength = length; } /******************************************************************************/ uint16_t AuthenticationContext::GetSignatureLength(void) { return signatureLength; } /******************************************************************************/ size_t AuthenticationContext::GetauthBlocks(size_t authblocks) { return authblocks; } /******************************************************************************/ void AuthenticationContext::SetZynpMpVerEs1Flag(bool isEs1) { AuthenticationContext::zynpmpVerEs1 = isEs1; } /******************************************************************************/ bool AuthenticationContext::GetZynpMpVerEs1Flag(void) { return AuthenticationContext::zynpmpVerEs1; } /******************************************************************************/ void AuthenticationContext::SetHashType(AuthHash::Type type) { hashType = type; } /******************************************************************************/ void AuthenticationContext::SetFirstChunkSize(uint64_t size) { firstChunkSize = size; } /******************************************************************************/ AuthHash::Type AuthenticationContext::GetHashType(void) { return hashType; } /******************************************************************************/ void AuthenticationContext::WritePaddedSHAFile(const uint8_t* shaBuf, const std::string& hashfilename) { std::string filename = StringUtils::BaseName(hashfilename); std::ofstream f(filename.c_str(),std::ios_base::out|std::ios_base::binary); f.write((char*)shaBuf, signatureLength); f.close(); if (f.fail()) { LOG_ERROR("-generate_hashes failure !!!\n Failed to write generated hash to the file: %s", filename.c_str()); } LOG_TRACE("Hash file %s generated successfully", filename.c_str()); } /******************************************************************************/ void AuthenticationContext::GetPresign(const std::string& presignFilename, uint8_t* signature, uint32_t index) { std::string filename(presignFilename); std::string baseFile = StringUtils::BaseName(filename); if (index != 0) { size_t x = filename.find(".0."); if (x == std::string::npos) { LOG_ERROR("Presign file %s does not have partition index (*.0.*)", baseFile.c_str()); } // nudge the '0' to index number std::string sindex = std::to_string(index); filename.replace(x+1,1,sindex); } LOG_TRACE("Reading presign file - %s", filename.c_str()); FILE* filePtr; filePtr = fopen(filename.c_str(),"rb"); if (filePtr) { fseek(filePtr, 0, SEEK_END); long size = ftell(filePtr); fclose(filePtr); if (size == signatureLength) { // read binary filePtr = fopen(filename.c_str(),"rb"); long read_size = fread(signature, 1, signatureLength, filePtr); if(read_size != signatureLength) { LOG_ERROR("Authentication Error !!!\n Presign file %s should be of %d bytes", baseFile.c_str(), signatureLength); } fclose(filePtr); } else { // read ascii filePtr = fopen(filename.c_str(),"r"); for(int i=0; i 255) { LOG_ERROR("Bad hex conversion %x - %s", datum, baseFile.c_str()); } if(nbytes == UDF_DATA_SIZE) { LOG_ERROR("More than %d bytes in the UDF Data file %s is not allowed.", UDF_DATA_SIZE, baseFile.c_str()); } signature[nbytes++] = datum; } else { LOG_ERROR("Failure reading UDF file - %s", baseFile.c_str()); } } } else { LOG_ERROR("Failure opening UDF file - %s", baseFile.c_str()); } fclose(filePtr); LOG_TRACE("UDF data is loaded successfully in the Authentication Certificate from file - %s", udfFilename.c_str()); } /******************************************************************************/ void AuthenticationContext::ResizeIfNecessary(Section* section) { uint32_t dataSizePadded = (section->Length + 63) & 0xFFFFFFC0; section->IncreaseLengthAndPadTo(dataSizePadded, 0xFF); } /******************************************************************************/ void AuthenticationContext::GenerateSPKSignature(const std::string& filename) { if (primaryKey->Loaded && primaryKey->isSecret) { uint8_t* shaHashPadded = new uint8_t [signatureLength]; uint8_t* spkSignatureTemp = new uint8_t [signatureLength]; if (!secondaryKey->Loaded) { ParseSPKeyFile(spkFile); } GenerateSPKHash(shaHashPadded); RearrangeEndianess(shaHashPadded, signatureLength); authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)primaryKey, spkSignatureTemp); RearrangeEndianess(spkSignatureTemp, signatureLength); LOG_INFO("SPK Signature generated successfully"); if (filename != "") { FILE* filePtr; filePtr = fopen(filename.c_str(),"w"); if (filePtr) { for(uint32_t i=0; iLoaded && primaryKey->isSecret) { uint8_t* shaHashPadded = new uint8_t [signatureLength]; uint8_t* spkSignaturetmp = new uint8_t [signatureLength]; /* Calulate the SPK hash with PKCS padding */ GenerateSPKHash(shaHashPadded); RearrangeEndianess(shaHashPadded, signatureLength); /* Sign the SPK hash */ authAlgorithm->CreateSignature(shaHashPadded, (uint8_t*)primaryKey, spkSignaturetmp); /* If SPK signature file is directly given in BIF file, Sanity Check by cross verifying the calculated SPK signature */ if (spkSignLoaded) { RearrangeEndianess(spkSignaturetmp, signatureLength); if (memcmp(spksignature, spkSignaturetmp, signatureLength) != 0) { LOG_ERROR("Authentication Error !!!\n Loaded SPK Signature does not match calculated SPK Signature"); } } /* If SPK signature file is not given in BIF file, Copy the calculated SPK signature */ else { memcpy(spksignature, spkSignaturetmp, signatureLength); spkSignLoaded = true; RearrangeEndianess(spksignature, signatureLength); } delete [] shaHashPadded; delete [] spkSignaturetmp; } /* If SPK signature file or PSK is not given in BIF file, cannot get SPK signature for the auth certificate Throw error */ else if(!spkSignLoaded) { LOG_ERROR("Authentication Error !!!\n PSK or SPK signature missing, must specify atleast one"); } LOG_INFO("SPK signature created successfully"); } /******************************************************************************/ void AuthenticationContext::GenerateSPKHashFile(const std::string& filename, Hash* hashObj) { hash = hashObj; hashLength = hash->GetHashLength(); uint8_t* shaHashPadded = new uint8_t [signatureLength]; memset(shaHashPadded, 0, signatureLength); /* Calculate the SPK hash */ GenerateSPKHash(shaHashPadded); std::string hashfile = filename + hash->GetHashFileExtension(); WritePaddedSHAFile(shaHashPadded, hashfile); delete [] shaHashPadded; } /******************************************************************************/ void AuthenticationContext::SetSPKSignatureFile(const std::string& filename) { spkSignFile = filename; if (spkSignFile != "") { ParseSPKSignatureFile(filename); } } /******************************************************************************/ void AuthenticationContext::ParseSPKSignatureFile(const std::string& filename) { GetPresign(filename, spksignature, 0); spkSignLoaded = true; spkSignRequested = ""; } /******************************************************************************/ void AuthenticationContext::SetBHSignatureFile(const std::string& filename) { bhSignFile = filename; if (bhSignFile != "") { ParseBHSignatureFile(filename); } } /******************************************************************************/ void AuthenticationContext::ParseBHSignatureFile(const std::string& filename) { GetPresign(filename, bHsignature, 0); bhSignLoaded = true; } /******************************************************************************/ AuthenticationCertificate::AuthenticationCertificate(AuthenticationContext* context) : AuthContext(context) , fsbl(false) , isTableHeader(false) { } /******************************************************************************/ void AuthenticationCertificate::Build(BootImage& bi, Binary& cache, Section* dataSection, bool fsbl0, bool isTableHeader0) { if (fsbl0 && (this->AuthContext->spkSelect != SpkSelect::SPK_eFUSE)) { LOG_ERROR("Bootloader partition can have only 'spk_select=spk-efuse'"); } /* If User - eFuse, SPK_ID mandatory - b/n 0x1 - 0x100 - else ERROR */ if (this->AuthContext->spkSelect == SpkSelect::USER_eFUSE) { if ((this->AuthContext->spkIdentification == 0) || (this->AuthContext->spkIdentification > 0x100)) { LOG_ERROR("spk_id can only take values from 0x1 to 0x100, if spk_select=user-efuse"); } } section = this->AuthContext->CreateCertificate(bi, cache, dataSection); fsbl = fsbl0; isTableHeader = isTableHeader0; } /******************************************************************************/ void AuthenticationCertificate::Link(BootImage& bi, Section* dataSection) { /* Gather up all the sections that will be used to calculate the authentication hash */ std::list sections; Section* headers = NULL; ImageHeaderTable* iHT = bi.imageHeaderTable; if (isTableHeader) { /* Header section */ sections.push_back(iHT->section); /* Append all image and partition headers */ for(std::list::iterator img = bi.imageList.begin(); img!= bi.imageList.end(); img++) { sections.push_back((*img)->section); } for(std::list::iterator part = bi.partitionHeaderList.begin(); part!= bi.partitionHeaderList.end(); part++) { sections.push_back((*part)->section); } sections.push_back(bi.nullPartHeaderSection); /* Create one new combined section with all the appended sections above */ size_t size = this->section->Address - iHT->section->Address; headers = new Section("Headers",size); headers->Address = iHT->section->Address; // not really needed, but useful for debug. memset(headers->Data, bi.options.GetOutputFillByte(), headers->Length); Binary::Address_t start = sections.front()->Address; for(SectionList::iterator i = sections.begin(); i != sections.end(); i++) { Section& section(**i); int offset = section.Address - start; memcpy(headers->Data + offset, section.Data, section.Length); } /* Replace sections list with the combined new section */ sections.clear(); sections.push_back(headers); } else { /* Partition section */ Section* bHSec = AttachBootHeaderToFsbl(bi); if(bHSec !=NULL) { sections.push_back(bHSec); } else { sections.push_back(dataSection); } } /* Link the certificate - pass for signing */ this->AuthContext->Link(bi, sections, this); if(headers != NULL) { delete headers; } } /******************************************************************************/ Section* RSA2048AuthenticationCertificate::AttachBootHeaderToFsbl(BootImage& bi) { /* If section is a bootloader section, prepend bootheader to this section */ if (fsbl) { BootHeader* bH = bi.bootHeader; Section* bhfsbl; size_t bHSecLen = bH->section->Length; size_t fsblSecLen = bi.partitionHeaderList.front()->partition->section->Length; bhfsbl = new Section("Bhfsbl", (bHSecLen + fsblSecLen)); bhfsbl->Address = bH->section->Address; if (bHSecLen != bH->GetBootHeaderSize() + bH->GetRegInitTableSize()) { LOG_DEBUG(DEBUG_STAMP, "AC size is incorrect during Link - Section Length - %d, BootHeader Size - %d", bHSecLen, bH->GetBootHeaderSize() + bH->GetRegInitTableSize()); LOG_ERROR("Authentication error !!!"); } memcpy(bhfsbl->Data, bH->section->Data, bHSecLen); memcpy(bhfsbl->Data + bHSecLen, bi.partitionHeaderList.front()->partition->section->Data, fsblSecLen); return bhfsbl; } else { return NULL; } } /******************************************************************************/ void AuthenticationAlgorithm::RSA_Exponentiation(const uint8_t *base, const uint8_t* modular, const uint8_t *modular_ext, const uint8_t *exponent, uint8_t *result0) { BIGNUM result; BIGNUM a; // base BIGNUM power; // exponent BIGNUM m; // modulus BN_CTX_Class ctxInst; BN_MONT_CTX_Class montClass(ctxInst); uint16_t keyLength = AuthenticationContext::GetRsaKeyLength(); a.d = (BN_ULONG*)base; a.dmax = keyLength / sizeof(BN_ULONG); a.top = keyLength / sizeof(BN_ULONG); a.flags = 0; a.neg = 0; power.d = (BN_ULONG*)exponent; power.dmax = keyLength / sizeof(BN_ULONG); power.top = keyLength / sizeof(BN_ULONG); power.flags = 0; power.neg = 0; m.d = (BN_ULONG*)modular; m.dmax = keyLength / sizeof(BN_ULONG); m.top = keyLength / sizeof(BN_ULONG); m.flags = 0; m.neg = 0; montClass.Set(m); uint8_t* sanityExtension = new uint8_t[keyLength]; montClass.GetModulusExtension(sanityExtension, m, keyLength); int comp = memcmp(sanityExtension, modular_ext, keyLength); delete[] sanityExtension; if (comp) { LOG_ERROR("Internal Error : Montgomery Reduction is not same as externally calculated value."); } result.d = (BN_ULONG*)result0; result.dmax = keyLength / sizeof(BN_ULONG); result.flags = 0; result.neg = 0; result.top = 0; int ret = BN_mod_exp_mont(&result, &a, &power, &m, ctxInst.ctx, montClass.mont); if (ret != 1) { LOG_DEBUG(DEBUG_STAMP, "Error in calculating Modulus Exponent"); LOG_ERROR("Authentication Error !!!"); } } /******************************************************************************/ void RSAAuthenticationAlgorithm::CreateSignature(const uint8_t* base, uint8_t* primaryKey, uint8_t* result0) { RSA_Exponentiation(base, ((Key*)primaryKey)->N, ((Key*)primaryKey)->N_ext, ((Key*)primaryKey)->D, result0); } /******************************************************************************/ NoneAuthenticationContext::NoneAuthenticationContext() { authAlgorithm = new NoneAuthenticationAlgorithm(); } xilinx-bootgen-2024.2/authentication.h000077500000000000000000000306461475706442400177720ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _AUTHENTICATION_H_ #define _AUTHENTICATION_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include "binary.h" #include "baseclass.h" #include "bootgenenum.h" #include "authkeys.h" #include "hash.h" #include "systemutils.h" #if OPENSSL_VERSION_NUMBER > 0x10100000L #include "xil-bignum.h" #endif /* Forward class references */ class BaseThing; class Section; class BootImage; class Binary; class AuthenticationCertificate; class PartitionHeader; class Key; class VersalKey; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define T_PAD_LENGTH 19 #define UDF_DATA_SIZE 56 #define AUTH_HEADER 0x115 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class RSA_Class { public: RSA_Class() { rsa = NULL; } ~RSA_Class() { if(rsa != NULL) { RSA_free(rsa); } } RSA* rsa; }; /******************************************************************************/ class BN_CTX_Class { public: BN_CTX_Class() { ctx = BN_CTX_new(); if (ctx == NULL) { std::string logmsg = "Failed to allocate BN_CTX_new"; LOG_ERROR(logmsg.c_str()); } } ~BN_CTX_Class() { if (ctx != NULL) { BN_CTX_free(ctx); } } BN_CTX* ctx; }; /******************************************************************************/ class BN_MONT_CTX_Class { public: BN_MONT_CTX_Class(BN_CTX_Class& ctxInst) { mont=BN_MONT_CTX_new(); if (mont == NULL) { LOG_ERROR("Failed to allocate BN_MONT_CTX_new"); } ctx = ctxInst.ctx; } ~BN_MONT_CTX_Class() { if (mont != NULL) { BN_MONT_CTX_free(mont); } } void Set(BIGNUM& m) { if (!BN_MONT_CTX_set(mont,&m, ctx)) { LOG_ERROR("Failed to calculated montgomery reduction in BN_MONT_CTX_set"); } } void GetModulusExtension(uint8_t* ptr, BIGNUM& m, size_t len) { if(len == RSA_2048_KEY_LENGTH) { if (len != mont->RR.top * sizeof(BN_ULONG)) { LOG_ERROR("Sanity check in GetModulusExtension Failed"); } memcpy(ptr,mont->RR.d,len); } else { BIGNUM *r = BN_new(); BIGNUM *res = BN_new(); BIGNUM *m_x = BN_new(); if( r == NULL || res == NULL || m_x == NULL) { LOG_ERROR("Failed to allocate BN_new"); } BN_one(r); BN_lshift(res, r, 4160); BN_mod_mul(m_x, res, res, &m, ctx); memcpy(ptr, m_x->d, RSA_4096_KEY_LENGTH); BN_free(r); BN_free(res); BN_free(m_x); } } BN_CTX* ctx; BN_MONT_CTX* mont; }; /******************************************************************************/ class AuthenticationAlgorithm { public: AuthenticationAlgorithm() { }; ~AuthenticationAlgorithm() { }; virtual Authentication::Type Type() = 0; virtual void CreateSignature(const uint8_t *base, uint8_t* primaryKey, uint8_t *result0) {}; void RSA_Exponentiation(const uint8_t *base, const uint8_t* modular, const uint8_t *modular_ext, const uint8_t *exponent, uint8_t *result0); virtual void RearrangeEndianess(uint8_t *array, uint32_t size) {}; virtual void CreatePadding(uint8_t* signature, uint8_t* hash, uint8_t hashLength) {}; virtual uint32_t GetAuthHeader(void) { return AUTH_HEADER; } virtual int KeySize() { return 0; } }; /******************************************************************************/ class RSAAuthenticationAlgorithm : public AuthenticationAlgorithm { public: RSAAuthenticationAlgorithm() { }; ~RSAAuthenticationAlgorithm() { }; Authentication::Type Type() { return Authentication::RSA; } void CreateSignature(const uint8_t* base, uint8_t* primaryKey, uint8_t* result0); }; /******************************************************************************/ class NoneAuthenticationAlgorithm : public AuthenticationAlgorithm { public: NoneAuthenticationAlgorithm() { }; ~NoneAuthenticationAlgorithm() { }; Authentication::Type Type() { return Authentication::None; } }; /******************************************************************************/ class AuthenticationContext { public: AuthenticationContext() : primaryKey(NULL) , secondaryKey(NULL) , hash(NULL) , spkSignLoaded(false) , bhSignLoaded(false) , spksignature(NULL) , bHsignature(NULL) , hashType(AuthHash::Sha2) , ppkSelect(0) , spkSelect(1) , spkIdentification(0) , acIndex(0) , authBlocks(0) , certIndex(0) , preSigned(false) , isHeaderAuthentication(false) , authAlgorithm(NULL) , authCertificate (NULL) , ppkFile("") , pskFile("") , spkFile("") , sskFile("") , firstChunkSize(0) , signatureLength(0) { }; virtual ~AuthenticationContext() { }; virtual uint32_t GetCertificateSize() { return 0; } virtual void ResizeIfNecessary(Section* section); virtual Section* CreateCertificate(BootImage& bi, Binary& cache, Section* dataSection) { return NULL; } virtual void Link(BootImage& bi, std::list sections, AuthenticationCertificate* cert) { } virtual void GeneratePPKHash(const std::string& filename) {} virtual void GenerateSPKHash(uint8_t* sha256_hash_padded) {} virtual void GenerateSPKHashFile(const std::string& filename, Hash* hashObj); virtual void GenerateSPKSignature(const std::string& filename); virtual void GenerateBHHash(BootImage& bi, uint8_t* sha_hash_padded) {}; virtual void GenerateBHSignature() {}; virtual void CreatePadding(uint8_t* signature, const uint8_t* hash) {}; virtual void CopyPartitionSignature(BootImage& bi, std::list sections, uint8_t* signatureBlock, Section* acSection) {}; virtual void RearrangeEndianess(uint8_t *array, uint32_t size) {}; virtual void AddAuthCertSizeToTotalFSBLSize(PartitionHeader* header) {}; virtual void CopySPKSignature(uint8_t* ptr) {}; virtual void SetKeyLength(Authentication::Type type) {}; void CreateSPKSignature(void); void SetSPKSignatureFile(const std::string & filename); void ParseSPKSignatureFile(const std::string & filename); void SetBHSignatureFile(const std::string & filename); void ParseBHSignatureFile(const std::string & filename); void GetPresign(const std::string& presignFilename, uint8_t* signature, uint32_t index); void GetAC(const std::string& presignFilename, uint8_t* signature, uint32_t index); void LoadUdfData(const std::string & udfFilename, uint8_t * signature); void WritePaddedSHAFile(const uint8_t * shaBuf, const std::string & hashfilename); void SetPresignFile(const std::string& filename); void SetACFile(const std::string& filename); void SetUdfFile(const std::string& filename); void SetPSKeyFile(const std::string& filename); void ParsePSKeyFile(const std::string& filename); void SetPPKeyFile(const std::string& filename); void ParsePPKeyFile(const std::string & filename); void SetSSKeyFile(const std::string& filename); void ParseSSKeyFile(const std::string& filename); void SetSPKeyFile(const std::string& filename); void ParseSPKeyFile(const std::string& filename); void SetPpkSelect(uint32_t ppk); void SetSpkSelect(uint32_t spk); void SetSpkIdentification(uint32_t spkid); void SetHeaderAuthentication(uint32_t headerauth); void SetHashType(AuthHash::Type); void SetFirstChunkSize(uint64_t); AuthHash::Type GetHashType(void); uint64_t GetFirstChunkSize(void) { return firstChunkSize; } static void SetAuthenticationKeyLength(uint16_t); static uint16_t GetRsaKeyLength(void); void SetSignatureLength(uint16_t signLength); uint16_t GetSignatureLength(void); static size_t GetauthBlocks(size_t authblocks); static bool GetZynpMpVerEs1Flag(void); static void SetZynpMpVerEs1Flag(bool isEs1); int acIndex; int certIndex; Hash *hash; uint8_t udf_data[UDF_DATA_SIZE]; bool spkSignLoaded; bool bhSignLoaded; std::string spkSignRequested; uint8_t* spksignature; uint8_t* bHsignature; AuthHash::Type hashType; size_t authBlocks; bool preSigned; std::string ppkFile; std::string pskFile; std::string spkFile; std::string sskFile; uint32_t ppkSelect; uint32_t spkSelect; uint32_t spkIdentification; bool isHeaderAuthentication; std::string spkSignFile; std::string bhSignFile; Key *primaryKey; Key *secondaryKey; AuthenticationAlgorithm *authAlgorithm; AuthenticationCertificate *authCertificate; uint16_t signatureLength; std::string presignFile; std::string acFile; std::string udfFile; protected: static uint16_t authKeyLength; static uint8_t hashLength; static bool zynpmpVerEs1; uint64_t firstChunkSize; }; /******************************************************************************/ class NoneAuthenticationContext : public AuthenticationContext { public: NoneAuthenticationContext(); void ResizeIfNecessary(Section* section) {}; }; /******************************************************************************/ class AuthenticationCertificate : public BaseThing { public: AuthenticationCertificate(AuthenticationContext* context); AuthenticationCertificate() {}; void Build(BootImage& bi, Binary& cache, Section* section, bool fsbl, bool isTableHeader); virtual void Link(BootImage& bi, Section* section); virtual Section* AttachBootHeaderToFsbl(BootImage& bi) { return NULL; } AuthenticationContext* AuthContext; bool fsbl; bool isTableHeader; }; /******************************************************************************/ class RSA2048AuthenticationCertificate : public AuthenticationCertificate { public: RSA2048AuthenticationCertificate(AuthenticationContext* context) : AuthenticationCertificate(context) { } RSA2048AuthenticationCertificate() { }; Section* AttachBootHeaderToFsbl(BootImage& bi); }; /******************************************************************************/ class RSA4096AuthenticationCertificate : public AuthenticationCertificate { public: RSA4096AuthenticationCertificate(AuthenticationContext* context) : AuthenticationCertificate(context) { } RSA4096AuthenticationCertificate() { }; }; #endif xilinx-bootgen-2024.2/authkeys-versal.cpp000077500000000000000000000506061475706442400204330ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "authkeys-versal.h" #include "authentication-versal.h" #include "options.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalKey::VersalKey(const std::string& name0) : Key(name0) { if (keySize == RSA_4096_KEY_LENGTH) { //Do Nothing eckey = nullptr; } else if (keySize == EC_P384_KEY_LENGTH) { keySizeX = keySizeY = keySize; eckey = EC_KEY_new_by_curve_name(NID_secp384r1); } else { eckey = EC_KEY_new_by_curve_name(NID_secp521r1); } x = nullptr; y = nullptr; } /******************************************************************************/ VersalKey::VersalKey(const Key& otherKey) :Key(otherKey) { // ECDSA if (keySize == RSA_4096_KEY_LENGTH) { //Do Nothing } else if (keySize == EC_P384_KEY_LENGTH) { eckey = EC_KEY_new_by_curve_name(NID_secp384r1); } else { eckey = EC_KEY_new_by_curve_name(NID_secp521r1); } memcpy(this, &otherKey, sizeof(Key)); } /******************************************************************************/ VersalKey::~VersalKey() { if (x != NULL) { delete[] x; x = nullptr; } if (y != NULL) { delete[] y; y = nullptr; } if (eckey != NULL) { EC_KEY_free(eckey); eckey = nullptr; } } /******************************************************************************/ void Key4096Sha3Padding::Export(void* acKey) { ACKey4096Sha3Padding* key = (ACKey4096Sha3Padding*)acKey; if (!Loaded) { std::string pubsec = (isSecret) ? " (Secret)" : " (Public)"; LOG_ERROR("%s - $s is not loaded", name.c_str(), pubsec.c_str()); } memset(key, 0, VERSAL_ACKEY_STRUCT_SIZE); memcpy(key->N, N, keySize); memcpy(key->N_extension, N_ext, keySize); memcpy(key->E, E, 4); } /******************************************************************************/ void Key4096Sha3Padding::Import(const void* acKey, const std::string& name0) { ACKey4096Sha3Padding* key = (ACKey4096Sha3Padding*)acKey; Loaded = true; isSecret = false; name = name0; memcpy(N, key->N, keySize); memcpy(N_ext, key->N_extension, keySize); memcpy(E, key->E, sizeof(uint32_t)); memset(P, 0, keySize / 2); memset(Q, 0, keySize / 2); // Fill secret exponent with zeros memset(D, 0, keySize); } /******************************************************************************/ void KeyECDSA::Export(void * acKey) { ACKeyECDSA* key = (ACKeyECDSA*)acKey; if (!Loaded) { std::string pubsec = (isSecret) ? " (Secret)" : " (Public)"; LOG_ERROR("%s - $s is not loaded", name.c_str(), pubsec.c_str()); } memset(key, 0, sizeof(ACKeyECDSA)); memcpy(key->x, x, keySize); memcpy(key->y, y, keySize); memset(key->pad, 0, sizeof(key->pad)); } /******************************************************************************/ void KeyECDSA::Import(const void * acKey, const std::string & name0) { ACKeyECDSA* key = (ACKeyECDSA*)acKey; Loaded = true; isSecret = false; name = name0; x = new uint8_t[keySize]; memset(x, 0, keySize); y = new uint8_t[keySize]; memset(y, 0, keySize); memcpy(x, key->x, keySize); memcpy(y, key->y, keySize); memset(key->pad, 0, sizeof(key->pad)); // Fill secret exponent with zeros memset(D, 0, keySize); } /******************************************************************************/ void KeyECDSAp521::Export(void * acKey) { ACKeyECDSAP521* key = (ACKeyECDSAP521*)acKey; if (!Loaded) { std::string pubsec = (isSecret) ? " (Secret)" : " (Public)"; LOG_ERROR("%s - $s is not loaded", name.c_str(), pubsec.c_str()); } memset(key, 0, sizeof(ACKeyECDSAP521)); if (keySizeX == EC_P521_KEY_LENGTH1) { memcpy((key->x) + 1, x, keySizeX); } else { memcpy(key->x, x, keySizeX); } if (keySizeY == EC_P521_KEY_LENGTH1) { memcpy((key->y)+1, y, keySizeY); } else { memcpy(key->y, y, keySizeY); } memset(key->pad, 0, sizeof(key->pad)); } /******************************************************************************/ void KeyECDSAp521::Import(const void * acKey, const std::string & name0) { ACKeyECDSAP521* key = (ACKeyECDSAP521*)acKey; Loaded = true; isSecret = false; name = name0; x = new uint8_t[keySizeX]; y = new uint8_t[keySizeY]; memset(x, 0, keySizeX); memset(y, 0, keySizeY); memcpy(x, key->x, keySizeX); memcpy(y, key->y, keySizeY); memset(key->pad, 0, sizeof(key->pad)); // Fill secret exponent with zeros memset(D, 0, keySize); } /******************************************************************************/ static void RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; // If array is NULL, return if (!array) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /******************************************************************************/ uint8_t VersalKey::ParseECDSAOpenSSLKey(const std::string& filename) { OpenSSL_add_all_algorithms(); BIGNUM *X = BN_new(); X->flags = 0; X->neg = 0; X->top = 0; BIGNUM *Y = BN_new(); Y->flags = 0; Y->neg = 0; Y->top = 0; uint32_t keySzRdX; uint32_t keySzRdY; FILE* file; file = fopen(filename.c_str(), "r"); if (file == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } if (isSecret) { eckey = PEM_read_ECPrivateKey(file, NULL, NULL, NULL); if (!EC_KEY_check_key(eckey)) { LOG_TRACE("Failed to check EC Key\n"); } else { EC_GROUP *ecgroup; if (keySize == EC_P384_KEY_LENGTH) { x = new uint8_t[keySize]; y = new uint8_t[keySize]; memset(x, 0, keySize); memset(y, 0, keySize); X->d = (BN_ULONG*)x; Y->d = (BN_ULONG*)y; X->dmax = keySize / sizeof(BN_ULONG); Y->dmax = keySize / sizeof(BN_ULONG); ecgroup = EC_GROUP_new_by_curve_name(NID_secp384r1); const EC_POINT *pub = EC_KEY_get0_public_key(eckey); if (EC_POINT_get_affine_coordinates_GFp(ecgroup, pub, X, Y, NULL)) { keySzRdX = BN_num_bytes(X); if (keySzRdX != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(X), keySize * 8); } keySzRdY = BN_num_bytes(Y); if (keySzRdY != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(Y), keySize * 8); } RearrangeEndianess(x, keySize); RearrangeEndianess(y, keySize); } else { LOG_ERROR("Failed to parse key %s for ECDSAp384",filename.c_str()); } } else { ecgroup = EC_GROUP_new_by_curve_name(NID_secp521r1); const EC_POINT *pub = EC_KEY_get0_public_key(eckey); if (EC_POINT_get_affine_coordinates_GFp(ecgroup, pub, X, Y, NULL)) { keySizeX = BN_num_bytes(X); if (keySizeX != EC_P521_KEY_LENGTH1 && keySizeX != EC_P521_KEY_LENGTH2) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(X), 521); } keySizeY = BN_num_bytes(Y); if (keySizeY != EC_P521_KEY_LENGTH1 && keySizeY != EC_P521_KEY_LENGTH2) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(Y), 521); } x = new uint8_t[keySizeX]; y = new uint8_t[keySizeY]; memset(x, 0, keySizeX); memset(y, 0, keySizeY); memcpy(x, X->d, keySizeX); memcpy(y, Y->d, keySizeY); RearrangeEndianess(x, keySizeX); RearrangeEndianess(y, keySizeY); } else { LOG_ERROR("Failed to parse key %s for ECDSAp521",filename.c_str()); } } } } else { eckey = PEM_read_EC_PUBKEY(file, NULL, NULL, NULL); if (!EC_KEY_check_key(eckey)) { LOG_TRACE("Failed to check EC Key\n"); } else { EC_GROUP *ecgroup; if (keySize == EC_P384_KEY_LENGTH) { x = new uint8_t[keySize]; y = new uint8_t[keySize]; memset(x, 0, keySize); memset(y, 0, keySize); X->d = (BN_ULONG*)x; Y->d = (BN_ULONG*)y; X->dmax = keySize / sizeof(BN_ULONG); Y->dmax = keySize / sizeof(BN_ULONG); ecgroup = EC_GROUP_new_by_curve_name(NID_secp384r1); const EC_POINT *pub = EC_KEY_get0_public_key(eckey); if (EC_POINT_get_affine_coordinates_GFp(ecgroup, pub, X, Y, NULL)) { keySzRdX = BN_num_bytes(X); if (keySzRdX != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(X), keySize * 8); } keySzRdY = BN_num_bytes(Y); if (keySzRdY != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(Y), keySize * 8); } RearrangeEndianess(x, keySize); RearrangeEndianess(y, keySize); } else { LOG_ERROR("Failed to parse key %s for ECDSAp384",filename.c_str()); } } else { ecgroup = EC_GROUP_new_by_curve_name(NID_secp521r1); const EC_POINT *pub = EC_KEY_get0_public_key(eckey); if (EC_POINT_get_affine_coordinates_GFp(ecgroup, pub, X, Y, NULL)) { keySizeX = BN_num_bytes(X); if (keySizeX != EC_P521_KEY_LENGTH1 && keySizeX != EC_P521_KEY_LENGTH2) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(X), 521); } keySizeY = BN_num_bytes(Y); if (keySizeY != EC_P521_KEY_LENGTH1 && keySizeY != EC_P521_KEY_LENGTH2) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", BN_num_bits(Y), 521); } x = new uint8_t[keySizeX]; y = new uint8_t[keySizeY]; memset(x, 0, keySizeX); memset(y, 0, keySizeY); memcpy(x, X->d, keySizeX); memcpy(y, Y->d, keySizeY); RearrangeEndianess(x, keySizeX); RearrangeEndianess(y, keySizeY); } else { LOG_ERROR("Failed to parse key %s for ECDSAp521",filename.c_str()); } } } } fclose(file); return 0; } /******************************************************************************/ void VersalKey::Parse(const std::string& filename, bool isSecret0) { uint8_t errCode = 0; isSecret = isSecret0; std::string basefile = StringUtils::BaseName(filename); std::ifstream File(filename.c_str()); std::string word; File >> word; File >> word; if (!isSecret) { FILE* f; f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } RSA* rsa = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); fclose(f); f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } EC_KEY *eckeyLocal = PEM_read_EC_PUBKEY(f, NULL, NULL, NULL); fclose(f); if (rsa != NULL) { if(authType == Authentication :: RSA) { keySize = 0x200; RSA_free(rsa); FILE* f; f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } try { int name; do { name = getc(f); } while (name >= 0 && isspace(name)); fseek(f, 0, 0); // rewind /* If the file starts with 'N', then it is AMD Format If it starts with '-', then it is OpenSSL format */ if (name == 'N') { LOG_INFO("Parsing RSA key (AMD Format)"); errCode = ParseAMDRsaKey(f); } else if (name == '-') { LOG_INFO("Parsing RSA key (OpenSSL Format)"); errCode = ParseOpenSSLKey(f); } else { LOG_ERROR("Unsupported key file - %s\n Supported key formats: AMD Format & OpenSSL format", basefile.c_str()); } fclose(f); if (errCode != 0) { LOG_ERROR("RSA authentication key parsing failed - %s", basefile.c_str()); } /* Calculate the modulus extension, i.e. Montgomery Reduction term RR and some sanity check for the keys passed */ { BIGNUM m; // modulus m.d = (BN_ULONG*)N; m.dmax = keySize / sizeof(BN_ULONG); m.top = keySize / sizeof(BN_ULONG); m.flags = 0; m.neg = 0; BN_CTX_Class ctxInst; BN_MONT_CTX_Class montClass(ctxInst); montClass.Set(m); montClass.GetModulusExtension(N_ext, m, keySize); } Loaded = true; } catch (...) { fclose(f); throw; } } else { LOG_ERROR("RSA keys are specified for ECDSAp384/ECDSAp521 authentication. Keyname is -%s",filename.c_str()); } } else if (eckeyLocal != NULL) { if(authType != Authentication::RSA) { LOG_INFO("Parsing EC key (OpenSSL Format)"); if (authType == Authentication::ECDSA) { keySize = 0x30; } errCode = ParseECDSAOpenSSLKey(filename); Loaded = true; } else { LOG_ERROR("ECDSA keys are specified for RSA authentication. Keyname is - %s",filename.c_str()); } } } else { // EC key if (word == "EC" ) { if(authType != Authentication :: RSA) { LOG_INFO("Parsing EC key (OpenSSL Format)"); errCode = ParseECDSAOpenSSLKey(filename); Loaded = true; } else { LOG_ERROR("ECDSA keys are specified for RSA authentication. Keyname is - %s",filename.c_str()); } } // RSA key else { if(authType == Authentication :: RSA) { FILE* f; f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } try { int name; do { name = getc(f); } while (name >= 0 && isspace(name) && name != EOF); fseek(f, 0, 0); // rewind /* If the file starts with 'N', then it is AMD Format. If it starts with '-', then it is OpenSSL format */ if (name == 'N') { LOG_INFO("Parsing RSA key (AMD Format)"); errCode = ParseAMDRsaKey(f); } else if (name == '-') { LOG_INFO("Parsing RSA key (OpenSSL Format)"); errCode = ParseOpenSSLKey(f); } else { LOG_ERROR("Unsupported key file - %s\n Supported key formats: AMD Format & OpenSSL format", basefile.c_str()); } fclose(f); if (errCode != 0) { LOG_ERROR("RSA authentication key parsing failed - %s", basefile.c_str()); } /* Calculate the modulus extension, i.e. Montgomery Reduction term RR and some sanity check for the keys passed */ { BIGNUM m; // modulus m.d = (BN_ULONG*)N; m.dmax = keySize / sizeof(BN_ULONG); m.top = keySize / sizeof(BN_ULONG); m.flags = 0; m.neg = 0; BN_CTX_Class ctxInst; BN_MONT_CTX_Class montClass(ctxInst); montClass.Set(m); montClass.GetModulusExtension(N_ext, m, keySize); } Loaded = true; } catch (...) { fclose(f); throw; } } else { LOG_ERROR("RSA keys are specified for ECDSAp384/ECDSAp521 authentication. Keyname is -%s",filename.c_str()); } } } } xilinx-bootgen-2024.2/authkeys-versal.h000077500000000000000000000107621475706442400200770ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _AUTH_KEYS_VERSAL_H_ #define _AUTH_KEYS_VERSAL_H_ /* ------------------------------------------------------------------------------- ************************************************************ HEADER FILES ***** ------------------------------------------------------------------------------- */ #include #include #include "logger.h" #include #include #include #include #include #include "authkeys.h" /* ------------------------------------------------------------------------------- *********************************************************** PREPROCESSORS ***** ------------------------------------------------------------------------------- */ //AC key related defines #define RSA_4096_N 0x0 #define RSA_4096_N_EXT 0x200 #define RSA_4096_E 0x400 #define VERSAL_ACKEY_STRUCT_SIZE 1028 #define RSA_4096_N_SIZE 512 #define RSA_4096_N_EXT_SIZE 512 #define RSA_4096_E_SIZE 4 /* ------------------------------------------------------------------------------- ************************************************************** STRUCTURES ***** ------------------------------------------------------------------------------- */ typedef struct { uint8_t N[RSA_4096_KEY_LENGTH]; // Modulus uint8_t N_extension[RSA_4096_KEY_LENGTH]; // Montgomery Modulus extension uint8_t E[4]; // Exponent } ACKey4096Sha3Padding; typedef struct { uint8_t x[EC_P384_KEY_LENGTH]; // x co-ordinate uint8_t y[EC_P384_KEY_LENGTH]; // y co-ordinate uint8_t pad[932]; // Padding } ACKeyECDSA; typedef struct { uint8_t x[EC_P521_KEY_LENGTH2]; // x co-ordinate uint8_t y[EC_P521_KEY_LENGTH2]; // y co-ordinate uint8_t pad[896]; // Padding } ACKeyECDSAP521; typedef struct { uint8_t Signature[SIGN_LENGTH_VERSAL]; } ACSignatureECDSA; /* ------------------------------------------------------------------------------- ***************************************************************** CLASSES ***** ------------------------------------------------------------------------------- */ class VersalKey : public Key { public: VersalKey(const std::string& name0); VersalKey(const Key& otherKey); ~VersalKey(); void Parse(const std::string& filename, bool isSecret0); uint8_t ParseECDSAOpenSSLKey(const std::string& filename); EC_KEY *eckey; uint8_t *x; // x co-ordinate (384 bits) uint8_t *y; // y co-ordinate (384 bits) }; /******************************************************************************/ class Key4096Sha3Padding : public VersalKey { public: Key4096Sha3Padding(const std::string& name0) : VersalKey(name0) { } Key4096Sha3Padding(const Key4096Sha3Padding& otherKey) : VersalKey(otherKey) { } void Export(void* dst); void Import(const void* acKey, const std::string& name0); }; /******************************************************************************/ class KeyECDSA : public VersalKey { public: KeyECDSA(const std::string& name0) : VersalKey(name0) { } KeyECDSA(const KeyECDSA& otherKey) : VersalKey(otherKey) { } void Export(void* dst); void Import(const void* acKey, const std::string& name0); }; /******************************************************************************/ class KeyECDSAp521 : public VersalKey { public: KeyECDSAp521(const std::string& name0) : VersalKey(name0) { } KeyECDSAp521(const KeyECDSAp521& otherKey) : VersalKey(otherKey) { } void Export(void* dst); void Import(const void* acKey, const std::string& name0); }; #endif xilinx-bootgen-2024.2/authkeys.cpp000077500000000000000000000540571475706442400171450ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "authkeys.h" #include "authentication.h" #include "options.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ Key::Key(const std::string& name0) : Loaded(false) , isSecret(false) , name(name0) { keySize = AuthenticationContext::GetRsaKeyLength(); N = new uint8_t [keySize]; N_ext = new uint8_t [keySize]; D = new uint8_t [keySize]; E = new uint8_t [WORD_SIZE_IN_BYTES]; P = new uint8_t [keySize/2]; Q = new uint8_t [keySize/2]; memset(N, 0, keySize); memset(N_ext, 0, keySize); memset(E, 0, WORD_SIZE_IN_BYTES); memset(P, 0, keySize/2); memset(Q, 0, keySize/2); memset(D, 0, keySize); } /******************************************************************************/ Key::Key(const Key& otherKey) { keySize = AuthenticationContext::GetRsaKeyLength(); N = new uint8_t [keySize]; N_ext = new uint8_t [keySize]; D = new uint8_t [keySize]; E = new uint8_t [WORD_SIZE_IN_BYTES]; P = new uint8_t [keySize/2]; Q = new uint8_t [keySize/2]; memcpy(this,&otherKey,sizeof(Key)); } /******************************************************************************/ Key::~Key() { if(N != NULL) { delete[] N; N = nullptr; } if(N_ext != NULL) { delete[] N_ext; N_ext = nullptr; } if(D != NULL) { delete[] D; D = nullptr; } if(E != NULL) { delete[] E; E = nullptr; } if(P != NULL) { delete[] P; P = nullptr; } if(Q != NULL) { delete[] Q; Q = nullptr; } } /******************************************************************************/ void Key::ParsePublic(const std::string& filename) { Parse(filename,false); } /******************************************************************************/ void Key::ParseSecret(const std::string& filename) { Parse(filename,true); } /******************************************************************************/ void Key::Parse(const std::string& filename, bool isSecret0) { uint8_t errCode = 0; isSecret = isSecret0; std::string basefile = StringUtils::BaseName(filename); FILE* f; f = fopen(filename.c_str(),"r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } try { int name; do { name = getc(f); } while (name >= 0 && isspace(name) && name != EOF); fseek(f,0,0); /* If the file starts with 'N', then it is AMD Format If it starts with '-', then it is OpenSSL format */ if (name == 'N') { errCode = ParseAMDRsaKey(f); } else if (name == '-') { errCode = ParseOpenSSLKey(f); } else { LOG_ERROR("Unsupported key file - %s\n Supported key formats: AMD Format & OpenSSL format", basefile.c_str()); } fclose(f); if(errCode != 0) { LOG_ERROR("RSA authentication key parsing failed - %s", basefile.c_str()); } /* Calculate the modulus extension, i.e. Montgomery Reduction term RR and some sanity check for the keys passed */ { BIGNUM m; m.d = (BN_ULONG*)N; m.dmax = keySize / sizeof(BN_ULONG); m.top = keySize / sizeof(BN_ULONG); m.flags = 0; m.neg = 0; BN_CTX_Class ctxInst; BN_MONT_CTX_Class montClass(ctxInst); montClass.Set(m); montClass.GetModulusExtension(N_ext, m, keySize); } Loaded = true; } catch(...) { fclose(f); throw; } } /******************************************************************************/ uint8_t Key::ParseOpenSSLKey(FILE* f) { RSA_Class rsaInst; OpenSSL_add_all_algorithms(); uint32_t keySzRd; if (isSecret) { rsaInst.rsa = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); if(rsaInst.rsa == NULL) { return 1; } #if OPENSSL_VERSION_NUMBER > 0x10100000L keySzRd = BN_num_bytes(RSA_get0_n(rsaInst.rsa)); #else keySzRd = BN_num_bytes(rsaInst.rsa->n); #endif if (keySzRd != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", keySzRd * 8, keySize * 8); } #if OPENSSL_VERSION_NUMBER > 0x10100000L memcpy(D, RSA_get0_d(rsaInst.rsa)->d, keySize); #else memcpy(D, rsaInst.rsa->d->d, keySize); #endif } else { rsaInst.rsa = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); if(rsaInst.rsa == NULL) { return 1; } #if OPENSSL_VERSION_NUMBER > 0x10100000L keySzRd = BN_num_bytes(RSA_get0_n(rsaInst.rsa)); #else keySzRd = BN_num_bytes(rsaInst.rsa->n); #endif if (keySzRd != keySize) { LOG_ERROR("Incorrect Key Size !!!\n\t Key Size is %d bits. Expected key size is %d bits", keySzRd * 8, keySize * 8); } memset(D,0,keySize); } #if OPENSSL_VERSION_NUMBER > 0x10100000L memcpy(N, RSA_get0_n(rsaInst.rsa)->d, keySize); memcpy(E, RSA_get0_e(rsaInst.rsa)->d, sizeof(uint32_t)); #else memcpy(N, rsaInst.rsa->n->d, keySize); memcpy(E, rsaInst.rsa->e->d, sizeof(uint32_t)); #endif return 0; } /******************************************************************************/ uint8_t Key::ParseAMDRsaKey(FILE* f) { int name; /* Check for N in the key file followed by '=', Once got, parse the value of N */ do { name = getc(f); } while (name >= 0 && isspace(name)); if (name != 'N') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected N, got %c", name); return 1; } do { name = getc(f); } while (name >= 0 && isspace(name)); if (name != '=') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected =, got %c", name); return 1; } LOG_TRACE("Parsing 'N' from key file"); Hex2Byte(f, N, keySize); /* Check for E in the key file followed by '=' Once got, parse the value of E */ do { name = getc(f); } while (name >= 0 && isspace(name)); if (name != 'E') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected E, got %c",name); return 1; } do { name = getc(f); } while (name >= 0 && isspace(name)); if (name != '=') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected =, got %c",name); return 1; } uint32_t temp; LOG_TRACE("Parsing 'E' from key file"); if(EOF != fscanf(f,"%X",&temp)) { E[0] = (uint8_t)(temp); E[1] = (uint8_t)(temp>>8); E[2] = (uint8_t)(temp>>16); E[3] = (uint8_t)(temp>>24); } if (isSecret) { /* Check for D in the key file followed by '=' Once got, parse the value of D */ do { name = getc(f); } while (name >= 0 && isspace(name)); if(name != 'D') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected D, got %c",name); return 1; } do { name = getc(f); } while (name >= 0 && isspace(name) && name != EOF); if (name != '=') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected =, got %c",name); return 1; } LOG_TRACE("Parsing 'D' from key file"); Hex2Byte(f, D, keySize); /* The rest of parsing is for sanity checking purpose Not used for signing or verfication */ /* Check for P in the key file followed by '=' Once got, parse the value of P */ do { name = getc(f); } while (name >= 0 && isspace(name)); if(name == 'P') { do { name = getc(f); } while (name >= 0 && isspace(name)); if (name != '=') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected =, got %c",name); return 1; } LOG_TRACE("Parsing 'P' from key file"); Hex2Byte(f, P, keySize/2); /* Check for Q in the key file followed by '=' Once got, parse the value of Q */ do { name = getc(f); } while (name >= 0 && isspace(name)); if(name != 'Q') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected Q, got %c",name); return 1; } do { name = getc(f); } while (name >= 0 && isspace(name)); if(name != '=') { LOG_DEBUG(DEBUG_STAMP, "Bad Key file, expected =, got %c",name); return 1; } LOG_TRACE("Parsing 'Q' from key file"); Hex2Byte(f, Q, keySize/2); /* Sanity check block, N = PxQ */ { uint8_t *Ncheck = new uint8_t [keySize]; Multiply_p_q(P, Q, Ncheck); if (memcmp(N, Ncheck, keySize)) { delete[] Ncheck; LOG_DEBUG(DEBUG_STAMP, "Inconsistency found in key file, P * Q != N"); return 1; } delete[] Ncheck; } } } else { /* If it is a public key, D=0 */ memset(D, 0, keySize); } return 0; } /******************************************************************************/ void Key::WriteRsaFile(std::string filename, const RSA* rsa, bool secret, uint16_t keyLength) { std::ofstream file(filename.c_str()); bool fileWritten = false; if (file) { uint8_t *temp = new uint8_t[keyLength]; file << "N = "; #if OPENSSL_VERSION_NUMBER > 0x10100000L memcpy(temp, RSA_get0_n(rsa)->d, keyLength); #else memcpy(temp, rsa->n->d, keyLength); #endif for (uint32_t index = keyLength; index != 0; index--) { file << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << int(temp[index - 1]); } file << "\n\nE = "; #if OPENSSL_VERSION_NUMBER > 0x10100000L uint32_t* temp_e = (uint32_t*)RSA_get0_e(rsa)->d; #else uint32_t* temp_e = (uint32_t*)rsa->e->d; #endif file << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << *temp_e; if (secret) { file << "\n\nD = "; #if OPENSSL_VERSION_NUMBER > 0x10100000L memcpy(temp, RSA_get0_d(rsa)->d, keyLength); #else memcpy(temp, rsa->d->d, keyLength); #endif for (uint32_t index = keyLength; index != 0; index--) { file << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << int(temp[index - 1]); } } delete[] temp; fileWritten = !file.bad(); file.close(); } if (!fileWritten) { LOG_ERROR("Failure writing authentication key file : %s", filename.c_str()); } else { LOG_INFO("%s key file generation in RSA format successful", filename.c_str()); } } /******************************************************************************/ void Key::WritePemFile(std::string filename, RSA * rsa, EC_KEY* eckey, bool secret) { FILE* file = fopen(filename.c_str(), "wb"); bool fileWritten = false; if (file) { if (rsa != NULL) { if (!secret) { if (PEM_write_RSA_PUBKEY(file, rsa)) { fileWritten = true; } } else { if (PEM_write_RSAPrivateKey(file, rsa, NULL, NULL, 0, NULL, NULL)) { fileWritten = true; } } fclose(file); } else if (eckey != NULL) { if (!secret) { if (PEM_write_EC_PUBKEY(file, eckey)) { fileWritten = true; } } else { if (PEM_write_ECPrivateKey(file, eckey, NULL, NULL, 0, NULL, NULL)) { fileWritten = true; } } fclose(file); } else { LOG_ERROR("Failed to generate authentication keys for the given algorithm."); } } if (!fileWritten) { LOG_ERROR("Failure writing authentication key file : %s", filename.c_str()); } else { LOG_INFO("%s key file generation in PEM format successful",filename.c_str()); } } /******************************************************************************/ void Key::GenerateRsaKeys(KeyGenerationStruct* keygen) { RSA *rsa = NULL; OpenSSL_add_all_algorithms(); if (!(keygen->ppk_file != "" || keygen->psk_file != "" || keygen->spk_file != "" || keygen->ssk_file != "")) { LOG_ERROR("Failed to generate authentication keys. Please specify the key paths in BIF file"); } if (keygen->ppk_file != "" || keygen->psk_file != "") { if ((rsa = RSA_generate_key(keygen->keyLength * 8, RSA_F4, NULL, NULL)) == NULL) { LOG_ERROR("Failure creating authentication Keys"); } else { if (keygen->format == GenAuthKeys::PEM) { if (keygen->ppk_file != "") { WritePemFile(keygen->ppk_file, rsa, NULL, false); } if (keygen->psk_file != "") { WritePemFile(keygen->psk_file, rsa, NULL, true); } } else { if (keygen->ppk_file != "") { WriteRsaFile(keygen->ppk_file, rsa, false, keygen->keyLength); } if (keygen->psk_file != "") { WriteRsaFile(keygen->psk_file, rsa, true, keygen->keyLength); } } } rsa = NULL; } if (keygen->spk_file != "" || keygen->ssk_file != "") { if ((rsa = RSA_generate_key(keygen->keyLength * 8, RSA_F4, NULL, NULL)) == NULL) { LOG_ERROR("Failure creating authentication Keys"); } else { if (keygen->format == GenAuthKeys::PEM) { if (keygen->spk_file != "") { WritePemFile(keygen->spk_file, rsa, NULL, false); } if (keygen->ssk_file != "") { WritePemFile(keygen->ssk_file, rsa, NULL, true); } } else { if (keygen->spk_file != "") { WriteRsaFile(keygen->spk_file, rsa, false, keygen->keyLength); } if (keygen->ssk_file != "") { WriteRsaFile(keygen->ssk_file, rsa, true, keygen->keyLength); } } } rsa = NULL; } } /************************************************************************************/ void Key::GenerateEcdsaKeys(KeyGenerationStruct* keygen) { EC_KEY* eckey = NULL; OpenSSL_add_all_algorithms(); if (!(keygen->ppk_file != "" || keygen->psk_file != "" || keygen->spk_file != "" || keygen->ssk_file != "")) { LOG_ERROR("Failed to generate authentication keys. Please specify the key paths in BIF file"); } if (keygen->format == GenAuthKeys::ECDSA) { eckey = EC_KEY_new_by_curve_name(NID_secp384r1); } else if(keygen->format == GenAuthKeys::ECDSAP521) { eckey = EC_KEY_new_by_curve_name(NID_secp521r1); } else { eckey = NULL; } if (keygen->ppk_file != "" || keygen->psk_file != "") { if((EC_KEY_generate_key(eckey)) == 0) { LOG_ERROR("Failure creating authentication Keys"); } else { if (keygen->ppk_file != "") { WritePemFile(keygen->ppk_file, NULL, eckey, false); } if (keygen->psk_file != "") { WritePemFile(keygen->psk_file,NULL, eckey, true); } } } if (keygen->spk_file != "" || keygen->ssk_file != "") { if ((EC_KEY_generate_key(eckey)) == 0) { LOG_ERROR("Failure creating authentication Keys"); } else { if (keygen->spk_file != "") { WritePemFile(keygen->spk_file, NULL, eckey, false); } if (keygen->ssk_file != "") { WritePemFile(keygen->ssk_file, NULL, eckey, true); } } } } /******************************************************************************/ void Key2048::Export(void* acKey) { ACKey2048* key = (ACKey2048*)acKey; if (!Loaded) { std::string pubsec = (isSecret) ? " (Secret)" : " (Public)"; LOG_ERROR("%s - $s is not loaded", name.c_str(), pubsec.c_str()); } memset(key,0,sizeof(ACKey2048)); memcpy(key->N, N, 256); memcpy(key->N_extension, N_ext, 256); memcpy(key->E, E, 4); } /******************************************************************************/ void Key2048::Import(const void* acKey, const std::string& name0) { ACKey2048* key = (ACKey2048*)acKey; Loaded = true; isSecret = false; name = name0; memcpy(N,key->N,keySize); memcpy(N_ext,key->N_extension,keySize); memcpy(E,key->E,sizeof(uint32_t)); memset(P,0,keySize/2); memset(Q,0,keySize/2); /* Fill secret exponent with zeros */ memset(D,0,keySize); } /******************************************************************************/ void Key4096::Export(void* acKey) { ACKey4096* key = (ACKey4096*)acKey; if (!Loaded) { std::string pubsec = (isSecret) ? " (Secret)" : " (Public)"; LOG_ERROR("%s - $s is not loaded", name.c_str(), pubsec.c_str()); } memset(key, 0, sizeof(ACKey4096)); memcpy(key->N, N, keySize); memcpy(key->N_extension, N_ext, keySize); memcpy(key->E, E, 4); } /******************************************************************************/ void Key4096::Import(const void* acKey, const std::string& name0) { ACKey4096* key = (ACKey4096*)acKey; Loaded = true; isSecret = false; name = name0; memcpy(N, key->N, keySize); memcpy(N_ext, key->N_extension, keySize); memcpy(E, key->E, sizeof(uint32_t)); memset(P, 0, keySize/2); memset(Q, 0, keySize/2); /* Fill secret exponent with zeros */ memset(D, 0, keySize); } /******************************************************************************/ void Key::SetKeyName(std::string keyname) { name = keyname; } /******************************************************************************/ void Key::Multiply_p_q(uint8_t p[], uint8_t q[], uint8_t n[]) { memset(n,0,256); /* Multiply p * q, and store in n */ for(int i = 0; i < 128; i++) { for(int j = 0; j < 128; j++) { uint16_t prod = p[i] * q[j]; int k = i+j; while (prod && k < 256) { uint16_t sum = n[k] + (prod & 0xFF); n[k] = sum & 0xFF; prod >>= 8; sum >>= 8; prod = (prod + sum); k++; } } } } /******************************************************************************/ void Key::Hex2Byte(FILE* f, uint8_t* data, int count) { char *buf; buf = (char *) malloc(2000); if (buf != NULL) { char *tempbuf = buf; if (fscanf(f, "%s", tempbuf) != 1) { LOG_ERROR("Error parsing key"); } int len = strlen(tempbuf)/2; if(len != count) { LOG_ERROR("Key size is %d bytes, expected size is %d bytes", len, count); } for(int i = count-1; i >= 0; i--) { int v; if (sscanf(tempbuf, "%2X", &v) != 1) { LOG_DEBUG(DEBUG_STAMP, "Failure reading the authentication key file"); LOG_ERROR("Failure in key parsing !!!"); } if (v < 0 || v > 255) { LOG_DEBUG(DEBUG_STAMP, "Failure converting the hex characters from key file"); LOG_ERROR("Failure in key parsing !!!"); } if(i > 0) { tempbuf += 2; } data[i] = v; } } else { LOG_DEBUG(DEBUG_STAMP, "Memory Allocation error while reading keys"); LOG_ERROR("Failure in key parsing !!!"); } free(buf); } xilinx-bootgen-2024.2/authkeys.h000077500000000000000000000126411475706442400166030ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _AUTHKEYS_H_ #define _AUTHKEYS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include "logger.h" #if OPENSSL_VERSION_NUMBER > 0x10100000L #include "xil-bignum.h" #endif /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define RSA_2048_KEY_LENGTH 256 #define RSA_4096_KEY_LENGTH 512 #define EC_P384_KEY_LENGTH 48 #define EC_P521_KEY_LENGTH1 65 /* 520/8 = 65 */ #define EC_P521_KEY_LENGTH2 66 /* 521/8 = 65 + 1bit */ #define SIGN_LENGTH_VERSAL 512 /* for ecdsa: r(48b)+ s(48b)+ pad(416b) */ #define RSA_SIGN_LENGTH_ZYNQ 256 #define RSA_SIGN_LENGTH_ZYNQMP 512 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint8_t N[RSA_2048_KEY_LENGTH]; // Modulus uint8_t N_extension[RSA_2048_KEY_LENGTH]; // Montgomery Modulus extension uint8_t E[4]; // Exponent uint8_t Padding[60]; // Padding } ACKey2048; typedef struct { uint8_t Signature[RSA_SIGN_LENGTH_ZYNQ]; } ACSignature2048; typedef struct { uint8_t N[RSA_4096_KEY_LENGTH]; // Modulus uint8_t N_extension[RSA_4096_KEY_LENGTH]; // Montgomery Modulus extension uint8_t E[4]; // Exponent uint8_t Padding[60]; // Padding } ACKey4096; /* Signature - RSA 4096 bits */ typedef struct { uint8_t Signature[RSA_SIGN_LENGTH_ZYNQMP]; } ACSignature4096; /* Key Generation Structures */ typedef struct { GenAuthKeys::Type format; std::string ppk_file; std::string psk_file; std::string spk_file; std::string ssk_file; uint16_t keyLength; } KeyGenerationStruct; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Key { public: Key(const std::string& name0); Key(const Key& otherKey); virtual ~Key(); virtual void Export(void* dst) = 0; virtual void Import(const void* acKey, const std::string& name0) = 0; void ParsePublic(const std::string& filename); void ParseSecret(const std::string& filename); void SetKeyName(std::string); static void GenerateRsaKeys(KeyGenerationStruct*); static void GenerateEcdsaKeys(KeyGenerationStruct*); bool Loaded; bool isSecret; uint8_t *N; // modulus (2048 bits) uint8_t *E; // public (encryption) exponent (32 bits) uint8_t *N_ext; // modular_ext (2048 bits) uint8_t *D; // secret (decryption) exponent (2048 bits). Authentication :: Type authType; protected: void Multiply_p_q(uint8_t p[], uint8_t q[], uint8_t n[]); void Hex2Byte(FILE* f, uint8_t* data, int count); virtual void Parse(const std::string& filename, bool isSecret0); uint8_t ParseAMDRsaKey(FILE* f); uint8_t ParseOpenSSLKey(FILE* f); static void WriteRsaFile(std::string file, const RSA* rsa, bool secret, uint16_t keyLength); static void WritePemFile(std::string file, RSA* rsa, EC_KEY* eckey, bool secret); uint8_t *P; uint8_t *Q; std::string name; uint16_t keySize; uint16_t keySizeX; uint16_t keySizeY; }; /******************************************************************************/ class Key2048 : public Key { public: Key2048(const std::string& name0) : Key(name0) { } Key2048(const Key2048& otherKey) : Key(otherKey) { } void Export(void* dst); void Import(const void* acKey, const std::string& name0); }; /******************************************************************************/ class Key4096 : public Key { public: Key4096(const std::string& name0) : Key(name0) { } Key4096(const Key4096& otherKey) : Key(otherKey) { } void Export(void* dst); void Import(const void* acKey, const std::string& name0); }; #endif xilinx-bootgen-2024.2/baseclass.h000077500000000000000000000045771475706442400167170ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BASECLASS_H_ #define _BASECLASS_H_ /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class BaseThing { public: BaseThing() : section(NULL) { } uint32_t ComputeWordChecksum( void* firstWordPtr, size_t length) { uint32_t checksum = 0; size_t numChecksumedWords = length / sizeof(uint32_t); for(size_t i=0;i< numChecksumedWords; i++) { checksum += ((uint32_t*)firstWordPtr)[i]; } /* Invert the Checksum value */ checksum ^= 0xFFFFFFFF; return checksum; } Section* section; }; /******************************************************************************/ template class Override { public: Override() : overriden(false), value(0) { } Override& operator=(T value0) { overriden = true; value = value0; return *this; } Override& operator=(Override& el) { overriden = el.overriden; value = el.value; return *this; } void Set(T value0) { overriden = true; value = value0; } T Value() const { return value; } T ValueOrDefault(T defValue) const { return overriden?value:defValue;} bool IsSet() const { return overriden;} private: bool overriden; T value; }; #endif xilinx-bootgen-2024.2/bif.l000077500000000000000000000645111475706442400155150ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the BIF file */ /* Run the bif.y file first through bison to generate the bif.tab.h file, which is included herein */ /* Then run this file through flex to generate the bif.yy.c source code */ %{ #include #include "bifscanner.h" #include "bif.tab.hpp" #include "authentication.h" #include "encryption.h" typedef BIF::BisonParser::token tok; %} /* see http://www.lysator.liu.se/c/ANSI-C-grammar-l.html */ %option nodefault yyclass="FlexScanner" noyywrap c++ noyywrap nounput batch debug %{ # define YY_USER_ACTION yylloc->columns (yyleng); %} %% %{ yylloc->step (); %} "/*" { comment(); } \/\/.*?\n yylloc->lines (1); yylloc->step (); bootloader return tok::BOOTLOADER; presign return tok::PRESIGN; ac return tok::AC; udf_data return tok::UDF_DATA; xip_mode return tok::XIP_MODE; boot return tok::BOOT; user return tok::USER; static return tok::STATIC; noautostart return tok::NOAUTOSTART; multiboot return tok::MULTIBOOT; protected return tok::PROTECTED; alignment return tok::ALIGNMENT; early_handoff return tok::EARLY_HANDOFF; delay_handoff return tok::DELAY_HANDOFF; delay_load return tok::DELAY_LOAD; delay_auth return tok::DELAY_AUTH; hivec return tok::HIVEC; blocks return tok::BLOCKS; authblocks return tok::AUTHBLOCKS; big_endian return tok::BIGENDIAN; aarch32_mode return tok::A32_MODE; partition return tok::PARTITION; image return tok::IMAGE; metaheader return tok::METAHEADER; section return tok::BIF_SECTION; lockstep return tok::LOCKSTEP; include return tok::INCLUDE; tcmboot return tok::TCM_BOOT; optionaldata return tok::OPTIONAL_DATA; offset yylval->number = tok::OFFSET; return tok::OFFSET; reserve_legacy yylval->number = tok::RESERVE_LEGACY; return tok::RESERVE_LEGACY; reserve yylval->number = tok::RESERVE; return tok::RESERVE; load yylval->number = tok::LOAD; return tok::LOAD; copy yylval->number = tok::COPY; return tok::COPY; startup yylval->number = tok::STARTUP; return tok::STARTUP; pid yylval->number = tok::PARTITION_NUM; return tok::PARTITION_NUM; init yylval->number = tok::INIT; return tok::INIT; udf_bh yylval->number = tok::UDF_BH; return tok::UDF_BH; aeskeyfile yylval->number = tok::AES_KEY_FILE; return tok::AES_KEY_FILE; ppkfile yylval->number = tok::PPK_FILE; return tok::PPK_FILE; pskfile yylval->number = tok::PSK_FILE; return tok::PSK_FILE; spkfile yylval->number = tok::SPK_FILE; return tok::SPK_FILE; sskfile yylval->number = tok::SSK_FILE; return tok::SSK_FILE; spksignature yylval->number = tok::SPK_SIGNATURE_FILE; return tok::SPK_SIGNATURE_FILE; bhsignature yylval->number = tok::BH_SIGNATURE_FILE; return tok::BH_SIGNATURE_FILE; headersignature yylval->number = tok::HEADER_SIGNATURE_FILE; return tok::HEADER_SIGNATURE_FILE; bootvectors yylval->number = tok::BOOTVECTORS; return tok::BOOTVECTORS; bootimage yylval->number = tok::BOOTIMAGE; return tok::BOOTIMAGE; parent_id yylval->number = tok::PARENT_ID; return tok::PARENT_ID; id_code yylval->number = tok::ID_CODE; return tok::ID_CODE; extended_id_code yylval->number = tok::EXT_ID_CODE; return tok::EXT_ID_CODE; id yylval->number = tok::ID; return tok::ID; name yylval->number = tok::NAME; return tok::NAME; file yylval->number = tok::PFILE; return tok::PFILE; bh_keyfile yylval->number = tok::BH_KEY_FILE; return tok::BH_KEY_FILE; puf_file yylval->number = tok::PUF_HELPER_FILE; return tok::PUF_HELPER_FILE; pmufw_image yylval->number = tok::PMUFW_IMAGE; return tok::PMUFW_IMAGE; pmcdata yylval->number = tok::PMCDATA; return tok::PMCDATA; bh_key_iv yylval->number = tok::BH_KEY_IV; return tok::BH_KEY_IV; uid yylval->number = tok::UNIQUE_ID; return tok::UNIQUE_ID; parent_uid yylval->number = tok::PARENT_UNIQUE_ID; return tok::PARENT_UNIQUE_ID; function_id yylval->number = tok::FUNCTION_ID; return tok::FUNCTION_ID; pcr yylval->number = tok::PCR_NUMBER; return tok::PCR_NUMBER; pcr_mindex yylval->number = tok::PCR_MEASUREMENT_INDEX; return tok::PCR_MEASUREMENT_INDEX; imagestore yylval->number = tok::IMAGE_STORE; return tok::IMAGE_STORE; tcm_a_region yylval->number = tok::TCM_A_REGION; return tok::TCM_A_REGION; tcm_b_region yylval->number = tok::TCM_B_REGION; return tok::TCM_B_REGION; tcm_c_region yylval->number = tok::TCM_C_REGION; return tok::TCM_C_REGION; bbram_kek_iv yylval->number = tok::BBRAM_KEK_IV; return tok::BBRAM_KEK_IV; bh_kek_iv yylval->number = tok::BH_KEK_IV; return tok::BH_KEK_IV; efuse_kek_iv yylval->number = tok::EFUSE_KEK_IV; return tok::EFUSE_KEK_IV; efuse_user_kek0_iv yylval->number = tok::EFUSE_USER_KEK0_IV; return tok::EFUSE_USER_KEK0_IV; efuse_user_kek1_iv yylval->number = tok::EFUSE_USER_KEK1_IV; return tok::EFUSE_USER_KEK1_IV; userkeys yylval->number = tok::USER_KEYS; return tok::USER_KEYS; familykey yylval->number = tok::FAMILY_KEY; return tok::FAMILY_KEY; encryption return tok::ENCRYPTION; none yylval->number = 0; return tok::NONE; aes yylval->number = Encryption::AES; return tok::ENCRVALUE; authentication return tok::AUTHENTICATION; rsa yylval->number = Authentication::RSA; return tok::AUTHVALUE; ecdsa yylval->number = Authentication::ECDSA; return tok::AUTHVALUE; ecdsa-p384 yylval->number = Authentication::ECDSA; return tok::AUTHVALUE; ecdsa-p521 yylval->number = Authentication::ECDSAp521; return tok::AUTHVALUE; checksum return tok::CHECKSUM; md5 yylval->number = Checksum::MD5; return tok::CHECKSUMVALUE; sha2 yylval->number = Checksum::SHA2; return tok::CHECKSUMVALUE; sha3 yylval->number = Checksum::SHA3; return tok::CHECKSUMVALUE; partition_owner return tok::PARTITION_OWNER; owner return tok::PARTITION_OWNER; fsbl yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; uboot yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; pmc yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; non-pmc yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; plm yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; non-plm yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; partition_type return tok::PARTITION_TYPE; type return tok::PARTITION_TYPE; cdo yylval->number = PartitionType::CONFIG_DATA_OBJ; return tok::PTYPEVALUE; raw yylval->number = PartitionType::RAW; return tok::PTYPEVALUE; cfi yylval->number = PartitionType::CFI; return tok::PTYPEVALUE; cfi-gsc yylval->number = PartitionType::CFI_GSC; return tok::PTYPEVALUE; slr-boot yylval->number = PartitionType::SLR_BOOT; return tok::PTYPEVALUE; slr-config yylval->number = PartitionType::SLR_CONFIG; return tok::PTYPEVALUE; slr-slave yylval->number = PartitionType::SLR_SLAVE; return tok::PTYPEVALUE; slr-slave-boot yylval->number = PartitionType::SLR_SLAVE_BOOT; return tok::PTYPEVALUE; slr-slave-config yylval->number = PartitionType::SLR_SLAVE_CONFIG; return tok::PTYPEVALUE; elf yylval->number = PartitionType::ELF; return tok::PTYPEVALUE; keysrc_encryption yylval->number = tok::KEYSRC_ENCRYPTION; return tok::KEYSRC_ENCRYPTION; keysrc yylval->number = tok::KEYSRC_ENCRYPTION; return tok::KEYSRC_ENCRYPTION; efuse yylval->number = KeySource::EfuseRedKey; return tok::KEY_SRC; bbram yylval->number = KeySource::BbramRedKey; return tok::KEY_SRC; efuse_red_key yylval->number = KeySource::EfuseRedKey; return tok::KEY_SRC; efuse_blk_key yylval->number = KeySource::EfuseBlkKey; return tok::KEY_SRC; efuse_gry_key yylval->number = KeySource::EfuseGryKey; return tok::KEY_SRC; bbram_red_key yylval->number = KeySource::BbramRedKey; return tok::KEY_SRC; bbram_blk_key yylval->number = KeySource::BbramBlkKey; return tok::KEY_SRC; bbram_gry_key yylval->number = KeySource::BbramGryKey; return tok::KEY_SRC; bh_gry_key yylval->number = KeySource::BhGryKey; return tok::KEY_SRC; bh_blk_key yylval->number = KeySource::BhBlkKey; return tok::KEY_SRC; user_key0 yylval->number = KeySource::UserKey0; return tok::KEY_SRC; user_key1 yylval->number = KeySource::UserKey1; return tok::KEY_SRC; user_key2 yylval->number = KeySource::UserKey2; return tok::KEY_SRC; user_key3 yylval->number = KeySource::UserKey3; return tok::KEY_SRC; user_key4 yylval->number = KeySource::UserKey4; return tok::KEY_SRC; user_key5 yylval->number = KeySource::UserKey5; return tok::KEY_SRC; user_key6 yylval->number = KeySource::UserKey6; return tok::KEY_SRC; user_key7 yylval->number = KeySource::UserKey7; return tok::KEY_SRC; efuse_user_key0 yylval->number = KeySource::EfuseUserKey0; return tok::KEY_SRC; efuse_user_blk_key0 yylval->number = KeySource::EfuseUserBlkKey0; return tok::KEY_SRC; efuse_user_gry_key0 yylval->number = KeySource::EfuseUserGryKey0; return tok::KEY_SRC; efuse_user_key1 yylval->number = KeySource::EfuseUserKey1; return tok::KEY_SRC; efuse_user_blk_key1 yylval->number = KeySource::EfuseUserBlkKey1; return tok::KEY_SRC; efuse_user_gry_key1 yylval->number = KeySource::EfuseUserGryKey1; return tok::KEY_SRC; kup_key yylval->number = KeySource::BhKupKey; return tok::KEY_SRC; fsbl_config yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; boot_config yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; image_config yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; r5_single yylval->number = Core::R5Single; return tok::CORE; a53_x32 yylval->number = Core::A53Singlex32; return tok::CORE; a5x_x32 yylval->number = Core::A53Singlex32; return tok::CORE; a53_x64 yylval->number = Core::A53Singlex64; return tok::CORE; a5x_x64 yylval->number = Core::A53Singlex64; return tok::CORE; r5_dual yylval->number = Core::R5Dual; return tok::CORE; bh_auth_enable yylval->number = BhRsa::BhRsaEnable; return tok::BH_RSA; auth_sha2_enable yylval->number = AuthHash::Sha2; return tok::AUTH_HASH; pufhd_bh yylval->number = PufHdLoc::PUFinBH; return tok::PUFHD_LOC; auth_only yylval->number = AuthOnly::Enabled; return tok::AUTH_ONLY; opt_key yylval->number = OptKey::OptKeyinSecHdr; return tok::OPT_KEY; puf4kmode yylval->number = PufMode::PUF4K; return tok::PUF4KMODE; shutter yylval->number = tok::SHUTTER; return tok::SHUTTER; puf_ro_swap yylval->number = tok::PUFROSWAP; return tok::PUFROSWAP; dpacm_enable yylval->number = DpaCM::DpaCMEnable; return tok::DPA_CM; dice_enable yylval->number = tok::DICE; return tok::DICE; smap_width yylval->number = tok::SMAP_WIDTH; return tok::SMAP_WIDTH; bypass_idcode_check yylval->number = tok::BYPASS_IDCODE_CHECK; return tok::BYPASS_IDCODE_CHECK; a_hwrot yylval->number = tok::A_HWROT; return tok::A_HWROT; s_hwrot yylval->number = tok::S_HWROT; return tok::S_HWROT; boot_device return tok::BOOT_DEVICE; address yylval->number = tok::ADDRESS; return tok::ADDRESS; qspi32 yylval->number = BootDevice::QSPI32; return tok::BOOT_DEVICE_TYPE ; qspi24 yylval->number = BootDevice::QSPI24; return tok::BOOT_DEVICE_TYPE ; nand yylval->number = BootDevice::NAND; return tok::BOOT_DEVICE_TYPE ; sd0 yylval->number = BootDevice::SD0; return tok::BOOT_DEVICE_TYPE ; sd1 yylval->number = BootDevice::SD1; return tok::BOOT_DEVICE_TYPE ; sd-ls yylval->number = BootDevice::SDLS; return tok::BOOT_DEVICE_TYPE ; mmc yylval->number = BootDevice::MMC; return tok::BOOT_DEVICE_TYPE ; usb yylval->number = BootDevice::USB; return tok::BOOT_DEVICE_TYPE ; ethernet yylval->number = BootDevice::ETHERNET; return tok::BOOT_DEVICE_TYPE ; pcie yylval->number = BootDevice::PCIE; return tok::BOOT_DEVICE_TYPE ; sata yylval->number = BootDevice::SATA; return tok::BOOT_DEVICE_TYPE ; ospi yylval->number = BootDevice::OSPI; return tok::BOOT_DEVICE_TYPE ; smap yylval->number = BootDevice::SMAP; return tok::BOOT_DEVICE_TYPE ; sbi yylval->number = BootDevice::SBI; return tok::BOOT_DEVICE_TYPE ; sd0-raw yylval->number = BootDevice::SD0RAW; return tok::BOOT_DEVICE_TYPE ; sd1-raw yylval->number = BootDevice::SD1RAW; return tok::BOOT_DEVICE_TYPE ; sd-ls-raw yylval->number = BootDevice::SDLSRAW; return tok::BOOT_DEVICE_TYPE ; mmc-raw yylval->number = BootDevice::MMCRAW; return tok::BOOT_DEVICE_TYPE ; mmc0 yylval->number = BootDevice::MMC0; return tok::BOOT_DEVICE_TYPE ; mmc0-raw yylval->number = BootDevice::MMC0RAW; return tok::BOOT_DEVICE_TYPE ; destination_cpu return tok::DEST_CPU; core return tok::DEST_CPU; a53-0 yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; a72-0 yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; a78-0 yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; a5x-0 yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; a53-1 yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; a72-1 yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; a78-1 yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; a5x-1 yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; a53-2 yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; a78-2 yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; a5x-2 yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; a53-3 yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; a78-3 yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; a5x-3 yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; r5-0 yylval->number = DestinationCPU::R5_0; return tok::DEST_CPU_TYPE; r52-0 yylval->number = DestinationCPU::R5_0; return tok::DEST_CPU_TYPE; r5-1 yylval->number = DestinationCPU::R5_1; return tok::DEST_CPU_TYPE; r52-1 yylval->number = DestinationCPU::R5_1; return tok::DEST_CPU_TYPE; r5-lockstep yylval->number = DestinationCPU::R5_lockstep; return tok::DEST_CPU_TYPE; pmu yylval->number = DestinationCPU::PMU; return tok::DEST_CPU_TYPE; psm yylval->number = DestinationCPU::PMU; return tok::DEST_CPU_TYPE; aie yylval->number = DestinationCPU::AIE; return tok::DEST_CPU_TYPE; cluster yylval->number = tok::CLUSTER_NUM; return tok::CLUSTER_NUM; destination_device return tok::DEST_DEVICE; ps yylval->number = DestinationDevice::DEST_DEV_PS; return tok::DEST_DEVICE_TYPE; pl yylval->number = DestinationDevice::DEST_DEV_PL; return tok::DEST_DEVICE_TYPE; pmufw yylval->number = DestinationDevice::DEST_DEV_PMU; return tok::DEST_DEVICE_TYPE; xip yylval->number = DestinationDevice::DEST_DEV_XIP; return tok::DEST_DEVICE_TYPE; exception_level return tok::EXCEPTION_LEVEL; el-0 yylval->number = ExceptionLevel::EL0; return tok::EXCEPTION_LEVEL_TYPE; el-1 yylval->number = ExceptionLevel::EL1; return tok::EXCEPTION_LEVEL_TYPE; el-2 yylval->number = ExceptionLevel::EL2; return tok::EXCEPTION_LEVEL_TYPE; el-3 yylval->number = ExceptionLevel::EL3; return tok::EXCEPTION_LEVEL_TYPE; trustzone return tok::TRUSTZONE; secure yylval->number = TrustZone::Secure; return tok::TRUSTZONE_TYPE; nonsecure yylval->number = TrustZone::NonSecure; return tok::TRUSTZONE_TYPE; slr yylval->number = tok::SLR_NUM; return tok::SLR_NUM; auth_params yylval->number = tok::AUTH_PARAMS; return tok::AUTH_PARAMS; ppk_select yylval->number = tok::PPK_SELECT; return tok::PPK_SELECT; spk_select yylval->number = tok::SPK_SELECT; return tok::SPK_SELECT; spk-efuse yylval->number = SpkSelect::SPK_eFUSE; return tok::SPKSELECT; user-efuse yylval->number = SpkSelect::USER_eFUSE; return tok::SPKSELECT; spk_id yylval->number = tok::SPK_ID; return tok::SPK_ID; header_auth return tok::HEADER_AUTH; revoke_id yylval->number = tok::REVOKE_ID; return tok::REVOKE_ID; split yylval->number = tok::SPLIT; return tok::SPLIT; mode yylval->number = tok::SPLIT_MODE; return tok::SPLIT_MODE; slaveboot yylval->number = SplitMode::SlaveMode; return tok::SPLITMODE; normal yylval->number = SplitMode::Normal; return tok::SPLITMODE; fmt yylval->number = tok::SPLIT_FMT; return tok::SPLIT_FMT; mcs return tok::MCS; bin return tok::BIN; authjtag_config yylval->number = tok::AUTHJTAG_CONFIG; return tok::AUTHJTAG_CONFIG; device_dna yylval->number = tok::DEVICE_DNA; return tok::DEVICE_DNA; jtag_timeout yylval->number = tok::JTAG_TIMEOUT; return tok::JTAG_TIMEOUT; [0-9]+ yylval->number=atoi(yytext); return tok::DECVALUE; 0[xX][0-9a-fA-F]+ yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; [a-fA-F0-9]+ yylval->string=strdup(yytext); return tok::HEXWORD; : return tok::COLON; ; return tok::SEMICOLON; = return tok::EQUAL; , return tok::COMMA; \[ return tok::OBRACKET; \] return tok::EBRACKET; \{ return tok::OBRACE; \} return tok::EBRACE; \( return tok::LPAREN; \) return tok::RPAREN; \* return tok::ASTERISK; \+ return tok::PLUS; \- return tok::MINUS; \<\< return tok::LSHIFT; \>\> return tok::RSHIFT; \* return tok::MULT; \/ return tok::DIVIDE; \% return tok::MODULO; \~ return tok::NEGATION; \& return tok::AND; \| return tok::OR; \^ return tok::XOR; [a-zA-Z_][a-zA-Z0-9_]* yylval->string=strdup(yytext); return tok::WORD; ([a-zA-Z]:[\/\\])?[a-zA-Z0-9\/\\\+._-]+ yylval->string=strdup(yytext); return tok::FILENAME; \"([a-zA-Z]:[\/\\])?[a-zA-Z0-9\/\\\\(\)@!#$%^&+._ -]+\" yylval->string=strdup(yytext+1); yylval->string[strlen(yytext)-2]=0; return tok::QFILENAME; [ \t]+ yylloc->step (); [\n]+ yylloc->lines (yyleng); yylloc->step (); \r /* ignore (Linux only) */ . printf("WARNING: bad character! '%s' (0x%02X)\n",yytext,yytext[0]); %% void BIF::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); if (c == '\n') yylloc->lines (1); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/bif.tab.cpp000077500000000000000000003346561475706442400166230ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton implementation for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* First part of user declarations. */ /* Line 279 of lalr1.cc */ #line 53 "../s/bif.y" #include #include "bootimage.h" #include "authentication.h" #include "encryption.h" #include "checksum.h" #include "bifscanner.h" #include "parsing.h" #include "imageheadertable-versal.h" BifOptions* currentBifOptions; PartitionBifOptions* currentPartitionBifOptions ; ImageBifOptions* currentImageBifOptions; /* Line 279 of lalr1.cc */ #line 53 "../bisonflex/bif.tab.cpp" #include "bif.tab.hpp" /* User implementation prologue. */ /* Line 285 of lalr1.cc */ #line 61 "../bisonflex/bif.tab.cpp" /* Unqualified %code blocks. */ /* Line 286 of lalr1.cc */ #line 47 "../s/bif.y" static int yylex(BIF::BisonParser::semantic_type * yylval, BIF::BisonParser::location_type* loc, BIF::FlexScanner &scanner); #include "options.h" /* Line 286 of lalr1.cc */ #line 71 "../bisonflex/bif.tab.cpp" # ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULL nullptr # else # define YY_NULL 0 # endif # endif #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* FIXME: INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ # ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (N) \ { \ (Current).begin = YYRHSLOC (Rhs, 1).begin; \ (Current).end = YYRHSLOC (Rhs, N).end; \ } \ else \ { \ (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ } \ while (/*CONSTCOND*/ false) # endif /* Suppress unused-variable warnings by "using" E. */ #define YYUSE(e) ((void) (e)) /* Enable debugging if requested. */ #if YYDEBUG /* A pseudo ostream that takes yydebug_ into account. */ # define YYCDEBUG if (yydebug_) (*yycdebug_) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug_) \ { \ *yycdebug_ << Title << ' '; \ yy_symbol_print_ ((Type), (Value), (Location)); \ *yycdebug_ << std::endl; \ } \ } while (false) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug_) \ yy_reduce_print_ (Rule); \ } while (false) # define YY_STACK_PRINT() \ do { \ if (yydebug_) \ yystack_print_ (); \ } while (false) #else /* !YYDEBUG */ # define YYCDEBUG if (false) std::cerr # define YY_SYMBOL_PRINT(Title, Type, Value, Location) YYUSE(Type) # define YY_REDUCE_PRINT(Rule) static_cast(0) # define YY_STACK_PRINT() static_cast(0) #endif /* !YYDEBUG */ #define yyerrok (yyerrstatus_ = 0) #define yyclearin (yychar = yyempty_) #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus_) /* Line 353 of lalr1.cc */ #line 24 "../s/bif.y" namespace BIF { /* Line 353 of lalr1.cc */ #line 167 "../bisonflex/bif.tab.cpp" /// Build a parser object. BisonParser::BisonParser (BIF::FlexScanner& scanner_yyarg, Options& options_yyarg) : #if YYDEBUG yydebug_ (false), yycdebug_ (&std::cerr), #endif scanner (scanner_yyarg), options (options_yyarg) { } BisonParser::~BisonParser () { } #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ inline void BisonParser::yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yyvaluep); std::ostream& yyo = debug_stream (); std::ostream& yyoutput = yyo; YYUSE (yyoutput); switch (yytype) { default: break; } } void BisonParser::yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm") << ' ' << yytname_[yytype] << " (" << *yylocationp << ": "; yy_symbol_value_print_ (yytype, yyvaluep, yylocationp); *yycdebug_ << ')'; } #endif void BisonParser::yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yymsg); YYUSE (yyvaluep); if (yymsg) YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } void BisonParser::yypop_ (unsigned int n) { yystate_stack_.pop (n); yysemantic_stack_.pop (n); yylocation_stack_.pop (n); } #if YYDEBUG std::ostream& BisonParser::debug_stream () const { return *yycdebug_; } void BisonParser::set_debug_stream (std::ostream& o) { yycdebug_ = &o; } BisonParser::debug_level_type BisonParser::debug_level () const { return yydebug_; } void BisonParser::set_debug_level (debug_level_type l) { yydebug_ = l; } #endif inline bool BisonParser::yy_pact_value_is_default_ (int yyvalue) { return yyvalue == yypact_ninf_; } inline bool BisonParser::yy_table_value_is_error_ (int yyvalue) { return yyvalue == yytable_ninf_; } int BisonParser::parse () { /// Lookahead and lookahead in internal form. int yychar = yyempty_; int yytoken = 0; // State. int yyn; int yylen = 0; int yystate = 0; // Error handling. int yynerrs_ = 0; int yyerrstatus_ = 0; /// Semantic value of the lookahead. static semantic_type yyval_default; semantic_type yylval = yyval_default; /// Location of the lookahead. location_type yylloc; /// The locations where the error started and ended. location_type yyerror_range[3]; /// $$. semantic_type yyval; /// @$. location_type yyloc; int yyresult; // FIXME: This shoud be completely indented. It is not yet to // avoid gratuitous conflicts when merging into the master branch. try { YYCDEBUG << "Starting parse" << std::endl; /* User initialization code. */ /* Line 545 of lalr1.cc */ #line 31 "../s/bif.y" { // Initialize the initial location. yylloc.begin.filename = yylloc.end.filename = &scanner.filename; } /* Line 545 of lalr1.cc */ #line 331 "../bisonflex/bif.tab.cpp" /* Initialize the stacks. The initial state will be pushed in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ yystate_stack_ = state_stack_type (0); yysemantic_stack_ = semantic_stack_type (0); yylocation_stack_ = location_stack_type (0); yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* New state. */ yynewstate: yystate_stack_.push (yystate); YYCDEBUG << "Entering state " << yystate << std::endl; /* Accept? */ if (yystate == yyfinal_) goto yyacceptlab; goto yybackup; /* Backup. */ yybackup: /* Try to take a decision without lookahead. */ yyn = yypact_[yystate]; if (yy_pact_value_is_default_ (yyn)) goto yydefault; /* Read a lookahead token. */ if (yychar == yyempty_) { YYCDEBUG << "Reading a token: "; yychar = yylex (&yylval, &yylloc, scanner); } /* Convert token to internal form. */ if (yychar <= yyeof_) { yychar = yytoken = yyeof_; YYCDEBUG << "Now at end of input." << std::endl; } else { yytoken = yytranslate_ (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) goto yydefault; /* Reduce or error. */ yyn = yytable_[yyn]; if (yyn <= 0) { if (yy_table_value_is_error_ (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted. */ yychar = yyempty_; yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus_) --yyerrstatus_; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact_[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: yylen = yyr2_[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. */ if (yylen) yyval = yysemantic_stack_[yylen - 1]; else yyval = yysemantic_stack_[0]; // Compute the default @$. { slice slice (yylocation_stack_, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen); } // Perform the reduction. YY_REDUCE_PRINT (yyn); switch (yyn) { case 5: /* Line 670 of lalr1.cc */ #line 204 "../s/bif.y" { options.includeBifOptionsList.push_back((yysemantic_stack_[(3) - (3)].string)); } break; case 6: /* Line 670 of lalr1.cc */ #line 205 "../s/bif.y" { currentBifOptions = new BifOptions(options.GetArchType(),(yysemantic_stack_[(1) - (1)].string)); } break; case 7: /* Line 670 of lalr1.cc */ #line 207 "../s/bif.y" { options.bifOptions = currentBifOptions; options.bifOptionsList.push_back(currentBifOptions); } break; case 16: /* Line 670 of lalr1.cc */ #line 221 "../s/bif.y" { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); } break; case 22: /* Line 670 of lalr1.cc */ #line 232 "../s/bif.y" { currentBifOptions->SetMetaHeaderEncryptType((yysemantic_stack_[(3) - (3)].encrvalue_t)); } break; case 23: /* Line 670 of lalr1.cc */ #line 233 "../s/bif.y" { currentBifOptions->SetMetaHeaderEncryptionKeySource((yysemantic_stack_[(3) - (3)].encrkeysrc_t), options.IsVersalNetSeries()); } break; case 24: /* Line 670 of lalr1.cc */ #line 234 "../s/bif.y" { currentBifOptions->SetMetaHeaderEncryptionKeyFile((yysemantic_stack_[(3) - (3)].string)); } break; case 25: /* Line 670 of lalr1.cc */ #line 235 "../s/bif.y" { currentBifOptions->SetMetaHeaderAuthType((yysemantic_stack_[(3) - (3)].authvalue_t)); } break; case 26: /* Line 670 of lalr1.cc */ #line 236 "../s/bif.y" { currentBifOptions->metaHdrAttributes.ppk = (yysemantic_stack_[(3) - (3)].string); } break; case 27: /* Line 670 of lalr1.cc */ #line 237 "../s/bif.y" { currentBifOptions->metaHdrAttributes.psk = (yysemantic_stack_[(3) - (3)].string); } break; case 28: /* Line 670 of lalr1.cc */ #line 238 "../s/bif.y" { currentBifOptions->metaHdrAttributes.spk = (yysemantic_stack_[(3) - (3)].string); } break; case 29: /* Line 670 of lalr1.cc */ #line 239 "../s/bif.y" { currentBifOptions->metaHdrAttributes.ssk = (yysemantic_stack_[(3) - (3)].string); } break; case 30: /* Line 670 of lalr1.cc */ #line 240 "../s/bif.y" { currentBifOptions->metaHdrAttributes.spkSignature = (yysemantic_stack_[(3) - (3)].string); } break; case 31: /* Line 670 of lalr1.cc */ #line 241 "../s/bif.y" { currentBifOptions->metaHdrAttributes.presign = (yysemantic_stack_[(3) - (3)].string); } break; case 32: /* Line 670 of lalr1.cc */ #line 242 "../s/bif.y" { currentBifOptions->metaHdrAttributes.revokeId = (yysemantic_stack_[(3) - (3)].number); } break; case 33: /* Line 670 of lalr1.cc */ #line 243 "../s/bif.y" { currentBifOptions->metaHdrAttributes.checksum = (yysemantic_stack_[(3) - (3)].checksumvalue_t); } break; case 34: /* Line 670 of lalr1.cc */ #line 244 "../s/bif.y" { currentBifOptions->metaHdrAttributes.dpaCM = DpaCM::DpaCMEnable; } break; case 36: /* Line 670 of lalr1.cc */ #line 246 "../s/bif.y" { currentBifOptions->metaHdrAttributes.pufHdLoc = PufHdLoc::PUFinBH; currentBifOptions->SetPufHdinBHFlag();} break; case 39: /* Line 670 of lalr1.cc */ #line 254 "../s/bif.y" { currentBifOptions->metaHdrAttributes.ihtOptionalDataInfo.push_back(std::pair((yysemantic_stack_[(5) - (1)].string), (yysemantic_stack_[(5) - (5)].number))); } break; case 43: /* Line 670 of lalr1.cc */ #line 261 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(1) - (1)].number)); currentBifOptions->metaHdrAttributes.encrBlocks = currentPartitionBifOptions->GetEncryptionBlocks(); } break; case 44: /* Line 670 of lalr1.cc */ #line 263 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(4) - (1)].number), (yysemantic_stack_[(4) - (3)].number)); currentBifOptions->metaHdrAttributes.encrBlocks = currentPartitionBifOptions->GetEncryptionBlocks(); } break; case 45: /* Line 670 of lalr1.cc */ #line 265 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(4) - (1)].number), 0); currentBifOptions->metaHdrAttributes.defEncrBlockSize = (yysemantic_stack_[(4) - (1)].number); } break; case 46: /* Line 670 of lalr1.cc */ #line 269 "../s/bif.y" { currentBifOptions->SetPdiId((yysemantic_stack_[(3) - (3)].number)); } break; case 47: /* Line 670 of lalr1.cc */ #line 270 "../s/bif.y" { currentBifOptions->SetParentId((yysemantic_stack_[(3) - (3)].number)); } break; case 48: /* Line 670 of lalr1.cc */ #line 271 "../s/bif.y" { currentBifOptions->SetIdCode((yysemantic_stack_[(3) - (3)].number)); } break; case 49: /* Line 670 of lalr1.cc */ #line 272 "../s/bif.y" { currentBifOptions->SetExtendedIdCode((yysemantic_stack_[(3) - (3)].number)); } break; case 50: /* Line 670 of lalr1.cc */ #line 273 "../s/bif.y" { currentBifOptions->AddFiles((yysemantic_stack_[(3) - (1)].number), (yysemantic_stack_[(3) - (3)].string)); } break; case 51: /* Line 670 of lalr1.cc */ #line 274 "../s/bif.y" { currentBifOptions->SetEncryptionKeySource((yysemantic_stack_[(3) - (3)].encrkeysrc_t)); } break; case 52: /* Line 670 of lalr1.cc */ #line 275 "../s/bif.y" { currentBifOptions->SetPdiType((yysemantic_stack_[(3) - (3)].ptype_t)); } break; case 53: /* Line 670 of lalr1.cc */ #line 276 "../s/bif.y" { currentBifOptions->SetRevokeId((yysemantic_stack_[(3) - (3)].number));} break; case 56: /* Line 670 of lalr1.cc */ #line 283 "../s/bif.y" { currentImageBifOptions = new ImageBifOptions(); } break; case 57: /* Line 670 of lalr1.cc */ #line 284 "../s/bif.y" { currentBifOptions->imageBifOptionList.push_back(currentImageBifOptions); } break; case 65: /* Line 670 of lalr1.cc */ #line 298 "../s/bif.y" { currentImageBifOptions->SetImageId((yysemantic_stack_[(3) - (3)].number)); } break; case 66: /* Line 670 of lalr1.cc */ #line 299 "../s/bif.y" { currentImageBifOptions->SetImageName((yysemantic_stack_[(3) - (3)].string)); } break; case 67: /* Line 670 of lalr1.cc */ #line 300 "../s/bif.y" { currentImageBifOptions->SetDelayHandoff(true); } break; case 68: /* Line 670 of lalr1.cc */ #line 301 "../s/bif.y" { currentImageBifOptions->SetDelayLoad(true); } break; case 69: /* Line 670 of lalr1.cc */ #line 302 "../s/bif.y" { LOG_ERROR("BIF attribute error !!!\n\t This usage of 'init' is not supported. See 'bootgen -bif_help init' for usage details."); } break; case 70: /* Line 670 of lalr1.cc */ #line 303 "../s/bif.y" { LOG_ERROR("Copy to Memory feature with the attribute 'copy' is no more supported.\n\t This can be duplicated with the option 'imagestore'. Please refer UG1283 for more details."); currentImageBifOptions->SetMemCopyAddress((yysemantic_stack_[(3) - (3)].number)); } break; case 71: /* Line 670 of lalr1.cc */ #line 305 "../s/bif.y" { currentImageBifOptions->SetImageType((yysemantic_stack_[(3) - (3)].ptype_t)); } break; case 72: /* Line 670 of lalr1.cc */ #line 306 "../s/bif.y" { currentImageBifOptions->SetUniqueId((yysemantic_stack_[(3) - (3)].number)); } break; case 73: /* Line 670 of lalr1.cc */ #line 307 "../s/bif.y" { currentImageBifOptions->SetParentUniqueId((yysemantic_stack_[(3) - (3)].number)); } break; case 74: /* Line 670 of lalr1.cc */ #line 308 "../s/bif.y" { currentImageBifOptions->SetFunctionId((yysemantic_stack_[(3) - (3)].number)); } break; case 75: /* Line 670 of lalr1.cc */ #line 309 "../s/bif.y" { if(!options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!!\n\t 'pcr' is supported only for VERSAL NET architecture"); currentImageBifOptions->SetPcrNumber((yysemantic_stack_[(3) - (3)].number)); } break; case 76: /* Line 670 of lalr1.cc */ #line 312 "../s/bif.y" { if(!options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!!\n\t 'pcr_mid' is supported only for VERSAL NET architecture"); currentImageBifOptions->SetPcrMeasurementIndex((yysemantic_stack_[(3) - (3)].number)); } break; case 82: /* Line 670 of lalr1.cc */ #line 326 "../s/bif.y" { if(options.GetArchType() == Arch::VERSAL) LOG_WARNING("BIF attribute error !!! [keysrc_encryption] not supported in VERSAL architecture.\n\t Please see 'bootgen -arch versal -bif_help keysrc'"); currentBifOptions->SetEncryptionKeySource((yysemantic_stack_[(4) - (4)].encrkeysrc_t)); options.SetEncryptedKeySource((yysemantic_stack_[(4) - (4)].encrkeysrc_t)); } break; case 83: /* Line 670 of lalr1.cc */ #line 329 "../s/bif.y" { if(options.GetArchType() == Arch::ZYNQ) LOG_ERROR("BIF attribute error !!!\n\t\t[fsbl_config] not supported in ZYNQ architecture"); } break; case 87: /* Line 670 of lalr1.cc */ #line 334 "../s/bif.y" { if(options.GetArchType() == Arch::ZYNQ) LOG_ERROR("BIF attribute error !!!\n\t\t[bootdevice] not supported in ZYNQ architecture"); if(options.GetArchType() == Arch::VERSAL) LOG_ERROR("This usage of boot_device is no more supported.\n\t Please see 'bootgen -arch versal -bif_help boot_device'"); currentBifOptions->SetBootDevice((yysemantic_stack_[(4) - (4)].bootdevice_t)); } break; case 88: /* Line 670 of lalr1.cc */ #line 339 "../s/bif.y" { LOG_ERROR("This usage of boot_device is no more supported.\n\t Please see 'bootgen -arch versal -bif_help boot_device'"); } break; case 96: /* Line 670 of lalr1.cc */ #line 351 "../s/bif.y" { currentBifOptions->SetBootDevice((yysemantic_stack_[(1) - (1)].bootdevice_t)); } break; case 97: /* Line 670 of lalr1.cc */ #line 352 "../s/bif.y" { currentBifOptions->SetBootDevice(BootDevice::IMAGESTORE); } break; case 98: /* Line 670 of lalr1.cc */ #line 353 "../s/bif.y" { currentBifOptions->SetBootDeviceAddress((yysemantic_stack_[(3) - (3)].number)); } break; case 105: /* Line 670 of lalr1.cc */ #line 366 "../s/bif.y" { currentBifOptions->SetAuthJtagRevokeID((yysemantic_stack_[(3) - (3)].number)); } break; case 106: /* Line 670 of lalr1.cc */ #line 367 "../s/bif.y" { currentBifOptions->SetAuthJtagDeviceDna((yysemantic_stack_[(3) - (3)].string)); } break; case 107: /* Line 670 of lalr1.cc */ #line 368 "../s/bif.y" { currentBifOptions->SetAuthJtagTimeOut((yysemantic_stack_[(3) - (3)].number)); } break; case 108: /* Line 670 of lalr1.cc */ #line 371 "../s/bif.y" { currentBifOptions->SetCore((yysemantic_stack_[(1) - (1)].core_t)); LOG_WARNING("[fsbl_config] a53_x64 | a53_x32 | r5_single | r5_dual is no more supported. Use 'destination_cpu' attribute for bootloader partition"); } break; case 109: /* Line 670 of lalr1.cc */ #line 374 "../s/bif.y" { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!! 'bh_auth_enable' is not supported with '-arch versalnet'.\n\t Bootheader or eFuse authentication will be chosen based on eFuse bits."); else currentBifOptions->SetBhRsa((yysemantic_stack_[(1) - (1)].bhrsa_t)); } break; case 110: /* Line 670 of lalr1.cc */ #line 380 "../s/bif.y" { LOG_ERROR("Authentication using SHA2 is no more supported."); } break; case 111: /* Line 670 of lalr1.cc */ #line 382 "../s/bif.y" { LOG_ERROR("[fsbl_config] bi_integrity_sha3 is no more supported. Use 'checksum' attribute of bootloader partition"); } break; case 112: /* Line 670 of lalr1.cc */ #line 384 "../s/bif.y" { currentBifOptions->SetPufHdLoc((yysemantic_stack_[(1) - (1)].pufhdloc_t)); } break; case 113: /* Line 670 of lalr1.cc */ #line 386 "../s/bif.y" { currentBifOptions->SetAuthOnly((yysemantic_stack_[(1) - (1)].authonly_t)); } break; case 114: /* Line 670 of lalr1.cc */ #line 388 "../s/bif.y" { currentBifOptions->SetOptKey((yysemantic_stack_[(1) - (1)].optkey_t)); } break; case 115: /* Line 670 of lalr1.cc */ #line 390 "../s/bif.y" { currentBifOptions->SetPufMode(PufMode::PUF4K); } break; case 116: /* Line 670 of lalr1.cc */ #line 392 "../s/bif.y" { currentBifOptions->SetShutterValue((yysemantic_stack_[(3) - (3)].number)); } break; case 117: /* Line 670 of lalr1.cc */ #line 394 "../s/bif.y" { if(options.GetArchType() != Arch::VERSAL) LOG_ERROR("BIF attribute error !!!\n\t\t'dpacm_enable' is supported only in VERSAL architecture"); if(options.GetArchType() == Arch::VERSAL) LOG_WARNING("boot_config { dpacm_enable } will be deprecated. 'dpacm_enable' should be specified along with the partition. \n See 'bootgen -bif_help dpacm_enable' for more info."); currentBifOptions->SetDpaCM((yysemantic_stack_[(1) - (1)].dpacm_t)); } break; case 118: /* Line 670 of lalr1.cc */ #line 400 "../s/bif.y" { if(((yysemantic_stack_[(3) - (3)].number) != 8) && ((yysemantic_stack_[(3) - (3)].number) !=16) && ((yysemantic_stack_[(3) - (3)].number) != 32) && ((yysemantic_stack_[(3) - (3)].number) != 0)) LOG_ERROR("Invalid smap_width value in BIF. Valid values are 8, 16 and 32"); currentBifOptions->SetSmapWidth((yysemantic_stack_[(3) - (3)].number)); } break; case 119: /* Line 670 of lalr1.cc */ #line 404 "../s/bif.y" { currentBifOptions->SetBypassIdcodeFlag(true); } break; case 120: /* Line 670 of lalr1.cc */ #line 405 "../s/bif.y" { currentBifOptions->SetAHwRoTFlag(true); } break; case 121: /* Line 670 of lalr1.cc */ #line 406 "../s/bif.y" { currentBifOptions->SetSHwRoTFlag(true); } break; case 122: /* Line 670 of lalr1.cc */ #line 407 "../s/bif.y" { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) currentBifOptions->SetPufRingOscilltorSwapConfigValue((yysemantic_stack_[(3) - (3)].number)); else LOG_ERROR("BIF attribute error !!!\n\t 'puf_ro_swap' is supported only in VersalNet architecture"); } break; case 123: /* Line 670 of lalr1.cc */ #line 412 "../s/bif.y" { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) currentBifOptions->SetDiceEnable(); else LOG_ERROR("BIF attribute error !!!\n\t 'dice_enable' is supported only in VersalNet architecture"); } break; case 124: /* Line 670 of lalr1.cc */ #line 419 "../s/bif.y" { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(),options.IsVersalNetSeries()); } break; case 125: /* Line 670 of lalr1.cc */ #line 422 "../s/bif.y" { currentPartitionBifOptions->filename = (yysemantic_stack_[(5) - (5)].string); currentPartitionBifOptions->filelist.push_back((yysemantic_stack_[(5) - (5)].string)); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } break; case 126: /* Line 670 of lalr1.cc */ #line 426 "../s/bif.y" { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); currentPartitionBifOptions->filename = (yysemantic_stack_[(1) - (1)].string); currentPartitionBifOptions->filelist.push_back((yysemantic_stack_[(1) - (1)].string)); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } break; case 127: /* Line 670 of lalr1.cc */ #line 432 "../s/bif.y" { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); } break; case 135: /* Line 670 of lalr1.cc */ #line 446 "../s/bif.y" { currentPartitionBifOptions->filename = (yysemantic_stack_[(3) - (3)].string); currentPartitionBifOptions->filelist.push_back((yysemantic_stack_[(3) - (3)].string)); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } break; case 136: /* Line 670 of lalr1.cc */ #line 449 "../s/bif.y" { currentPartitionBifOptions->partitionId = (yysemantic_stack_[(3) - (3)].number); } break; case 137: /* Line 670 of lalr1.cc */ #line 450 "../s/bif.y" { currentPartitionBifOptions->imageStoreId = (yysemantic_stack_[(3) - (3)].number); currentPartitionBifOptions->SetPartitionType(PartitionType::IMAGE_STORE_PDI); } break; case 139: /* Line 670 of lalr1.cc */ #line 453 "../s/bif.y" { currentPartitionBifOptions->fileType = (yysemantic_stack_[(3) - (3)].number); } break; case 140: /* Line 670 of lalr1.cc */ #line 454 "../s/bif.y" { currentPartitionBifOptions->bifSection = (yysemantic_stack_[(3) - (3)].string); currentPartitionBifOptions->filename = currentPartitionBifOptions->GetOutputFileFromBifSection(options.GetOutputFileNames().front(), (yysemantic_stack_[(3) - (3)].string), currentImageBifOptions->GetImageType()); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } break; case 154: /* Line 670 of lalr1.cc */ #line 482 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[bootvectors] only supported in ZYNQMP architecture"); currentBifOptions->SetBootVectorArray((yysemantic_stack_[(1) - (1)].number)); } break; case 155: /* Line 670 of lalr1.cc */ #line 487 "../s/bif.y" { currentPartitionBifOptions->SetAuthBlockAttr((yysemantic_stack_[(1) - (1)].number)); } break; case 156: /* Line 670 of lalr1.cc */ #line 489 "../s/bif.y" { currentPartitionBifOptions->bootloader = true;} break; case 157: /* Line 670 of lalr1.cc */ #line 490 "../s/bif.y" { currentPartitionBifOptions->boot = true;} break; case 158: /* Line 670 of lalr1.cc */ #line 491 "../s/bif.y" { currentPartitionBifOptions->user = true;} break; case 159: /* Line 670 of lalr1.cc */ #line 492 "../s/bif.y" { currentPartitionBifOptions->Static = true;} break; case 160: /* Line 670 of lalr1.cc */ #line 493 "../s/bif.y" { currentPartitionBifOptions->noautostart = true;} break; case 161: /* Line 670 of lalr1.cc */ #line 494 "../s/bif.y" { currentPartitionBifOptions->multiboot = true;} break; case 162: /* Line 670 of lalr1.cc */ #line 495 "../s/bif.y" { currentPartitionBifOptions->Protected = true;} break; case 163: /* Line 670 of lalr1.cc */ #line 496 "../s/bif.y" { currentPartitionBifOptions->SetEarlyHandoff(true); } break; case 164: /* Line 670 of lalr1.cc */ #line 497 "../s/bif.y" { currentPartitionBifOptions->SetHivec(true); } break; case 165: /* Line 670 of lalr1.cc */ #line 498 "../s/bif.y" { if(currentPartitionBifOptions->bootloader!=true) LOG_ERROR("XIP mode can be enabled only for bootloader"); currentBifOptions->SetXipMode(); } break; case 166: /* Line 670 of lalr1.cc */ #line 501 "../s/bif.y" { currentPartitionBifOptions->fileType = (yysemantic_stack_[(1) - (1)].number); } break; case 167: /* Line 670 of lalr1.cc */ #line 502 "../s/bif.y" { currentPartitionBifOptions->bootImage = true; } break; case 168: /* Line 670 of lalr1.cc */ #line 503 "../s/bif.y" { currentPartitionBifOptions->fileType = (yysemantic_stack_[(1) - (1)].number); } break; case 169: /* Line 670 of lalr1.cc */ #line 504 "../s/bif.y" { currentPartitionBifOptions->fileType = (yysemantic_stack_[(1) - (1)].number); } break; case 170: /* Line 670 of lalr1.cc */ #line 505 "../s/bif.y" { currentPartitionBifOptions->SetPartitionType((yysemantic_stack_[(1) - (1)].ptype_t)); } break; case 171: /* Line 670 of lalr1.cc */ #line 506 "../s/bif.y" { currentPartitionBifOptions->SetLockStepFlag();} break; case 172: /* Line 670 of lalr1.cc */ #line 509 "../s/bif.y" { currentPartitionBifOptions->SetTrustZone(::TrustZone::Secure); } break; case 173: /* Line 670 of lalr1.cc */ #line 510 "../s/bif.y" { currentPartitionBifOptions->SetTrustZone((yysemantic_stack_[(3) - (3)].trustzone_t)); } break; case 174: /* Line 670 of lalr1.cc */ #line 513 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(1) - (1)].number)); } break; case 175: /* Line 670 of lalr1.cc */ #line 514 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(4) - (1)].number), (yysemantic_stack_[(4) - (3)].number)); } break; case 176: /* Line 670 of lalr1.cc */ #line 515 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionBlocks((yysemantic_stack_[(4) - (1)].number), 0); } break; case 177: /* Line 670 of lalr1.cc */ #line 517 "../s/bif.y" { currentPartitionBifOptions->SetAuthType((yysemantic_stack_[(3) - (3)].authvalue_t)); } break; case 178: /* Line 670 of lalr1.cc */ #line 518 "../s/bif.y" { currentPartitionBifOptions->SetEncryptType((yysemantic_stack_[(3) - (3)].encrvalue_t)); } break; case 179: /* Line 670 of lalr1.cc */ #line 519 "../s/bif.y" { currentPartitionBifOptions->SetChecksumType((yysemantic_stack_[(3) - (3)].checksumvalue_t)); } break; case 180: /* Line 670 of lalr1.cc */ #line 520 "../s/bif.y" { currentPartitionBifOptions->SetOwnerType((yysemantic_stack_[(3) - (3)].powner_t)); } break; case 181: /* Line 670 of lalr1.cc */ #line 521 "../s/bif.y" { currentPartitionBifOptions->SetDestCpu((yysemantic_stack_[(3) - (3)].destcpu_t)); } break; case 182: /* Line 670 of lalr1.cc */ #line 522 "../s/bif.y" { currentPartitionBifOptions->SetDestDevice((yysemantic_stack_[(3) - (3)].destdevice_t)); } break; case 183: /* Line 670 of lalr1.cc */ #line 523 "../s/bif.y" { currentPartitionBifOptions->SetExceptionLevel((yysemantic_stack_[(3) - (3)].el_t)); } break; case 184: /* Line 670 of lalr1.cc */ #line 524 "../s/bif.y" { currentPartitionBifOptions->SetAesKeyFile((yysemantic_stack_[(3) - (3)].string)); } break; case 185: /* Line 670 of lalr1.cc */ #line 525 "../s/bif.y" { currentPartitionBifOptions->ppkFile = ((yysemantic_stack_[(3) - (3)].string)); } break; case 186: /* Line 670 of lalr1.cc */ #line 526 "../s/bif.y" { currentPartitionBifOptions->pskFile = ((yysemantic_stack_[(3) - (3)].string)); } break; case 187: /* Line 670 of lalr1.cc */ #line 527 "../s/bif.y" { currentPartitionBifOptions->spkFile = ((yysemantic_stack_[(3) - (3)].string)); } break; case 188: /* Line 670 of lalr1.cc */ #line 528 "../s/bif.y" { currentPartitionBifOptions->sskFile = ((yysemantic_stack_[(3) - (3)].string)); } break; case 189: /* Line 670 of lalr1.cc */ #line 529 "../s/bif.y" { currentPartitionBifOptions->spkSelect =((yysemantic_stack_[(3) - (3)].spkselect_t)); currentPartitionBifOptions->spkSelLocal = true; } break; case 190: /* Line 670 of lalr1.cc */ #line 530 "../s/bif.y" { currentPartitionBifOptions->SetSpkId((yysemantic_stack_[(3) - (3)].number)); } break; case 191: /* Line 670 of lalr1.cc */ #line 531 "../s/bif.y" { currentPartitionBifOptions->spkSignatureFile = ((yysemantic_stack_[(3) - (3)].string)); } break; case 193: /* Line 670 of lalr1.cc */ #line 533 "../s/bif.y" { currentPartitionBifOptions->SetPartitionType((yysemantic_stack_[(3) - (3)].ptype_t)); } break; case 194: /* Line 670 of lalr1.cc */ #line 534 "../s/bif.y" { currentPartitionBifOptions->SetEncryptionKeySource((yysemantic_stack_[(3) - (3)].encrkeysrc_t)); } break; case 195: /* Line 670 of lalr1.cc */ #line 535 "../s/bif.y" { currentPartitionBifOptions->SetRevokeId((yysemantic_stack_[(3) - (3)].number)); } break; case 196: /* Line 670 of lalr1.cc */ #line 536 "../s/bif.y" { currentPartitionBifOptions->SetDpaCM(DpaCM::DpaCMEnable); } break; case 197: /* Line 670 of lalr1.cc */ #line 537 "../s/bif.y" { currentPartitionBifOptions->SetSlrNum((yysemantic_stack_[(3) - (3)].number)); } break; case 198: /* Line 670 of lalr1.cc */ #line 538 "../s/bif.y" { currentPartitionBifOptions->SetClusterNum((yysemantic_stack_[(3) - (3)].number)); } break; case 199: /* Line 670 of lalr1.cc */ #line 539 "../s/bif.y" { currentPartitionBifOptions->SetPufHdLocation(PufHdLoc::PUFinBH); } break; case 200: /* Line 670 of lalr1.cc */ #line 540 "../s/bif.y" { currentPartitionBifOptions->SetDelayAuth(true); } break; case 201: /* Line 670 of lalr1.cc */ #line 541 "../s/bif.y" { currentPartitionBifOptions->SetTcmBootFlag(); } break; case 210: /* Line 670 of lalr1.cc */ #line 554 "../s/bif.y" { (yyval.authvalue_t) = ::Authentication::None;} break; case 212: /* Line 670 of lalr1.cc */ #line 558 "../s/bif.y" { (yyval.encrvalue_t) = ::Encryption::None;} break; case 214: /* Line 670 of lalr1.cc */ #line 562 "../s/bif.y" { (yyval.checksumvalue_t) = ::Checksum::None;} break; case 231: /* Line 670 of lalr1.cc */ #line 611 "../s/bif.y" { currentPartitionBifOptions->alignment = (yysemantic_stack_[(3) - (3)].number); } break; case 232: /* Line 670 of lalr1.cc */ #line 612 "../s/bif.y" { currentPartitionBifOptions->offset = (yysemantic_stack_[(3) - (3)].number); } break; case 233: /* Line 670 of lalr1.cc */ #line 613 "../s/bif.y" { currentPartitionBifOptions->SetReserveLength((yysemantic_stack_[(3) - (3)].number), false); } break; case 234: /* Line 670 of lalr1.cc */ #line 614 "../s/bif.y" { currentPartitionBifOptions->SetReserveLength((yysemantic_stack_[(3) - (3)].number), true); } break; case 235: /* Line 670 of lalr1.cc */ #line 615 "../s/bif.y" { currentPartitionBifOptions->load = (yysemantic_stack_[(3) - (3)].number); } break; case 236: /* Line 670 of lalr1.cc */ #line 616 "../s/bif.y" { currentPartitionBifOptions->startup = (yysemantic_stack_[(3) - (3)].number); } break; case 237: /* Line 670 of lalr1.cc */ #line 617 "../s/bif.y" { currentPartitionBifOptions->bigEndian = true; } break; case 238: /* Line 670 of lalr1.cc */ #line 618 "../s/bif.y" { currentPartitionBifOptions->a32Mode = true; } break; case 239: /* Line 670 of lalr1.cc */ #line 619 "../s/bif.y" { currentPartitionBifOptions->pid = (yysemantic_stack_[(3) - (3)].number); } break; case 240: /* Line 670 of lalr1.cc */ #line 620 "../s/bif.y" { currentPartitionBifOptions->SetTcmARegion((yysemantic_stack_[(3) - (3)].number)); } break; case 241: /* Line 670 of lalr1.cc */ #line 621 "../s/bif.y" { currentPartitionBifOptions->SetTcmBRegion((yysemantic_stack_[(3) - (3)].number)); } break; case 242: /* Line 670 of lalr1.cc */ #line 622 "../s/bif.y" { currentPartitionBifOptions->SetTcmCRegion((yysemantic_stack_[(3) - (3)].number)); } break; case 243: /* Line 670 of lalr1.cc */ #line 625 "../s/bif.y" { currentPartitionBifOptions->presignFile = (yysemantic_stack_[(3) - (3)].string); } break; case 244: /* Line 670 of lalr1.cc */ #line 626 "../s/bif.y" { currentPartitionBifOptions->acFile = (yysemantic_stack_[(3) - (3)].string); } break; case 245: /* Line 670 of lalr1.cc */ #line 627 "../s/bif.y" { currentPartitionBifOptions->SetUdfDataFile((yysemantic_stack_[(3) - (3)].string)); } break; case 262: /* Line 670 of lalr1.cc */ #line 652 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetPPKSelection((yysemantic_stack_[(3) - (3)].number)); } break; case 263: /* Line 670 of lalr1.cc */ #line 655 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetSPKSelection((yysemantic_stack_[(3) - (3)].spkselect_t)); } break; case 264: /* Line 670 of lalr1.cc */ #line 658 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_WARNING("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetSpkId((yysemantic_stack_[(3) - (3)].number)); } break; case 265: /* Line 670 of lalr1.cc */ #line 661 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetHeaderAuthentication(); } break; case 268: /* Line 670 of lalr1.cc */ #line 670 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitMode((yysemantic_stack_[(3) - (3)].splitmode_t)); } break; case 272: /* Line 670 of lalr1.cc */ #line 680 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitFmt(File::MCS); } break; case 273: /* Line 670 of lalr1.cc */ #line 683 "../s/bif.y" { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitFmt(File::BIN); } break; case 278: /* Line 670 of lalr1.cc */ #line 695 "../s/bif.y" { (yyval.number) = (yysemantic_stack_[(3) - (2)].number); } break; case 280: /* Line 670 of lalr1.cc */ #line 702 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(2) - (2)].number); *options.debugstr << (yyval.number) << " + " << (yysemantic_stack_[(2) - (2)].number) << std::endl;} break; case 281: /* Line 670 of lalr1.cc */ #line 703 "../s/bif.y" {(yyval.number) = ~(yysemantic_stack_[(2) - (2)].number); *options.debugstr << (yyval.number) << " ~ " << (yysemantic_stack_[(2) - (2)].number) << std::endl;} break; case 283: /* Line 670 of lalr1.cc */ #line 708 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) * (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " + " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 284: /* Line 670 of lalr1.cc */ #line 709 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) / (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " / " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 285: /* Line 670 of lalr1.cc */ #line 710 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) % (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " % " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 287: /* Line 670 of lalr1.cc */ #line 714 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) + (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " + " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 288: /* Line 670 of lalr1.cc */ #line 715 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) - (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " - " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 290: /* Line 670 of lalr1.cc */ #line 719 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) << (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " << " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 291: /* Line 670 of lalr1.cc */ #line 720 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) >> (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " >> " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 293: /* Line 670 of lalr1.cc */ #line 724 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) & (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " & " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 295: /* Line 670 of lalr1.cc */ #line 728 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) ^ (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " ^ " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 297: /* Line 670 of lalr1.cc */ #line 733 "../s/bif.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) | (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " | " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; /* Line 670 of lalr1.cc */ #line 1507 "../bisonflex/bif.tab.cpp" default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc); yypop_ (yylen); yylen = 0; YY_STACK_PRINT (); yysemantic_stack_.push (yyval); yylocation_stack_.push (yyloc); /* Shift the result of the reduction. */ yyn = yyr1_[yyn]; yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0]; if (0 <= yystate && yystate <= yylast_ && yycheck_[yystate] == yystate_stack_[0]) yystate = yytable_[yystate]; else yystate = yydefgoto_[yyn - yyntokens_]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus_) { ++yynerrs_; if (yychar == yyempty_) yytoken = yyempty_; error (yylloc, yysyntax_error_ (yystate, yytoken)); } yyerror_range[1] = yylloc; if (yyerrstatus_ == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= yyeof_) { /* Return failure if at end of input. */ if (yychar == yyeof_) YYABORT; } else { yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); yychar = yyempty_; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (false) goto yyerrorlab; yyerror_range[1] = yylocation_stack_[yylen - 1]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ yypop_ (yylen); yylen = 0; yystate = yystate_stack_[0]; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus_ = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact_[yystate]; if (!yy_pact_value_is_default_ (yyn)) { yyn += yyterror_; if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_) { yyn = yytable_[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yystate_stack_.height () == 1) YYABORT; yyerror_range[1] = yylocation_stack_[0]; yydestruct_ ("Error: popping", yystos_[yystate], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); yystate = yystate_stack_[0]; YY_STACK_PRINT (); } yyerror_range[2] = yylloc; // Using YYLLOC is tempting, but would change the location of // the lookahead. YYLOC is available though. YYLLOC_DEFAULT (yyloc, yyerror_range, 2); yysemantic_stack_.push (yylval); yylocation_stack_.push (yyloc); /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos_[yyn], &yysemantic_stack_[0], &yylocation_stack_[0]); yystate = yyn; goto yynewstate; /* Accept. */ yyacceptlab: yyresult = 0; goto yyreturn; /* Abort. */ yyabortlab: yyresult = 1; goto yyreturn; yyreturn: if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ yypop_ (yylen); while (1 < yystate_stack_.height ()) { yydestruct_ ("Cleanup: popping", yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } return yyresult; } catch (...) { YYCDEBUG << "Exception caught: cleaning lookahead and stack" << std::endl; // Do not try to display the values of the reclaimed symbols, // as their printer might throw an exception. if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc); } while (1 < yystate_stack_.height ()) { yydestruct_ (YY_NULL, yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } throw; } } // Generate an error message. std::string BisonParser::yysyntax_error_ (int, int) { return YY_("syntax error"); } /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ const short int BisonParser::yypact_ninf_ = -388; const short int BisonParser::yypact_[] = { -388, 13, 42, -388, 12, -388, -388, 32, 14, -388, -388, -388, 72, -388, 811, -388, -388, -11, 86, 97, 113, 128, 145, 152, 160, 163, -388, 164, 171, 180, 186, 197, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, 135, -388, -388, 106, -388, -388, -388, 205, -388, -388, -388, 600, 211, 215, 220, -388, 223, 225, 739, 114, 50, 108, -79, -79, -79, -79, -388, -79, 106, 32, -388, 122, 294, 29, -388, -388, -388, -388, 32, -388, -388, -388, -388, -388, 254, 255, 256, 257, 261, 267, 268, 269, 271, 272, 273, 274, 281, 282, 283, 284, -388, -388, 285, 286, 287, -388, -388, -388, -388, -388, -388, 288, 291, 292, 296, 298, 300, 303, 304, 305, 306, -388, 307, -388, 308, 309, 311, 312, -388, -388, -388, -388, -388, 313, 315, 323, 329, 334, 335, -388, -388, -388, 297, 18, 461, -388, -388, -388, -388, -388, -388, -388, -388, -388, 108, -79, 122, 289, 117, -15, 336, 332, 339, -388, 340, -388, -388, 341, 344, -388, -388, -388, -388, -79, -79, -79, -388, -388, 5, 43, 44, 196, 199, 201, 201, 201, 201, -388, 201, 347, 350, 355, 206, -388, -388, -388, -388, -388, -388, -388, 359, 363, 369, -388, -388, -388, -388, -388, -388, -388, -388, 357, 103, -388, -388, -388, -388, -388, -388, -388, -388, 370, 372, 373, 376, 19, -388, -50, -36, -39, 249, 900, -79, 239, 240, 238, 241, -79, -79, -79, -79, -79, -79, -79, 242, -79, -79, -79, 32, 32, 301, 32, -79, -79, -79, -79, 32, -79, -79, -79, 122, 32, 32, 32, 32, 32, 32, -388, 600, -388, 600, -388, -388, -388, 385, 201, -388, 294, 386, 388, 394, -388, 398, 407, 408, 417, 114, 32, 739, -79, -388, 50, -388, -388, -67, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, 295, -388, 32, 349, 419, 421, 423, 424, 432, 433, 434, 435, 436, 437, 439, 440, 441, -388, -388, 444, 198, -79, -79, -79, -388, 294, -388, -79, 358, -79, -388, 29, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, 201, -388, -388, -388, -388, -388, -388, -388, 201, 201, 201, 201, 201, 201, 201, -388, -388, 201, -388, 442, -141, -388, 201, -388, -388, -388, -388, 201, 201, 201, 201, -388, 201, 201, 201, -388, -388, -388, -388, -388, -388, -388, -388, -388, -79, -388, -79, -79, 242, 117, 310, 161, -15, -388, -388, -388, 201, -388, -388, -388, -388, -388, 5, 5, 43, 43, 44, 196, 199, -388, 446, 448, 449, 450, 454, 455, 456, 457, -388, -388, 458, -388, -388, 333, -388, -388, -388, 478, -50, -36, -39, -79, -79, 32, 122, 32, 32, 32, 32, 32, 32, -388, 206, -388, 201, 201, 201, -388, 201, -388, 201, -388, -79, 70, -388, 201, 201, -388, 398, -388, -388, -388, -388, -388, 417, 114, -79, -79, -79, -79, -79, -79, 360, -79, 880, -388, -79, -388, -388, -388, 201, -388, 489, -134, -388, -388, -388, -388, -388, -388, -388, -388, -388, -388, 337, -41, -388, 201, 201, 201, 201, 201, 201, -388, 201, -388, 201, -79, 92, -388, -388, -388, 354, -35, -388, -388 }; /* YYDEFACT[S] -- default reduction number in state S. Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ const unsigned short int BisonParser::yydefact_[] = { 3, 0, 2, 1, 0, 6, 4, 0, 0, 274, 275, 5, 0, 8, 0, 127, 7, 124, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 252, 251, 253, 204, 205, 206, 207, 208, 209, 202, 246, 254, 255, 256, 257, 258, 248, 249, 250, 12, 13, 11, 54, 15, 78, 10, 9, 14, 0, 203, 247, 126, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 77, 40, 16, 0, 0, 0, 55, 124, 80, 81, 0, 156, 165, 163, 164, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 237, 238, 0, 0, 0, 157, 158, 159, 160, 161, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 201, 0, 0, 0, 0, 260, 167, 261, 166, 259, 246, 255, 256, 257, 258, 248, 217, 199, 196, 0, 130, 129, 147, 143, 192, 144, 170, 145, 146, 168, 169, 0, 0, 0, 0, 0, 0, 0, 0, 141, 52, 0, 97, 227, 0, 94, 96, 88, 277, 276, 0, 0, 0, 279, 282, 286, 289, 292, 294, 296, 53, 47, 48, 49, 58, 46, 0, 37, 0, 21, 218, 51, 123, 119, 120, 121, 115, 0, 0, 0, 219, 220, 222, 223, 224, 225, 226, 221, 0, 99, 108, 109, 117, 110, 111, 112, 114, 113, 0, 0, 0, 0, 102, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 133, 0, 134, 87, 91, 152, 154, 82, 0, 0, 0, 0, 265, 89, 0, 0, 90, 0, 0, 0, 0, 86, 0, 280, 281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 93, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 34, 0, 18, 0, 0, 0, 85, 0, 101, 0, 0, 0, 92, 0, 104, 210, 211, 177, 212, 213, 178, 214, 215, 179, 216, 180, 139, 138, 170, 239, 229, 182, 228, 181, 230, 183, 173, 231, 232, 233, 234, 235, 236, 190, 267, 189, 195, 148, 150, 174, 149, 155, 243, 244, 140, 245, 197, 198, 137, 136, 135, 240, 241, 242, 194, 184, 185, 186, 187, 188, 191, 131, 132, 0, 84, 0, 0, 0, 0, 0, 0, 0, 193, 125, 142, 98, 95, 278, 283, 284, 285, 287, 288, 290, 291, 293, 295, 297, 57, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 59, 62, 61, 60, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 21, 20, 122, 116, 118, 100, 105, 106, 107, 103, 0, 0, 153, 262, 264, 263, 266, 271, 268, 272, 273, 269, 270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 25, 22, 33, 32, 35, 41, 43, 31, 23, 24, 26, 27, 28, 29, 30, 19, 151, 0, 0, 71, 75, 76, 72, 73, 74, 65, 66, 70, 63, 39, 0, 0, 176, 175, 42, 0, 0, 45, 44 }; /* YYPGOTO[NTERM-NUM]. */ const short int BisonParser::yypgoto_[] = { -388, -388, -388, -388, -388, -388, -388, -388, -318, -388, 167, -388, -29, -388, -388, -388, 451, -388, -388, -387, -388, 195, 493, -388, -388, 218, -388, -210, -231, -388, -388, -10, -388, 509, -388, -131, -388, 226, -63, -388, 47, 119, -388, -388, 290, -388, -388, -388, -388, 73, 75, 76, -388, -62, -163, -388, -388, -388, -388, -388, -388, -388, -388, -65, -388, -388, -388, -388, -388, 516, -388, -388, 118, 120, 121, -388, -388, 7, -388, -96, -91, -84, 222, 219, 224, -75 }; /* YYDEFGOTO[NTERM-NUM]. */ const short int BisonParser::yydefgoto_[] = { -1, 1, 2, 6, 8, 14, 51, 205, 337, 338, 202, 203, 506, 507, 52, 53, 54, 200, 318, 447, 448, 55, 56, 57, 170, 180, 181, 224, 237, 238, 225, 89, 71, 90, 64, 155, 156, 174, 157, 158, 383, 286, 287, 386, 159, 160, 384, 161, 60, 353, 356, 359, 361, 162, 207, 226, 227, 228, 229, 230, 231, 232, 233, 182, 369, 367, 371, 163, 164, 165, 62, 166, 295, 381, 298, 485, 488, 63, 189, 190, 191, 192, 193, 194, 195, 288 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF_, syntax error. */ const signed char BisonParser::yytable_ninf_ = -1; const unsigned short int BisonParser::yytable_[] = { 196, 197, 198, 199, 58, 201, 289, 350, 175, 183, 176, 317, 65, 3, 11, 344, 184, 185, 317, 7, 468, 12, 478, 281, 349, 282, 284, 296, 297, 533, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 66, 103, 104, 351, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 357, 115, 116, 354, 117, 234, 500, 118, 119, 120, 121, 122, 123, 124, 125, 234, 126, 127, 128, 129, 13, 177, 130, 131, 186, 410, 352, 132, 187, 188, 317, 67, 68, 69, 204, 305, 306, 72, 133, 358, 70, 355, 423, 239, 134, 73, 135, 285, 74, 136, 137, 138, 139, 343, 15, 400, 317, 530, 307, 178, 140, 88, 317, 476, 75, 235, 236, 4, 535, 9, 10, 32, 33, 34, 540, 235, 236, 5, 472, 76, 141, 142, 143, 144, 145, 146, 43, 147, 148, 149, 150, 151, 49, 50, 517, 407, 77, 408, 152, 291, 292, 293, 294, 78, 153, 308, 309, 310, 79, 208, 184, 185, 82, 154, 80, 365, 209, 210, 211, 83, 373, 374, 375, 376, 377, 378, 379, 364, 382, 385, 387, 84, 184, 185, 85, 392, 393, 394, 395, 179, 397, 398, 399, 9, 10, 86, 311, 312, 467, 313, 314, 212, 213, 214, 24, 215, 91, 424, 425, 426, 322, 323, 324, 486, 487, 427, 428, 167, 322, 323, 324, 168, 421, 186, 429, 430, 169, 187, 188, 171, 519, 172, 418, 175, 325, 216, 217, 218, 219, 220, 221, 222, 325, 326, 152, 186, 327, 179, 223, 187, 188, 326, 537, 206, 327, 240, 241, 242, 243, 469, 470, 471, 244, 388, 389, 473, 391, 475, 245, 246, 247, 396, 248, 249, 250, 251, 401, 402, 403, 404, 405, 406, 252, 253, 254, 255, 256, 257, 258, 259, 328, 510, 260, 261, 434, 290, 280, 262, 328, 263, 88, 264, 419, 450, 265, 266, 267, 268, 269, 270, 271, 435, 272, 273, 274, 329, 275, 330, 331, 332, 333, 334, 204, 329, 276, 330, 331, 332, 333, 334, 277, 480, 481, 499, 335, 278, 279, 299, 300, 301, 303, 302, 335, 336, 304, 315, 319, 316, 317, 435, 208, 336, 436, 437, 320, 321, 342, 209, 210, 211, 339, 438, 439, 440, 340, 441, 442, 443, 444, 445, 341, 345, 26, 346, 347, 348, 505, 508, 360, 366, 370, 368, 9, 10, 372, 409, 390, 411, 380, 412, 436, 437, 212, 213, 214, 413, 215, 385, 520, 438, 439, 440, 414, 441, 442, 443, 444, 445, 415, 416, 446, 522, 523, 524, 525, 526, 527, 417, 529, 452, 453, 531, 454, 521, 455, 456, 216, 217, 218, 219, 220, 221, 222, 457, 458, 459, 460, 461, 462, 223, 463, 464, 465, 466, 474, 528, 477, 490, 446, 491, 492, 493, 508, 538, 484, 494, 495, 496, 497, 498, 509, 283, 511, 512, 513, 514, 515, 516, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 501, 103, 104, 451, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 532, 115, 116, 534, 117, 536, 87, 118, 119, 120, 121, 122, 123, 124, 125, 449, 126, 127, 128, 129, 539, 81, 130, 131, 422, 59, 518, 132, 502, 420, 479, 503, 61, 504, 483, 482, 363, 432, 133, 431, 489, 0, 0, 433, 134, 0, 135, 0, 0, 136, 137, 138, 139, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, 145, 146, 43, 147, 148, 149, 150, 151, 49, 50, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 154, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 0, 103, 104, 0, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 115, 116, 0, 117, 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, 129, 0, 0, 130, 131, 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 0, 0, 0, 0, 0, 134, 0, 135, 0, 0, 136, 137, 138, 139, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, 145, 146, 43, 147, 148, 149, 150, 151, 49, 50, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 154, 92, 93, 94, 95, 96, 97, 98, 99, 100, 173, 102, 0, 103, 104, 0, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 115, 116, 0, 117, 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, 0, 129, 0, 0, 130, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 0, 0, 0, 134, 17, 0, 0, 0, 136, 137, 138, 139, 0, 0, 0, 18, 0, 19, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 0, 0, 20, 0, 0, 0, 141, 142, 143, 144, 145, 146, 43, 147, 148, 149, 150, 151, 49, 50, 0, 0, 0, 0, 152, 0, 21, 22, 23, 0, 153, 0, 0, 0, 0, 24, 25, 0, 0, 154, 0, 0, 0, 26, 0, 27, 28, 0, 0, 0, 0, 435, 0, 9, 10, 0, 0, 0, 29, 30, 0, 31, 92, 93, 94, 95, 96, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 41, 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, 436, 437, 118, 119, 120, 121, 122, 123, 0, 438, 439, 440, 0, 441, 442, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 446, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 0, 0, 0, 0, 0, 0, 362, 142, 143, 144, 145, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 0, 0, 0, 152 }; /* YYCHECK. */ const short int BisonParser::yycheck_[] = { 75, 76, 77, 78, 14, 80, 169, 238, 71, 74, 72, 152, 23, 0, 7, 225, 95, 96, 152, 7, 338, 7, 163, 5, 5, 156, 157, 42, 43, 163, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 52, 24, 25, 94, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 94, 38, 39, 94, 41, 41, 448, 44, 45, 46, 47, 48, 49, 50, 51, 41, 53, 54, 55, 56, 3, 26, 59, 60, 158, 290, 131, 64, 162, 163, 152, 97, 98, 99, 82, 186, 187, 6, 75, 133, 106, 132, 164, 91, 81, 3, 83, 167, 6, 86, 87, 88, 89, 5, 3, 273, 152, 499, 188, 64, 97, 10, 152, 349, 6, 101, 102, 80, 164, 92, 93, 108, 109, 110, 164, 101, 102, 90, 343, 6, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 467, 281, 6, 283, 135, 37, 38, 39, 40, 6, 141, 155, 156, 157, 3, 61, 95, 96, 3, 150, 6, 245, 68, 69, 70, 3, 250, 251, 252, 253, 254, 255, 256, 244, 258, 259, 260, 6, 95, 96, 3, 265, 266, 267, 268, 144, 270, 271, 272, 92, 93, 3, 158, 159, 5, 160, 161, 103, 104, 105, 74, 107, 6, 308, 309, 310, 17, 18, 19, 57, 58, 311, 312, 11, 17, 18, 19, 11, 302, 158, 313, 314, 11, 162, 163, 11, 165, 11, 299, 301, 41, 137, 138, 139, 140, 141, 142, 143, 41, 50, 135, 158, 53, 144, 150, 162, 163, 50, 165, 136, 53, 6, 6, 6, 6, 339, 340, 341, 6, 261, 262, 345, 264, 347, 6, 6, 6, 269, 6, 6, 6, 6, 274, 275, 276, 277, 278, 279, 6, 6, 6, 6, 6, 6, 6, 6, 97, 459, 6, 6, 4, 11, 4, 6, 97, 6, 10, 6, 300, 318, 6, 6, 6, 6, 6, 6, 6, 21, 6, 6, 6, 122, 6, 124, 125, 126, 127, 128, 320, 122, 6, 124, 125, 126, 127, 128, 6, 411, 412, 5, 141, 6, 6, 6, 11, 5, 4, 6, 141, 150, 5, 154, 4, 153, 152, 21, 61, 150, 62, 63, 9, 5, 4, 68, 69, 70, 6, 71, 72, 73, 6, 75, 76, 77, 78, 79, 6, 6, 82, 6, 6, 4, 456, 457, 134, 145, 147, 146, 92, 93, 148, 5, 90, 6, 151, 6, 62, 63, 103, 104, 105, 6, 107, 477, 478, 71, 72, 73, 9, 75, 76, 77, 78, 79, 6, 6, 120, 491, 492, 493, 494, 495, 496, 5, 498, 75, 6, 501, 6, 490, 6, 6, 137, 138, 139, 140, 141, 142, 143, 6, 6, 6, 6, 6, 6, 150, 6, 6, 6, 4, 91, 90, 9, 6, 120, 6, 6, 6, 532, 533, 149, 6, 6, 6, 6, 6, 458, 5, 460, 461, 462, 463, 464, 465, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 6, 24, 25, 320, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 9, 38, 39, 164, 41, 532, 53, 44, 45, 46, 47, 48, 49, 50, 51, 318, 53, 54, 55, 56, 164, 26, 59, 60, 304, 14, 477, 64, 453, 301, 409, 454, 14, 455, 414, 413, 244, 316, 75, 315, 417, -1, -1, 317, 81, -1, 83, -1, -1, 86, 87, 88, 89, -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, 109, 110, -1, -1, -1, -1, -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -1, -1, -1, -1, 135, -1, -1, -1, -1, -1, 141, -1, -1, -1, -1, -1, -1, -1, -1, 150, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, 24, 25, -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, 41, -1, -1, 44, 45, 46, 47, 48, 49, 50, 51, -1, 53, 54, 55, 56, -1, -1, 59, 60, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, -1, 83, -1, -1, 86, 87, 88, 89, -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, 109, 110, -1, -1, -1, -1, -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -1, -1, -1, -1, 135, -1, -1, -1, -1, -1, 141, -1, -1, -1, -1, -1, -1, -1, -1, 150, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, 24, 25, -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, 41, -1, -1, 44, 45, 46, 47, 48, 49, 50, 51, -1, 53, 54, -1, 56, -1, -1, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, -1, -1, 81, 10, -1, -1, -1, 86, 87, 88, 89, -1, -1, -1, 21, -1, 23, -1, 97, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, 109, 110, -1, -1, 41, -1, -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -1, -1, -1, -1, 135, -1, 65, 66, 67, -1, 141, -1, -1, -1, -1, 74, 75, -1, -1, 150, -1, -1, -1, 82, -1, 84, 85, -1, -1, -1, -1, 21, -1, 92, 93, -1, -1, -1, 97, 98, -1, 100, 12, 13, 14, 15, 16, -1, -1, 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, -1, -1, 120, -1, 122, 123, 124, 125, 126, 127, 128, 129, 130, 62, 63, 44, 45, 46, 47, 48, 49, -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, -1, -1, 108, 109, 110, -1, -1, -1, -1, -1, -1, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -1, -1, -1, -1, 135 }; /* STOS_[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ const unsigned char BisonParser::yystos_[] = { 0, 167, 168, 0, 80, 90, 169, 7, 170, 92, 93, 243, 7, 3, 171, 3, 4, 10, 21, 23, 41, 65, 66, 67, 74, 75, 82, 84, 85, 97, 98, 100, 108, 109, 110, 111, 112, 113, 114, 115, 116, 120, 122, 123, 124, 125, 126, 127, 128, 129, 130, 172, 180, 181, 182, 187, 188, 189, 197, 199, 214, 235, 236, 243, 200, 23, 52, 97, 98, 99, 106, 198, 6, 3, 6, 6, 6, 6, 6, 3, 6, 188, 3, 3, 6, 3, 3, 182, 10, 197, 199, 6, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 41, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 59, 60, 64, 75, 81, 83, 86, 87, 88, 89, 97, 117, 118, 119, 120, 121, 122, 124, 125, 126, 127, 128, 135, 141, 150, 201, 202, 204, 205, 210, 211, 213, 219, 233, 234, 235, 237, 11, 11, 11, 190, 11, 11, 21, 203, 204, 219, 26, 64, 144, 191, 192, 229, 229, 95, 96, 158, 162, 163, 244, 245, 246, 247, 248, 249, 250, 251, 251, 251, 251, 183, 251, 176, 177, 243, 173, 136, 220, 61, 68, 69, 70, 103, 104, 105, 107, 137, 138, 139, 140, 141, 142, 143, 150, 193, 196, 221, 222, 223, 224, 225, 226, 227, 228, 41, 101, 102, 194, 195, 243, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 5, 201, 5, 201, 229, 207, 208, 251, 220, 11, 37, 38, 39, 40, 238, 42, 43, 240, 6, 11, 5, 6, 4, 5, 245, 245, 251, 155, 156, 157, 158, 159, 160, 161, 154, 153, 152, 184, 4, 9, 5, 17, 18, 19, 41, 50, 53, 97, 122, 124, 125, 126, 127, 128, 141, 150, 174, 175, 6, 6, 6, 4, 5, 193, 6, 6, 6, 4, 5, 194, 94, 131, 215, 94, 132, 216, 94, 133, 217, 134, 218, 117, 210, 219, 251, 145, 231, 146, 230, 147, 232, 148, 251, 251, 251, 251, 251, 251, 251, 151, 239, 251, 206, 212, 251, 209, 251, 243, 243, 90, 243, 251, 251, 251, 251, 243, 251, 251, 251, 220, 243, 243, 243, 243, 243, 243, 201, 201, 5, 193, 6, 6, 6, 9, 6, 6, 5, 219, 243, 203, 251, 191, 164, 245, 245, 245, 246, 246, 247, 247, 248, 249, 250, 4, 21, 62, 63, 71, 72, 73, 75, 76, 77, 78, 79, 120, 185, 186, 187, 197, 176, 75, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 5, 174, 251, 251, 251, 193, 251, 91, 251, 194, 9, 163, 207, 251, 251, 239, 238, 149, 241, 57, 58, 242, 240, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 185, 6, 215, 216, 217, 251, 178, 179, 251, 243, 220, 243, 243, 243, 243, 243, 243, 174, 206, 165, 251, 219, 251, 251, 251, 251, 251, 251, 90, 251, 185, 251, 9, 163, 164, 164, 178, 165, 251, 164, 164 }; #if YYDEBUG /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding to YYLEX-NUM. */ const unsigned short int BisonParser::yytoken_number_[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ const unsigned char BisonParser::yyr1_[] = { 0, 166, 167, 168, 168, 169, 170, 169, 171, 171, 171, 171, 171, 171, 171, 171, 173, 172, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 177, 177, 178, 178, 179, 179, 179, 180, 180, 180, 180, 180, 180, 180, 180, 181, 181, 183, 182, 184, 184, 184, 184, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 188, 188, 188, 189, 190, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 191, 191, 192, 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 198, 197, 197, 200, 199, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 203, 203, 204, 204, 204, 204, 204, 205, 205, 206, 206, 207, 207, 208, 209, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, 214, 214, 214, 214, 214, 215, 215, 216, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 237, 237, 237, 238, 238, 238, 238, 238, 239, 240, 240, 240, 241, 242, 242, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 250, 250, 251, 251 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ const unsigned char BisonParser::yyr2_[] = { 0, 2, 1, 0, 2, 3, 0, 6, 0, 2, 2, 2, 2, 2, 2, 2, 0, 5, 1, 3, 2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 5, 0, 1, 3, 1, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 0, 5, 0, 2, 2, 2, 1, 3, 2, 3, 3, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 2, 2, 4, 0, 5, 4, 4, 4, 3, 4, 4, 4, 4, 4, 1, 3, 1, 1, 3, 1, 3, 2, 1, 3, 2, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 1, 0, 5, 1, 0, 4, 1, 1, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 1, 3, 1, 1, 1, 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3 }; #if YYDEBUG /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at \a yyntokens_, nonterminals. */ const char* const BisonParser::yytname_[] = { "$end", "error", "$undefined", "OBRACE", "EBRACE", "COMMA", "EQUAL", "COLON", "QUOTE", "SEMICOLON", "OBRACKET", "EBRACKET", "BOOTLOADER", "XIP_MODE", "EARLY_HANDOFF", "HIVEC", "LOCKSTEP", "AUTHENTICATION", "ENCRYPTION", "CHECKSUM", "PARTITION_OWNER", "PARTITION_TYPE", "PARTITION_NUM", "BOOT_DEVICE", "DEST_DEVICE", "DEST_CPU", "ADDRESS", "EXCEPTION_LEVEL", "TRUSTZONE", "ALIGNMENT", "OFFSET", "RESERVE_LEGACY", "RESERVE", "LOAD", "STARTUP", "BIGENDIAN", "A32_MODE", "PPK_SELECT", "SPK_ID", "SPK_SELECT", "HEADER_AUTH", "REVOKE_ID", "SPLIT_MODE", "SPLIT_FMT", "BOOT", "USER", "STATIC", "NOAUTOSTART", "MULTIBOOT", "PROTECTED", "BLOCKS", "AUTHBLOCKS", "BOOTVECTORS", "PRESIGN", "AC", "BIF_SECTION", "UDF_DATA", "MCS", "BIN", "SLR_NUM", "CLUSTER_NUM", "DICE", "PCR_NUMBER", "PCR_MEASUREMENT_INDEX", "IMAGE_STORE", "PARENT_ID", "ID_CODE", "EXT_ID_CODE", "BYPASS_IDCODE_CHECK", "A_HWROT", "S_HWROT", "UNIQUE_ID", "PARENT_UNIQUE_ID", "FUNCTION_ID", "IMAGE", "ID", "NAME", "DELAY_HANDOFF", "DELAY_LOAD", "COPY", "INCLUDE", "DELAY_AUTH", "PARTITION", "PFILE", "OPTIONAL_DATA", "METAHEADER", "TCM_BOOT", "TCM_A_REGION", "TCM_B_REGION", "TCM_C_REGION", "WORD", "HEXWORD", "FILENAME", "QFILENAME", "NONE", "DECVALUE", "HEXVALUE", "KEYSRC_ENCRYPTION", "FSBL_CONFIG", "AUTH_PARAMS", "AUTHJTAG_CONFIG", "DEVICE_DNA", "JTAG_TIMEOUT", "PUF4KMODE", "PUFROSWAP", "SHUTTER", "SPLIT", "SMAP_WIDTH", "PUF_HELPER_FILE", "BH_KEY_FILE", "BH_KEY_IV", "BH_KEK_IV", "BBRAM_KEK_IV", "EFUSE_KEK_IV", "EFUSE_USER_KEK0_IV", "EFUSE_USER_KEK1_IV", "USER_KEYS", "PMCDATA", "BOOTIMAGE", "UDF_BH", "INIT", "PMUFW_IMAGE", "AES_KEY_FILE", "FAMILY_KEY", "PPK_FILE", "PSK_FILE", "SPK_FILE", "SSK_FILE", "SPK_SIGNATURE_FILE", "BH_SIGNATURE_FILE", "HEADER_SIGNATURE_FILE", "AUTHVALUE", "ENCRVALUE", "CHECKSUMVALUE", "POWNERVALUE", "PTYPEVALUE", "KEY_SRC", "CORE", "BH_RSA", "AUTH_HASH", "INT_HASH", "PUFHD_LOC", "OPT_KEY", "AUTH_ONLY", "BOOT_DEVICE_TYPE", "DEST_DEVICE_TYPE", "DEST_CPU_TYPE", "EXCEPTION_LEVEL_TYPE", "TRUSTZONE_TYPE", "SPLITMODE", "DPA_CM", "SPKSELECT", "OR", "XOR", "AND", "MULT", "DIVIDE", "MODULO", "PLUS", "MINUS", "LSHIFT", "RSHIFT", "NEGATION", "LPAREN", "RPAREN", "ASTERISK", "$accept", "bif", "group_list", "bifoptions", "$@1", "file_list", "metahdr_spec", "$@2", "metahdr_attr_list", "metahdr_attr", "optional_data", "optional_data_attr", "metahdr_blk", "metahdr_blk_attr", "new_pdi_spec", "image_spec", "image_list", "$@3", "image_content", "image_attributes_list", "image_attributes", "partition_spec", "partition_content", "other_spec", "$@4", "sec_boot_attr_list", "sec_boot_attr", "fsbl_attr_list", "authjtag_attr_list", "authjtag_attr", "fsbl_attr", "file_spec", "$@5", "new_file_spec", "$@6", "new_attribute_list", "new_attribute", "attribute_list", "attribute", "blocksattr_list", "blocksattr", "bootvectors_list", "bootvector", "authblockattr", "boolattr", "trustzone_type", "blockattr", "optattr", "other_file_attr", "authvalue", "encrvalue", "checkvalue", "pownervalue", "ptypevalue", "key_src", "core", "bh_rsa", "dpa_cm", "auth_hash", "int_hash", "pufhd_loc", "opt_key", "auth_only", "boot_device_type", "dest_cpu_type", "dest_device_type", "exception_level_type", "numattr", "fileattr", "key_file", "rsa_key_file", "other_files", "auth_parameters", "spkselect", "split_options", "splitmode", "splitfmt", "filename", "number", "unary_expression", "multiplicative_expression", "additive_expression", "shift_expression", "and_expression", "xor_expression", "expression", YY_NULL }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ const BisonParser::rhs_number_type BisonParser::yyrhs_[] = { 167, 0, -1, 168, -1, -1, 168, 169, -1, 80, 7, 243, -1, -1, 90, 170, 7, 3, 171, 4, -1, -1, 171, 197, -1, 171, 189, -1, 171, 181, -1, 171, 172, -1, 171, 180, -1, 171, 199, -1, 171, 187, -1, -1, 85, 3, 173, 174, 4, -1, 175, -1, 175, 5, 174, -1, 175, 174, -1, -1, 18, 6, 216, -1, 97, 6, 220, -1, 122, 6, 243, -1, 17, 6, 215, -1, 124, 6, 243, -1, 125, 6, 243, -1, 126, 6, 243, -1, 127, 6, 243, -1, 128, 6, 243, -1, 53, 6, 243, -1, 41, 6, 251, -1, 19, 6, 217, -1, 150, -1, 50, 6, 178, -1, 141, -1, 177, -1, 177, 9, 176, -1, 243, 5, 75, 6, 251, -1, -1, 179, -1, 179, 9, 178, -1, 251, -1, 251, 163, 251, 164, -1, 251, 163, 165, 164, -1, 75, 6, 251, -1, 65, 6, 251, -1, 66, 6, 251, -1, 67, 6, 251, -1, 214, 6, 243, -1, 97, 6, 220, -1, 21, 6, 219, -1, 41, 6, 251, -1, 182, -1, 181, 182, -1, -1, 74, 3, 183, 184, 4, -1, -1, 184, 185, -1, 184, 197, -1, 184, 187, -1, 186, -1, 186, 5, 185, -1, 186, 185, -1, 75, 6, 251, -1, 76, 6, 90, -1, 77, -1, 78, -1, 120, -1, 79, 6, 251, -1, 21, 6, 219, -1, 71, 6, 251, -1, 72, 6, 251, -1, 73, 6, 251, -1, 62, 6, 251, -1, 63, 6, 251, -1, 82, 188, -1, 188, -1, -1, 188, 197, -1, 188, 199, -1, 10, 97, 11, 220, -1, -1, 10, 98, 190, 11, 193, -1, 98, 3, 193, 4, -1, 23, 3, 191, 4, -1, 10, 23, 11, 229, -1, 23, 6, 229, -1, 10, 99, 11, 238, -1, 10, 106, 11, 240, -1, 10, 52, 11, 207, -1, 100, 3, 194, 4, -1, 84, 3, 176, 4, -1, 192, -1, 192, 5, 191, -1, 229, -1, 64, -1, 26, 6, 251, -1, 196, -1, 196, 5, 193, -1, 196, 193, -1, 195, -1, 195, 5, 194, -1, 195, 194, -1, 41, 6, 251, -1, 101, 6, 91, -1, 102, 6, 251, -1, 221, -1, 222, -1, 224, -1, 225, -1, 226, -1, 228, -1, 227, -1, 103, -1, 105, 6, 251, -1, 223, -1, 107, 6, 251, -1, 68, -1, 69, -1, 70, -1, 104, 6, 251, -1, 61, -1, -1, 10, 198, 203, 11, 243, -1, 243, -1, -1, 3, 200, 201, 4, -1, 204, -1, 202, -1, 202, 5, 201, -1, 204, 5, 201, -1, 202, 201, -1, 204, 201, -1, 83, 6, 243, -1, 75, 6, 251, -1, 64, 6, 251, -1, 21, 6, 210, -1, 21, 6, 117, -1, 55, 6, 90, -1, 204, -1, 204, 5, 203, -1, 210, -1, 213, -1, 233, -1, 234, -1, 205, -1, 50, 6, 206, -1, 51, 6, 209, -1, 212, -1, 212, 9, 206, -1, 208, -1, 208, 5, 207, -1, 251, -1, 251, -1, 12, -1, 44, -1, 45, -1, 46, -1, 47, -1, 48, -1, 49, -1, 14, -1, 15, -1, 13, -1, 120, -1, 118, -1, 235, -1, 237, -1, 219, -1, 16, -1, 28, -1, 28, 6, 148, -1, 251, -1, 251, 163, 251, 164, -1, 251, 163, 165, 164, -1, 17, 6, 215, -1, 18, 6, 216, -1, 19, 6, 217, -1, 20, 6, 218, -1, 25, 6, 230, -1, 24, 6, 231, -1, 27, 6, 232, -1, 122, 6, 243, -1, 124, 6, 243, -1, 125, 6, 243, -1, 126, 6, 243, -1, 127, 6, 243, -1, 39, 6, 239, -1, 38, 6, 251, -1, 128, 6, 243, -1, 211, -1, 21, 6, 219, -1, 97, 6, 220, -1, 41, 6, 251, -1, 150, -1, 59, 6, 251, -1, 60, 6, 251, -1, 141, -1, 81, -1, 86, -1, 120, -1, 235, -1, 111, -1, 112, -1, 113, -1, 114, -1, 115, -1, 116, -1, 94, -1, 131, -1, 94, -1, 132, -1, 94, -1, 133, -1, 134, -1, 135, -1, 136, -1, 137, -1, 138, -1, 150, -1, 139, -1, 140, -1, 141, -1, 142, -1, 143, -1, 144, -1, 146, -1, 145, -1, 147, -1, 29, 6, 251, -1, 30, 6, 251, -1, 31, 6, 251, -1, 32, 6, 251, -1, 33, 6, 251, -1, 34, 6, 251, -1, 35, -1, 36, -1, 22, 6, 251, -1, 87, 6, 251, -1, 88, 6, 251, -1, 89, 6, 251, -1, 53, 6, 243, -1, 54, 6, 243, -1, 56, 6, 243, -1, 122, -1, 236, -1, 128, -1, 129, -1, 130, -1, 109, -1, 108, -1, 110, -1, 123, -1, 124, -1, 125, -1, 126, -1, 127, -1, 121, -1, 117, -1, 119, -1, 37, 6, 251, -1, 39, 6, 239, -1, 38, 6, 251, -1, 40, -1, 238, 9, 238, -1, 151, -1, 42, 6, 241, -1, 43, 6, 242, -1, 240, 5, 240, -1, 149, -1, 57, -1, 58, -1, 92, -1, 93, -1, 96, -1, 95, -1, 163, 251, 164, -1, 244, -1, 158, 245, -1, 162, 245, -1, 245, -1, 246, 155, 245, -1, 246, 156, 245, -1, 246, 157, 245, -1, 246, -1, 247, 158, 246, -1, 247, 159, 246, -1, 247, -1, 248, 160, 247, -1, 248, 161, 247, -1, 248, -1, 249, 154, 248, -1, 249, -1, 250, 153, 249, -1, 250, -1, 251, 152, 250, -1 }; /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ const unsigned short int BisonParser::yyprhs_[] = { 0, 0, 3, 5, 6, 9, 13, 14, 21, 22, 25, 28, 31, 34, 37, 40, 43, 44, 50, 52, 56, 59, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 110, 114, 116, 118, 122, 128, 129, 131, 135, 137, 142, 147, 151, 155, 159, 163, 167, 171, 175, 179, 181, 184, 185, 191, 192, 195, 198, 201, 203, 207, 210, 214, 218, 220, 222, 224, 228, 232, 236, 240, 244, 248, 252, 255, 257, 258, 261, 264, 269, 270, 276, 281, 286, 291, 295, 300, 305, 310, 315, 320, 322, 326, 328, 330, 334, 336, 340, 343, 345, 349, 352, 356, 360, 364, 366, 368, 370, 372, 374, 376, 378, 380, 384, 386, 390, 392, 394, 396, 400, 402, 403, 409, 411, 412, 417, 419, 421, 425, 429, 432, 435, 439, 443, 447, 451, 455, 459, 461, 465, 467, 469, 471, 473, 475, 479, 483, 485, 489, 491, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 537, 539, 544, 549, 553, 557, 561, 565, 569, 573, 577, 581, 585, 589, 593, 597, 601, 605, 609, 611, 615, 619, 623, 625, 629, 633, 635, 637, 639, 641, 643, 645, 647, 649, 651, 653, 655, 657, 659, 661, 663, 665, 667, 669, 671, 673, 675, 677, 679, 681, 683, 685, 687, 689, 691, 693, 695, 697, 701, 705, 709, 713, 717, 721, 723, 725, 729, 733, 737, 741, 745, 749, 753, 755, 757, 759, 761, 763, 765, 767, 769, 771, 773, 775, 777, 779, 781, 783, 785, 789, 793, 797, 799, 803, 805, 809, 813, 817, 819, 821, 823, 825, 827, 829, 831, 835, 837, 840, 843, 845, 849, 853, 857, 859, 863, 867, 869, 873, 877, 879, 883, 885, 889, 891 }; /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ const unsigned short int BisonParser::yyrline_[] = { 0, 198, 198, 200, 201, 204, 205, 205, 211, 212, 213, 214, 215, 216, 217, 218, 221, 221, 226, 227, 228, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 250, 251, 254, 255, 257, 258, 261, 263, 265, 269, 270, 271, 272, 273, 274, 275, 276, 279, 280, 283, 283, 287, 288, 289, 290, 293, 294, 295, 298, 299, 300, 301, 302, 303, 305, 306, 307, 308, 309, 312, 317, 318, 321, 322, 323, 326, 329, 329, 332, 333, 334, 339, 340, 341, 342, 343, 344, 347, 348, 351, 352, 353, 356, 357, 358, 361, 362, 363, 366, 367, 368, 371, 374, 380, 382, 384, 386, 388, 390, 392, 394, 400, 404, 405, 406, 407, 412, 419, 419, 426, 432, 432, 438, 439, 440, 441, 442, 443, 446, 449, 450, 452, 453, 454, 459, 460, 463, 464, 465, 466, 467, 470, 471, 474, 475, 478, 479, 482, 487, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 501, 502, 503, 504, 505, 506, 509, 510, 513, 514, 515, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 544, 545, 546, 547, 548, 549, 550, 551, 554, 555, 558, 559, 562, 563, 566, 569, 572, 575, 578, 581, 584, 587, 590, 593, 596, 599, 602, 605, 608, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 625, 626, 627, 630, 631, 632, 633, 634, 635, 636, 637, 638, 641, 642, 643, 644, 647, 648, 649, 652, 655, 658, 661, 664, 667, 670, 673, 674, 677, 680, 683, 689, 690, 693, 694, 695, 701, 702, 703, 707, 708, 709, 710, 713, 714, 715, 718, 719, 720, 723, 724, 727, 728, 732, 733 }; // Print the state stack on the debug stream. void BisonParser::yystack_print_ () { *yycdebug_ << "Stack now"; for (state_stack_type::const_iterator i = yystate_stack_.begin (); i != yystate_stack_.end (); ++i) *yycdebug_ << ' ' << *i; *yycdebug_ << std::endl; } // Report on the debug stream that the rule \a yyrule is going to be reduced. void BisonParser::yy_reduce_print_ (int yyrule) { unsigned int yylno = yyrline_[yyrule]; int yynrhs = yyr2_[yyrule]; /* Print the symbols being reduced, and their result. */ *yycdebug_ << "Reducing stack by rule " << yyrule - 1 << " (line " << yylno << "):" << std::endl; /* The symbols being reduced. */ for (int yyi = 0; yyi < yynrhs; yyi++) YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", yyrhs_[yyprhs_[yyrule] + yyi], &(yysemantic_stack_[(yynrhs) - (yyi + 1)]), &(yylocation_stack_[(yynrhs) - (yyi + 1)])); } #endif // YYDEBUG /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ BisonParser::token_number_type BisonParser::yytranslate_ (int t) { static const token_number_type translate_table[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165 }; if ((unsigned int) t <= yyuser_token_number_max_) return translate_table[t]; else return yyundef_token_; } const int BisonParser::yyeof_ = 0; const int BisonParser::yylast_ = 1035; const int BisonParser::yynnts_ = 86; const int BisonParser::yyempty_ = -2; const int BisonParser::yyfinal_ = 3; const int BisonParser::yyterror_ = 1; const int BisonParser::yyerrcode_ = 256; const int BisonParser::yyntokens_ = 166; const unsigned int BisonParser::yyuser_token_number_max_ = 420; const BisonParser::token_number_type BisonParser::yyundef_token_ = 2; /* Line 1141 of lalr1.cc */ #line 24 "../s/bif.y" } // BIF /* Line 1141 of lalr1.cc */ #line 2589 "../bisonflex/bif.tab.cpp" /* Line 1142 of lalr1.cc */ #line 738 "../s/bif.y" void BIF::BisonParser::error(const BIF::BisonParser::location_type &loc, const std::string &msg) { Parsing::Error(loc,msg); } static int yylex(BIF::BisonParser::semantic_type * yylval, BIF::BisonParser::location_type* loc, BIF::FlexScanner &scanner) { return scanner.yylex(yylval,loc); } xilinx-bootgen-2024.2/bif.tab.hpp000077500000000000000000000320531475706442400166120ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton interface for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file ../bisonflex/bif.tab.hpp ** Define the BIF::parser class. */ /* C++ LALR(1) parser skeleton written by Akim Demaille. */ #ifndef YY_YY_BISONFLEX_BIF_TAB_HPP_INCLUDED # define YY_YY_BISONFLEX_BIF_TAB_HPP_INCLUDED /* "%code requires" blocks. */ /* Line 33 of lalr1.cc */ #line 37 "../s/bif.y" namespace BIF { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "bifoptions.h" /* Line 33 of lalr1.cc */ #line 58 "../bisonflex/bif.tab.hpp" #include #include #include "stack.hh" #include "location.hh" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Line 33 of lalr1.cc */ #line 24 "../s/bif.y" namespace BIF { /* Line 33 of lalr1.cc */ #line 75 "../bisonflex/bif.tab.hpp" /// A Bison parser. class BisonParser { public: /// Symbol semantic values. #ifndef YYSTYPE union semantic_type { /* Line 33 of lalr1.cc */ #line 73 "../s/bif.y" uint32_t token; uint64_t number; char *string; Authentication::Type authvalue_t; Encryption::Type encrvalue_t; KeySource::Type encrkeysrc_t; Core::Type core_t; BhRsa::Type bhrsa_t; AuthHash::Type authhash_t; PufHdLoc::Type pufhdloc_t; OptKey::Type optkey_t; AuthOnly::Type authonly_t; BootDevice::Type bootdevice_t; DestinationDevice::Type destdevice_t; DestinationCPU::Type destcpu_t; Checksum::Type checksumvalue_t; PartitionOwner::Type powner_t; PartitionType::Type ptype_t; ExceptionLevel::Type el_t; SplitMode::Type splitmode_t; TrustZone::Type trustzone_t; BifOptions* bifoptions; PartitionBifOptions* partitionBifOptions; DpaCM::Type dpacm_t; SpkSelect::Type spkselect_t; /* Line 33 of lalr1.cc */ #line 116 "../bisonflex/bif.tab.hpp" }; #else typedef YYSTYPE semantic_type; #endif /// Symbol locations. typedef location location_type; /// Tokens. struct token { /* Tokens. */ enum yytokentype { OBRACE = 258, EBRACE = 259, COMMA = 260, EQUAL = 261, COLON = 262, QUOTE = 263, SEMICOLON = 264, OBRACKET = 265, EBRACKET = 266, BOOTLOADER = 267, XIP_MODE = 268, EARLY_HANDOFF = 269, HIVEC = 270, LOCKSTEP = 271, AUTHENTICATION = 272, ENCRYPTION = 273, CHECKSUM = 274, PARTITION_OWNER = 275, PARTITION_TYPE = 276, PARTITION_NUM = 277, BOOT_DEVICE = 278, DEST_DEVICE = 279, DEST_CPU = 280, ADDRESS = 281, EXCEPTION_LEVEL = 282, TRUSTZONE = 283, ALIGNMENT = 284, OFFSET = 285, RESERVE_LEGACY = 286, RESERVE = 287, LOAD = 288, STARTUP = 289, BIGENDIAN = 290, A32_MODE = 291, PPK_SELECT = 292, SPK_ID = 293, SPK_SELECT = 294, HEADER_AUTH = 295, REVOKE_ID = 296, SPLIT_MODE = 297, SPLIT_FMT = 298, BOOT = 299, USER = 300, STATIC = 301, NOAUTOSTART = 302, MULTIBOOT = 303, PROTECTED = 304, BLOCKS = 305, AUTHBLOCKS = 306, BOOTVECTORS = 307, PRESIGN = 308, AC = 309, BIF_SECTION = 310, UDF_DATA = 311, MCS = 312, BIN = 313, SLR_NUM = 314, CLUSTER_NUM = 315, DICE = 316, PCR_NUMBER = 317, PCR_MEASUREMENT_INDEX = 318, IMAGE_STORE = 319, PARENT_ID = 320, ID_CODE = 321, EXT_ID_CODE = 322, BYPASS_IDCODE_CHECK = 323, A_HWROT = 324, S_HWROT = 325, UNIQUE_ID = 326, PARENT_UNIQUE_ID = 327, FUNCTION_ID = 328, IMAGE = 329, ID = 330, NAME = 331, DELAY_HANDOFF = 332, DELAY_LOAD = 333, COPY = 334, INCLUDE = 335, DELAY_AUTH = 336, PARTITION = 337, PFILE = 338, OPTIONAL_DATA = 339, METAHEADER = 340, TCM_BOOT = 341, TCM_A_REGION = 342, TCM_B_REGION = 343, TCM_C_REGION = 344, WORD = 345, HEXWORD = 346, FILENAME = 347, QFILENAME = 348, NONE = 349, DECVALUE = 350, HEXVALUE = 351, KEYSRC_ENCRYPTION = 352, FSBL_CONFIG = 353, AUTH_PARAMS = 354, AUTHJTAG_CONFIG = 355, DEVICE_DNA = 356, JTAG_TIMEOUT = 357, PUF4KMODE = 358, PUFROSWAP = 359, SHUTTER = 360, SPLIT = 361, SMAP_WIDTH = 362, PUF_HELPER_FILE = 363, BH_KEY_FILE = 364, BH_KEY_IV = 365, BH_KEK_IV = 366, BBRAM_KEK_IV = 367, EFUSE_KEK_IV = 368, EFUSE_USER_KEK0_IV = 369, EFUSE_USER_KEK1_IV = 370, USER_KEYS = 371, PMCDATA = 372, BOOTIMAGE = 373, UDF_BH = 374, INIT = 375, PMUFW_IMAGE = 376, AES_KEY_FILE = 377, FAMILY_KEY = 378, PPK_FILE = 379, PSK_FILE = 380, SPK_FILE = 381, SSK_FILE = 382, SPK_SIGNATURE_FILE = 383, BH_SIGNATURE_FILE = 384, HEADER_SIGNATURE_FILE = 385, AUTHVALUE = 386, ENCRVALUE = 387, CHECKSUMVALUE = 388, POWNERVALUE = 389, PTYPEVALUE = 390, KEY_SRC = 391, CORE = 392, BH_RSA = 393, AUTH_HASH = 394, INT_HASH = 395, PUFHD_LOC = 396, OPT_KEY = 397, AUTH_ONLY = 398, BOOT_DEVICE_TYPE = 399, DEST_DEVICE_TYPE = 400, DEST_CPU_TYPE = 401, EXCEPTION_LEVEL_TYPE = 402, TRUSTZONE_TYPE = 403, SPLITMODE = 404, DPA_CM = 405, SPKSELECT = 406, OR = 407, XOR = 408, AND = 409, MULT = 410, DIVIDE = 411, MODULO = 412, PLUS = 413, MINUS = 414, LSHIFT = 415, RSHIFT = 416, NEGATION = 417, LPAREN = 418, RPAREN = 419, ASTERISK = 420 }; }; /// Token type. typedef token::yytokentype token_type; /// Build a parser object. BisonParser (BIF::FlexScanner& scanner_yyarg, Options& options_yyarg); virtual ~BisonParser (); /// Parse. /// \returns 0 iff parsing succeeded. virtual int parse (); #if YYDEBUG /// The current debugging stream. std::ostream& debug_stream () const; /// Set the current debugging stream. void set_debug_stream (std::ostream &); /// Type for debugging levels. typedef int debug_level_type; /// The current debugging level. debug_level_type debug_level () const; /// Set the current debugging level. void set_debug_level (debug_level_type l); #endif private: /// Report a syntax error. /// \param loc where the syntax error is found. /// \param msg a description of the syntax error. virtual void error (const location_type& loc, const std::string& msg); /// Generate an error message. /// \param state the state where the error occurred. /// \param tok the lookahead token. virtual std::string yysyntax_error_ (int yystate, int tok); #if YYDEBUG /// \brief Report a symbol value on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); /// \brief Report a symbol on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); #endif /// State numbers. typedef int state_type; /// State stack type. typedef stack state_stack_type; /// Semantic value stack type. typedef stack semantic_stack_type; /// location stack type. typedef stack location_stack_type; /// The state stack. state_stack_type yystate_stack_; /// The semantic value stack. semantic_stack_type yysemantic_stack_; /// The location stack. location_stack_type yylocation_stack_; /// Whether the given \c yypact_ value indicates a defaulted state. /// \param yyvalue the value to check static bool yy_pact_value_is_default_ (int yyvalue); /// Whether the given \c yytable_ value indicates a syntax error. /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); /// Internal symbol numbers. typedef unsigned char token_number_type; /* Tables. */ /// For a state, the index in \a yytable_ of its portion. static const short int yypact_[]; static const short int yypact_ninf_; /// For a state, default reduction number. /// Unless\a yytable_ specifies something else to do. /// Zero means the default is an error. static const unsigned short int yydefact_[]; static const short int yypgoto_[]; static const short int yydefgoto_[]; /// What to do in a state. /// \a yytable_[yypact_[s]]: what to do in state \a s. /// - if positive, shift that token. /// - if negative, reduce the rule which number is the opposite. /// - if zero, do what YYDEFACT says. static const unsigned short int yytable_[]; static const signed char yytable_ninf_; static const short int yycheck_[]; /// For a state, its accessing symbol. static const unsigned char yystos_[]; /// For a rule, its LHS. static const unsigned char yyr1_[]; /// For a rule, its RHS length. static const unsigned char yyr2_[]; #if YYDEBUG /// For a symbol, its name in clear. static const char* const yytname_[]; /// A type to store symbol numbers and -1. typedef short int rhs_number_type; /// A `-1'-separated list of the rules' RHS. static const rhs_number_type yyrhs_[]; /// For each rule, the index of the first RHS symbol in \a yyrhs_. static const unsigned short int yyprhs_[]; /// For each rule, its source line number. static const unsigned short int yyrline_[]; /// For each scanner token number, its symbol number. static const unsigned short int yytoken_number_[]; /// Report on the debug stream that the rule \a r is going to be reduced. virtual void yy_reduce_print_ (int r); /// Print the state stack on the debug stream. virtual void yystack_print_ (); /* Debugging. */ int yydebug_; std::ostream* yycdebug_; #endif /// Convert a scanner token number \a t to a symbol number. token_number_type yytranslate_ (int t); /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// If null, do not display the symbol, just free it. /// \param yytype The symbol type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. inline void yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp); /// Pop \a n symbols the three stacks. inline void yypop_ (unsigned int n = 1); /* Constants. */ static const int yyeof_; /* LAST_ -- Last index in TABLE_. */ static const int yylast_; static const int yynnts_; static const int yyempty_; static const int yyfinal_; static const int yyterror_; static const int yyerrcode_; static const int yyntokens_; static const unsigned int yyuser_token_number_max_; static const token_number_type yyundef_token_; /* User arguments. */ BIF::FlexScanner& scanner; Options& options; }; /* Line 33 of lalr1.cc */ #line 24 "../s/bif.y" } // BIF /* Line 33 of lalr1.cc */ #line 467 "../bisonflex/bif.tab.hpp" #endif /* !YY_YY_BISONFLEX_BIF_TAB_HPP_INCLUDED */ xilinx-bootgen-2024.2/bif.y000077500000000000000000001375151475706442400155370ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* BIF (Boot Image Format) * Use bison to process this file into bif.tab.cpp */ %require "2.7" %skeleton "lalr1.cc" %defines %define namespace "BIF" %define parser_class_name "BisonParser" %parse-param { BIF::FlexScanner& scanner } %parse-param { Options& options} %lex-param { BIF::FlexScanner& scanner } %locations %initial-action { // Initialize the initial location. @$.begin.filename = @$.end.filename = &scanner.filename; }; %code requires { namespace BIF { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "bifoptions.h" } %code { static int yylex(BIF::BisonParser::semantic_type * yylval, BIF::BisonParser::location_type* loc, BIF::FlexScanner &scanner); #include "options.h" } %{ #include #include "bootimage.h" #include "authentication.h" #include "encryption.h" #include "checksum.h" #include "bifscanner.h" #include "parsing.h" #include "imageheadertable-versal.h" BifOptions* currentBifOptions; PartitionBifOptions* currentPartitionBifOptions ; ImageBifOptions* currentImageBifOptions; %} %start bif %union { uint32_t token; uint64_t number; char *string; Authentication::Type authvalue_t; Encryption::Type encrvalue_t; KeySource::Type encrkeysrc_t; Core::Type core_t; BhRsa::Type bhrsa_t; AuthHash::Type authhash_t; PufHdLoc::Type pufhdloc_t; OptKey::Type optkey_t; AuthOnly::Type authonly_t; BootDevice::Type bootdevice_t; DestinationDevice::Type destdevice_t; DestinationCPU::Type destcpu_t; Checksum::Type checksumvalue_t; PartitionOwner::Type powner_t; PartitionType::Type ptype_t; ExceptionLevel::Type el_t; SplitMode::Type splitmode_t; TrustZone::Type trustzone_t; BifOptions* bifoptions; PartitionBifOptions* partitionBifOptions; DpaCM::Type dpacm_t; SpkSelect::Type spkselect_t; } %token OBRACE EBRACE %token COMMA EQUAL COLON QUOTE SEMICOLON %token OBRACKET EBRACKET %token BOOTLOADER XIP_MODE EARLY_HANDOFF HIVEC LOCKSTEP %token AUTHENTICATION ENCRYPTION CHECKSUM %token PARTITION_OWNER PARTITION_TYPE PARTITION_NUM %token BOOT_DEVICE DEST_DEVICE DEST_CPU ADDRESS %token EXCEPTION_LEVEL TRUSTZONE %token ALIGNMENT OFFSET RESERVE_LEGACY RESERVE LOAD STARTUP BIGENDIAN A32_MODE %token PPK_SELECT SPK_ID SPK_SELECT HEADER_AUTH REVOKE_ID %token SPLIT_MODE SPLIT_FMT %token BOOT USER STATIC NOAUTOSTART MULTIBOOT PROTECTED %token BLOCKS AUTHBLOCKS BOOTVECTORS %token PRESIGN AC BIF_SECTION %token UDF_DATA %token MCS BIN %token SLR_NUM CLUSTER_NUM DICE PCR_NUMBER PCR_MEASUREMENT_INDEX IMAGE_STORE %token PARENT_ID ID_CODE EXT_ID_CODE BYPASS_IDCODE_CHECK A_HWROT S_HWROT UNIQUE_ID PARENT_UNIQUE_ID FUNCTION_ID %token IMAGE ID NAME DELAY_HANDOFF DELAY_LOAD COPY INCLUDE DELAY_AUTH %token PARTITION PFILE OPTIONAL_DATA %token METAHEADER %token TCM_BOOT TCM_A_REGION TCM_B_REGION TCM_C_REGION %token WORD HEXWORD %token FILENAME QFILENAME %token NONE %token DECVALUE HEXVALUE %token KEYSRC_ENCRYPTION FSBL_CONFIG AUTH_PARAMS %token AUTHJTAG_CONFIG DEVICE_DNA JTAG_TIMEOUT %token PUF4KMODE PUFROSWAP SHUTTER SPLIT SMAP_WIDTH %token PUF_HELPER_FILE BH_KEY_FILE BH_KEY_IV %token BH_KEK_IV BBRAM_KEK_IV EFUSE_KEK_IV EFUSE_USER_KEK0_IV EFUSE_USER_KEK1_IV USER_KEYS %token PMCDATA BOOTIMAGE UDF_BH INIT PMUFW_IMAGE %token AES_KEY_FILE FAMILY_KEY %token PPK_FILE PSK_FILE SPK_FILE SSK_FILE %token SPK_SIGNATURE_FILE BH_SIGNATURE_FILE HEADER_SIGNATURE_FILE %token AUTHVALUE %token ENCRVALUE %token CHECKSUMVALUE %token POWNERVALUE %token PTYPEVALUE %token KEY_SRC %token CORE %token BH_RSA %token AUTH_HASH %token INT_HASH %token PUFHD_LOC %token OPT_KEY %token AUTH_ONLY %token BOOT_DEVICE_TYPE %token DEST_DEVICE_TYPE %token DEST_CPU_TYPE %token EXCEPTION_LEVEL_TYPE %token TRUSTZONE_TYPE %token SPLITMODE %token DPA_CM %token SPKSELECT %token OR XOR AND MULT DIVIDE MODULO PLUS MINUS LSHIFT RSHIFT %left OR XOR AND MULT DIVIDE MODULO PLUS MINUS LSHIFT RSHIFT %token NEGATION %right NEGATION %token LPAREN RPAREN ASTERISK %right LPAREN %left RPAREN %left EQUAL %type filename %type number key_file rsa_key_file other_spec other_files other_file_attr %type authvalue %type encrvalue %type checkvalue %type pownervalue %type ptypevalue %type key_src %type core %type bh_rsa %type auth_hash %type int_hash %type pufhd_loc %type opt_key %type auth_only %type boot_device_type %type dest_device_type %type dest_cpu_type %type exception_level_type %type splitmode %type spkselect %type expression multiplicative_expression unary_expression additive_expression shift_expression %type and_expression xor_expression %type bifoptions %type dpa_cm %% bif : group_list; group_list : /* empty */ | group_list bifoptions ; bifoptions : INCLUDE COLON filename { options.includeBifOptionsList.push_back($3); } | WORD { currentBifOptions = new BifOptions(options.GetArchType(),$1); } COLON OBRACE file_list EBRACE { options.bifOptions = currentBifOptions; options.bifOptionsList.push_back(currentBifOptions); } ; file_list : /* empty */ | file_list file_spec | file_list other_spec | file_list image_spec | file_list metahdr_spec | file_list new_pdi_spec | file_list new_file_spec | file_list partition_spec ; metahdr_spec : METAHEADER OBRACE { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); } metahdr_attr_list EBRACE ; metahdr_attr_list : metahdr_attr | metahdr_attr COMMA metahdr_attr_list | metahdr_attr metahdr_attr_list ; metahdr_attr : /* empty */ | ENCRYPTION EQUAL encrvalue { currentBifOptions->SetMetaHeaderEncryptType($3); } | KEYSRC_ENCRYPTION EQUAL key_src { currentBifOptions->SetMetaHeaderEncryptionKeySource($3, options.IsVersalNetSeries()); } | AES_KEY_FILE EQUAL filename { currentBifOptions->SetMetaHeaderEncryptionKeyFile($3); } | AUTHENTICATION EQUAL authvalue { currentBifOptions->SetMetaHeaderAuthType($3); } | PPK_FILE EQUAL filename { currentBifOptions->metaHdrAttributes.ppk = $3; } | PSK_FILE EQUAL filename { currentBifOptions->metaHdrAttributes.psk = $3; } | SPK_FILE EQUAL filename { currentBifOptions->metaHdrAttributes.spk = $3; } | SSK_FILE EQUAL filename { currentBifOptions->metaHdrAttributes.ssk = $3; } | SPK_SIGNATURE_FILE EQUAL filename { currentBifOptions->metaHdrAttributes.spkSignature = $3; } | PRESIGN EQUAL filename { currentBifOptions->metaHdrAttributes.presign = $3; } | REVOKE_ID EQUAL expression { currentBifOptions->metaHdrAttributes.revokeId = $3; } | CHECKSUM EQUAL checkvalue { currentBifOptions->metaHdrAttributes.checksum = $3; } | DPA_CM { currentBifOptions->metaHdrAttributes.dpaCM = DpaCM::DpaCMEnable; } | BLOCKS EQUAL metahdr_blk | PUFHD_LOC { currentBifOptions->metaHdrAttributes.pufHdLoc = PufHdLoc::PUFinBH; currentBifOptions->SetPufHdinBHFlag();} ; optional_data : optional_data_attr | optional_data_attr SEMICOLON optional_data ; optional_data_attr : filename COMMA ID EQUAL expression { currentBifOptions->metaHdrAttributes.ihtOptionalDataInfo.push_back(std::pair($1, $5)); } | metahdr_blk : metahdr_blk_attr | metahdr_blk_attr SEMICOLON metahdr_blk ; metahdr_blk_attr : expression { currentPartitionBifOptions->SetEncryptionBlocks($1); currentBifOptions->metaHdrAttributes.encrBlocks = currentPartitionBifOptions->GetEncryptionBlocks(); } | expression LPAREN expression RPAREN { currentPartitionBifOptions->SetEncryptionBlocks($1, $3); currentBifOptions->metaHdrAttributes.encrBlocks = currentPartitionBifOptions->GetEncryptionBlocks(); } | expression LPAREN ASTERISK RPAREN { currentPartitionBifOptions->SetEncryptionBlocks($1, 0); currentBifOptions->metaHdrAttributes.defEncrBlockSize = $1; } ; new_pdi_spec : ID EQUAL expression { currentBifOptions->SetPdiId($3); } | PARENT_ID EQUAL expression { currentBifOptions->SetParentId($3); } | ID_CODE EQUAL expression { currentBifOptions->SetIdCode($3); } | EXT_ID_CODE EQUAL expression { currentBifOptions->SetExtendedIdCode($3); } | other_file_attr EQUAL filename { currentBifOptions->AddFiles($1, $3); } | KEYSRC_ENCRYPTION EQUAL key_src { currentBifOptions->SetEncryptionKeySource($3); } | PARTITION_TYPE EQUAL ptypevalue { currentBifOptions->SetPdiType($3); } | REVOKE_ID EQUAL expression { currentBifOptions->SetRevokeId($3);} ; image_spec : image_list | image_spec image_list ; image_list : IMAGE OBRACE { currentImageBifOptions = new ImageBifOptions(); } image_content EBRACE { currentBifOptions->imageBifOptionList.push_back(currentImageBifOptions); } ; image_content : /* empty */ | image_content image_attributes_list | image_content file_spec | image_content partition_spec ; image_attributes_list : image_attributes | image_attributes COMMA image_attributes_list | image_attributes image_attributes_list ; image_attributes : ID EQUAL expression { currentImageBifOptions->SetImageId($3); } | NAME EQUAL WORD { currentImageBifOptions->SetImageName($3); } | DELAY_HANDOFF { currentImageBifOptions->SetDelayHandoff(true); } | DELAY_LOAD { currentImageBifOptions->SetDelayLoad(true); } | INIT { LOG_ERROR("BIF attribute error !!!\n\t This usage of 'init' is not supported. See 'bootgen -bif_help init' for usage details."); } | COPY EQUAL expression { LOG_ERROR("Copy to Memory feature with the attribute 'copy' is no more supported.\n\t This can be duplicated with the option 'imagestore'. Please refer UG1283 for more details."); currentImageBifOptions->SetMemCopyAddress($3); } | PARTITION_TYPE EQUAL ptypevalue { currentImageBifOptions->SetImageType($3); } | UNIQUE_ID EQUAL expression { currentImageBifOptions->SetUniqueId($3); } | PARENT_UNIQUE_ID EQUAL expression { currentImageBifOptions->SetParentUniqueId($3); } | FUNCTION_ID EQUAL expression { currentImageBifOptions->SetFunctionId($3); } | PCR_NUMBER EQUAL expression { if(!options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!!\n\t 'pcr' is supported only for VERSAL NET architecture"); currentImageBifOptions->SetPcrNumber($3); } | PCR_MEASUREMENT_INDEX EQUAL expression { if(!options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!!\n\t 'pcr_mid' is supported only for VERSAL NET architecture"); currentImageBifOptions->SetPcrMeasurementIndex($3); } ; partition_spec : PARTITION partition_content | partition_content ; partition_content : /* empty */ | partition_content file_spec | partition_content new_file_spec ; other_spec : OBRACKET KEYSRC_ENCRYPTION EBRACKET key_src { if(options.GetArchType() == Arch::VERSAL) LOG_WARNING("BIF attribute error !!! [keysrc_encryption] not supported in VERSAL architecture.\n\t Please see 'bootgen -arch versal -bif_help keysrc'"); currentBifOptions->SetEncryptionKeySource($4); options.SetEncryptedKeySource($4); } | OBRACKET FSBL_CONFIG { if(options.GetArchType() == Arch::ZYNQ) LOG_ERROR("BIF attribute error !!!\n\t\t[fsbl_config] not supported in ZYNQ architecture"); } EBRACKET fsbl_attr_list | FSBL_CONFIG OBRACE fsbl_attr_list EBRACE | BOOT_DEVICE OBRACE sec_boot_attr_list EBRACE | OBRACKET BOOT_DEVICE EBRACKET boot_device_type { if(options.GetArchType() == Arch::ZYNQ) LOG_ERROR("BIF attribute error !!!\n\t\t[bootdevice] not supported in ZYNQ architecture"); if(options.GetArchType() == Arch::VERSAL) LOG_ERROR("This usage of boot_device is no more supported.\n\t Please see 'bootgen -arch versal -bif_help boot_device'"); currentBifOptions->SetBootDevice($4); } | BOOT_DEVICE EQUAL boot_device_type { LOG_ERROR("This usage of boot_device is no more supported.\n\t Please see 'bootgen -arch versal -bif_help boot_device'"); } | OBRACKET AUTH_PARAMS EBRACKET auth_parameters | OBRACKET SPLIT EBRACKET split_options | OBRACKET BOOTVECTORS EBRACKET bootvectors_list | AUTHJTAG_CONFIG OBRACE authjtag_attr_list EBRACE | OPTIONAL_DATA OBRACE optional_data EBRACE ; sec_boot_attr_list : sec_boot_attr | sec_boot_attr COMMA sec_boot_attr_list ; sec_boot_attr : boot_device_type { currentBifOptions->SetBootDevice($1); } | IMAGE_STORE { currentBifOptions->SetBootDevice(BootDevice::IMAGESTORE); } | ADDRESS EQUAL expression { currentBifOptions->SetBootDeviceAddress($3); } ; fsbl_attr_list : fsbl_attr | fsbl_attr COMMA fsbl_attr_list | fsbl_attr fsbl_attr_list ; authjtag_attr_list : authjtag_attr | authjtag_attr COMMA authjtag_attr_list | authjtag_attr authjtag_attr_list ; authjtag_attr : REVOKE_ID EQUAL expression { currentBifOptions->SetAuthJtagRevokeID($3); } | DEVICE_DNA EQUAL HEXWORD { currentBifOptions->SetAuthJtagDeviceDna($3); } | JTAG_TIMEOUT EQUAL expression { currentBifOptions->SetAuthJtagTimeOut($3); } ; fsbl_attr : core { currentBifOptions->SetCore($1); LOG_WARNING("[fsbl_config] a53_x64 | a53_x32 | r5_single | r5_dual is no more supported. Use 'destination_cpu' attribute for bootloader partition"); } | bh_rsa { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) LOG_ERROR("BIF attribute error !!! 'bh_auth_enable' is not supported with '-arch versalnet'.\n\t Bootheader or eFuse authentication will be chosen based on eFuse bits."); else currentBifOptions->SetBhRsa($1); } | auth_hash { LOG_ERROR("Authentication using SHA2 is no more supported."); } | int_hash { LOG_ERROR("[fsbl_config] bi_integrity_sha3 is no more supported. Use 'checksum' attribute of bootloader partition"); } | pufhd_loc { currentBifOptions->SetPufHdLoc($1); } | auth_only { currentBifOptions->SetAuthOnly($1); } | opt_key { currentBifOptions->SetOptKey($1); } | PUF4KMODE { currentBifOptions->SetPufMode(PufMode::PUF4K); } | SHUTTER EQUAL expression { currentBifOptions->SetShutterValue($3); } | dpa_cm { if(options.GetArchType() != Arch::VERSAL) LOG_ERROR("BIF attribute error !!!\n\t\t'dpacm_enable' is supported only in VERSAL architecture"); if(options.GetArchType() == Arch::VERSAL) LOG_WARNING("boot_config { dpacm_enable } will be deprecated. 'dpacm_enable' should be specified along with the partition. \n See 'bootgen -bif_help dpacm_enable' for more info."); currentBifOptions->SetDpaCM($1); } | SMAP_WIDTH EQUAL expression { if(($3 != 8) && ($3 !=16) && ($3 != 32) && ($3 != 0)) LOG_ERROR("Invalid smap_width value in BIF. Valid values are 8, 16 and 32"); currentBifOptions->SetSmapWidth($3); } | BYPASS_IDCODE_CHECK { currentBifOptions->SetBypassIdcodeFlag(true); } | A_HWROT { currentBifOptions->SetAHwRoTFlag(true); } | S_HWROT { currentBifOptions->SetSHwRoTFlag(true); } | PUFROSWAP EQUAL expression { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) currentBifOptions->SetPufRingOscilltorSwapConfigValue($3); else LOG_ERROR("BIF attribute error !!!\n\t 'puf_ro_swap' is supported only in VersalNet architecture"); } | DICE { if(options.GetArchType() == Arch::VERSAL && options.IsVersalNetSeries()) currentBifOptions->SetDiceEnable(); else LOG_ERROR("BIF attribute error !!!\n\t 'dice_enable' is supported only in VersalNet architecture"); } ; file_spec : OBRACKET { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(),options.IsVersalNetSeries()); } attribute_list EBRACKET filename { currentPartitionBifOptions->filename = $5; currentPartitionBifOptions->filelist.push_back($5); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } | filename { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); currentPartitionBifOptions->filename = $1; currentPartitionBifOptions->filelist.push_back($1); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); }; new_file_spec : OBRACE { currentPartitionBifOptions = new PartitionBifOptions(); currentPartitionBifOptions->SetArchType(options.GetArchType(), options.IsVersalNetSeries()); } new_attribute_list EBRACE ; new_attribute_list : attribute | new_attribute | new_attribute COMMA new_attribute_list | attribute COMMA new_attribute_list | new_attribute new_attribute_list | attribute new_attribute_list ; new_attribute : PFILE EQUAL filename { currentPartitionBifOptions->filename = $3; currentPartitionBifOptions->filelist.push_back($3); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } | ID EQUAL expression { currentPartitionBifOptions->partitionId = $3; } | IMAGE_STORE EQUAL expression { currentPartitionBifOptions->imageStoreId = $3; currentPartitionBifOptions->SetPartitionType(PartitionType::IMAGE_STORE_PDI); } | PARTITION_TYPE EQUAL boolattr | PARTITION_TYPE EQUAL PMCDATA { currentPartitionBifOptions->fileType = $3; } | BIF_SECTION EQUAL WORD { currentPartitionBifOptions->bifSection = $3; currentPartitionBifOptions->filename = currentPartitionBifOptions->GetOutputFileFromBifSection(options.GetOutputFileNames().front(), $3, currentImageBifOptions->GetImageType()); currentBifOptions->Add(currentPartitionBifOptions, currentImageBifOptions); } ; attribute_list : attribute | attribute COMMA attribute_list ; attribute : boolattr | optattr | numattr | fileattr | blocksattr_list ; blocksattr_list : BLOCKS EQUAL blocksattr | AUTHBLOCKS EQUAL authblockattr ; blocksattr : blockattr | blockattr SEMICOLON blocksattr ; bootvectors_list : bootvector | bootvector COMMA bootvectors_list ; bootvector : expression { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[bootvectors] only supported in ZYNQMP architecture"); currentBifOptions->SetBootVectorArray($1); } ; authblockattr : expression { currentPartitionBifOptions->SetAuthBlockAttr($1); } boolattr : BOOTLOADER { currentPartitionBifOptions->bootloader = true;} | BOOT { currentPartitionBifOptions->boot = true;} | USER { currentPartitionBifOptions->user = true;} | STATIC { currentPartitionBifOptions->Static = true;} | NOAUTOSTART { currentPartitionBifOptions->noautostart = true;} | MULTIBOOT { currentPartitionBifOptions->multiboot = true;} | PROTECTED { currentPartitionBifOptions->Protected = true;} | EARLY_HANDOFF { currentPartitionBifOptions->SetEarlyHandoff(true); } | HIVEC { currentPartitionBifOptions->SetHivec(true); } | XIP_MODE { if(currentPartitionBifOptions->bootloader!=true) LOG_ERROR("XIP mode can be enabled only for bootloader"); currentBifOptions->SetXipMode(); } | INIT { currentPartitionBifOptions->fileType = $1; } | BOOTIMAGE { currentPartitionBifOptions->bootImage = true; } | key_file { currentPartitionBifOptions->fileType = $1; } | other_files { currentPartitionBifOptions->fileType = $1; } | ptypevalue { currentPartitionBifOptions->SetPartitionType($1); } | LOCKSTEP { currentPartitionBifOptions->SetLockStepFlag();} ; trustzone_type : TRUSTZONE { currentPartitionBifOptions->SetTrustZone(::TrustZone::Secure); } | TRUSTZONE EQUAL TRUSTZONE_TYPE { currentPartitionBifOptions->SetTrustZone($3); } ; blockattr : expression { currentPartitionBifOptions->SetEncryptionBlocks($1); } | expression LPAREN expression RPAREN { currentPartitionBifOptions->SetEncryptionBlocks($1, $3); } | expression LPAREN ASTERISK RPAREN { currentPartitionBifOptions->SetEncryptionBlocks($1, 0); } optattr : AUTHENTICATION EQUAL authvalue { currentPartitionBifOptions->SetAuthType($3); } | ENCRYPTION EQUAL encrvalue { currentPartitionBifOptions->SetEncryptType($3); } | CHECKSUM EQUAL checkvalue { currentPartitionBifOptions->SetChecksumType($3); } | PARTITION_OWNER EQUAL pownervalue { currentPartitionBifOptions->SetOwnerType($3); } | DEST_CPU EQUAL dest_cpu_type { currentPartitionBifOptions->SetDestCpu($3); } | DEST_DEVICE EQUAL dest_device_type { currentPartitionBifOptions->SetDestDevice($3); } | EXCEPTION_LEVEL EQUAL exception_level_type { currentPartitionBifOptions->SetExceptionLevel($3); } | AES_KEY_FILE EQUAL filename { currentPartitionBifOptions->SetAesKeyFile($3); } | PPK_FILE EQUAL filename { currentPartitionBifOptions->ppkFile = ($3); } | PSK_FILE EQUAL filename { currentPartitionBifOptions->pskFile = ($3); } | SPK_FILE EQUAL filename { currentPartitionBifOptions->spkFile = ($3); } | SSK_FILE EQUAL filename { currentPartitionBifOptions->sskFile = ($3); } | SPK_SELECT EQUAL spkselect { currentPartitionBifOptions->spkSelect =($3); currentPartitionBifOptions->spkSelLocal = true; } | SPK_ID EQUAL expression { currentPartitionBifOptions->SetSpkId($3); } | SPK_SIGNATURE_FILE EQUAL filename { currentPartitionBifOptions->spkSignatureFile = ($3); } | trustzone_type | PARTITION_TYPE EQUAL ptypevalue { currentPartitionBifOptions->SetPartitionType($3); } | KEYSRC_ENCRYPTION EQUAL key_src { currentPartitionBifOptions->SetEncryptionKeySource($3); } | REVOKE_ID EQUAL expression { currentPartitionBifOptions->SetRevokeId($3); } | DPA_CM { currentPartitionBifOptions->SetDpaCM(DpaCM::DpaCMEnable); } | SLR_NUM EQUAL expression { currentPartitionBifOptions->SetSlrNum($3); } | CLUSTER_NUM EQUAL expression { currentPartitionBifOptions->SetClusterNum($3); } | PUFHD_LOC { currentPartitionBifOptions->SetPufHdLocation(PufHdLoc::PUFinBH); } | DELAY_AUTH { currentPartitionBifOptions->SetDelayAuth(true); } | TCM_BOOT { currentPartitionBifOptions->SetTcmBootFlag(); } ; other_file_attr : INIT | key_file | BH_KEK_IV | BBRAM_KEK_IV | EFUSE_KEK_IV | EFUSE_USER_KEK0_IV | EFUSE_USER_KEK1_IV | USER_KEYS ; authvalue : NONE { $$ = ::Authentication::None;} | AUTHVALUE ; encrvalue : NONE { $$ = ::Encryption::None;} | ENCRVALUE ; checkvalue : NONE { $$ = ::Checksum::None;} | CHECKSUMVALUE ; pownervalue : POWNERVALUE ; ptypevalue : PTYPEVALUE ; key_src : KEY_SRC ; core : CORE ; bh_rsa : BH_RSA ; dpa_cm : DPA_CM ; auth_hash : AUTH_HASH ; int_hash : INT_HASH ; pufhd_loc : PUFHD_LOC ; opt_key : OPT_KEY ; auth_only : AUTH_ONLY ; boot_device_type : BOOT_DEVICE_TYPE ; dest_cpu_type : DEST_CPU_TYPE ; dest_device_type : DEST_DEVICE_TYPE ; exception_level_type : EXCEPTION_LEVEL_TYPE ; numattr : ALIGNMENT EQUAL expression { currentPartitionBifOptions->alignment = $3; } | OFFSET EQUAL expression { currentPartitionBifOptions->offset = $3; } | RESERVE_LEGACY EQUAL expression { currentPartitionBifOptions->SetReserveLength($3, false); } | RESERVE EQUAL expression { currentPartitionBifOptions->SetReserveLength($3, true); } | LOAD EQUAL expression { currentPartitionBifOptions->load = $3; } | STARTUP EQUAL expression { currentPartitionBifOptions->startup = $3; } | BIGENDIAN { currentPartitionBifOptions->bigEndian = true; } | A32_MODE { currentPartitionBifOptions->a32Mode = true; } | PARTITION_NUM EQUAL expression { currentPartitionBifOptions->pid = $3; } | TCM_A_REGION EQUAL expression { currentPartitionBifOptions->SetTcmARegion($3); } | TCM_B_REGION EQUAL expression { currentPartitionBifOptions->SetTcmBRegion($3); } | TCM_C_REGION EQUAL expression { currentPartitionBifOptions->SetTcmCRegion($3); } ; fileattr : PRESIGN EQUAL filename { currentPartitionBifOptions->presignFile = $3; } | AC EQUAL filename { currentPartitionBifOptions->acFile = $3; } | UDF_DATA EQUAL filename { currentPartitionBifOptions->SetUdfDataFile($3); } ; key_file : AES_KEY_FILE | rsa_key_file | SPK_SIGNATURE_FILE | BH_SIGNATURE_FILE | HEADER_SIGNATURE_FILE | BH_KEY_FILE | PUF_HELPER_FILE | BH_KEY_IV | FAMILY_KEY ; rsa_key_file : PPK_FILE | PSK_FILE | SPK_FILE | SSK_FILE ; other_files : PMUFW_IMAGE | PMCDATA | UDF_BH ; auth_parameters : PPK_SELECT EQUAL expression { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetPPKSelection($3); } | SPK_SELECT EQUAL spkselect { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetSPKSelection($3); } | SPK_ID EQUAL expression { if(options.GetArchType() != Arch::ZYNQMP) LOG_WARNING("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetSpkId($3); } | HEADER_AUTH { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[auth_params] is supported only in ZYNQMP architecture"); currentBifOptions->SetHeaderAuthentication(); } | auth_parameters SEMICOLON auth_parameters ; spkselect : SPKSELECT ; split_options : SPLIT_MODE EQUAL splitmode { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitMode($3); } | SPLIT_FMT EQUAL splitfmt | split_options COMMA split_options ; splitmode : SPLITMODE ; splitfmt : MCS { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitFmt(File::MCS); } | BIN { if(options.GetArchType() != Arch::ZYNQMP) LOG_ERROR("BIF attribute error !!!\n\t\t[split] not supported in ZYNQ architecture"); currentBifOptions->SetSplitFmt(File::BIN); } ; filename : FILENAME | QFILENAME ; number : HEXVALUE | DECVALUE | LPAREN expression RPAREN { $$ = $2; }; // highest precendence unary_expression : number | PLUS unary_expression {$$ = $2; *options.debugstr << $$ << " + " << $2 << std::endl;} | NEGATION unary_expression {$$ = ~$2; *options.debugstr << $$ << " ~ " << $2 << std::endl;} ; multiplicative_expression : unary_expression | multiplicative_expression MULT unary_expression {$$ = $1 * $3; *options.debugstr << $$ << " = " << $1 << " + " << $3 << std::endl;} | multiplicative_expression DIVIDE unary_expression {$$ = $1 / $3; *options.debugstr << $$ << " = " << $1 << " / " << $3 << std::endl;} | multiplicative_expression MODULO unary_expression {$$ = $1 % $3; *options.debugstr << $$ << " = " << $1 << " % " << $3 << std::endl;} ; additive_expression : multiplicative_expression | additive_expression PLUS multiplicative_expression {$$ = $1 + $3;*options.debugstr << $$ << " = " << $1 << " + " << $3 << std::endl;} | additive_expression MINUS multiplicative_expression {$$ = $1 - $3;*options.debugstr << $$ << " = " << $1 << " - " << $3 << std::endl;} ; shift_expression : additive_expression | shift_expression LSHIFT additive_expression {$$ = $1 << $3;*options.debugstr << $$ << " = " << $1 << " << " << $3 << std::endl;} | shift_expression RSHIFT additive_expression {$$ = $1 >> $3;*options.debugstr << $$ << " = " << $1 << " >> " << $3 << std::endl;} ; and_expression : shift_expression | and_expression AND shift_expression {$$ = $1 & $3;*options.debugstr << $$ << " = " << $1 << " & " << $3 << std::endl;} ; xor_expression : and_expression | xor_expression XOR and_expression {$$ = $1 ^ $3;*options.debugstr << $$ << " = " << $1 << " ^ " << $3 << std::endl;} ; // lowest precendence expression : xor_expression | expression OR xor_expression {$$ = $1 | $3;*options.debugstr << $$ << " = " << $1 << " | " << $3 << std::endl;} ; %% void BIF::BisonParser::error(const BIF::BisonParser::location_type &loc, const std::string &msg) { Parsing::Error(loc,msg); } static int yylex(BIF::BisonParser::semantic_type * yylval, BIF::BisonParser::location_type* loc, BIF::FlexScanner &scanner) { return scanner.yylex(yylval,loc); } xilinx-bootgen-2024.2/bif.yy.cpp000077500000000000000000004141661475706442400165110ustar00rootroot00000000000000#line 2 "../bisonflex/bif.yy.cpp" #line 4 "../bisonflex/bif.yy.cpp" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ /* %not-for-header */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ /* %ok-for-header */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* %if-c++-only */ /* The c++ scanner is a mess. The FlexLexer.h header file relies on the * following macro. This is required in order to pass the c++-multiple-scanners * test in the regression suite. We get reports that it breaks inheritance. * We will address this in a future release of flex, or omit the C++ scanner * altogether. */ #define yyFlexLexer bifFlexLexer /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ /* %if-c-only */ /* %endif */ /* %if-tables-serialization */ /* %endif */ /* end standard C headers. */ /* %if-c-or-c++ */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ /* %endif */ /* %if-c++-only */ /* begin standard C++ headers. */ #include #include #include #include /* end standard C++ headers. */ /* %endif */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* %not-for-header */ /* Returned upon end-of-file. */ #define YY_NULL 0 /* %ok-for-header */ /* %not-for-header */ /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* %ok-for-header */ /* %if-reentrant */ /* %endif */ /* %if-not-reentrant */ /* %endif */ /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif /* %if-not-reentrant */ extern int yyleng; /* %endif */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { /* %if-c-only */ /* %endif */ /* %if-c++-only */ std::istream* yy_input_file; /* %endif */ char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %if-not-reentrant */ /* %endif */ /* %ok-for-header */ /* %endif */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* %if-c-only Standard (non-C++) definition */ /* %if-not-reentrant */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ /* %endif */ void *bifalloc (yy_size_t ); void *bifrealloc (void *,yy_size_t ); void biffree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ /* Begin user sect3 */ #define YY_SKIP_YYWRAP #define FLEX_DEBUG typedef unsigned char YY_CHAR; #define yytext_ptr yytext #include "FlexLexer.h" int yyFlexLexer::yywrap() { return 1; } int yyFlexLexer::yylex() { LexerError( "yyFlexLexer::yylex invoked but %option yyclass used" ); return 0; } #define YY_DECL int FlexScanner::yylex() /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ #define YY_NUM_RULES 271 #define YY_END_OF_BUFFER 272 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[1225] = { 0, 0, 0, 272, 270, 267, 268, 269, 270, 259, 261, 250, 251, 252, 253, 245, 254, 265, 258, 239, 239, 242, 243, 270, 244, 270, 241, 264, 246, 247, 263, 264, 241, 241, 241, 241, 241, 241, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 248, 262, 249, 260, 267, 268, 0, 0, 265, 1, 265, 239, 241, 265, 255, 256, 241, 0, 264, 241, 241, 264, 241, 5, 241, 241, 264, 264, 264, 241, 264, 264, 264, 264, 264, 241, 241, 264, 264, 264, 241, 264, 264, 241, 241, 241, 264, 264, 264, 264, 241, 264, 264, 264, 264, 264, 264, 54, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 209, 264, 264, 264, 208, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 266, 0, 0, 2, 265, 240, 0, 241, 264, 241, 241, 264, 264, 241, 80, 205, 264, 264, 264, 264, 264, 264, 235, 264, 264, 264, 100, 102, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 241, 264, 265, 109, 264, 264, 264, 264, 264, 264, 233, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 234, 87, 264, 168, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 65, 38, 96, 94, 203, 264, 264, 264, 264, 204, 264, 264, 265, 264, 264, 101, 264, 264, 82, 264, 264, 175, 265, 165, 166, 264, 264, 264, 264, 220, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 62, 169, 264, 211, 0, 265, 264, 265, 264, 265, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 8, 264, 265, 264, 264, 36, 183, 264, 264, 264, 264, 264, 264, 264, 264, 213, 214, 215, 216, 264, 264, 264, 264, 264, 56, 92, 264, 264, 264, 264, 264, 264, 39, 264, 264, 264, 35, 264, 264, 265, 180, 230, 264, 55, 164, 264, 265, 79, 264, 264, 264, 264, 264, 173, 264, 264, 264, 171, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 198, 200, 265, 265, 264, 264, 264, 264, 264, 172, 265, 265, 265, 264, 264, 88, 89, 264, 264, 265, 174, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 99, 264, 264, 9, 264, 184, 188, 192, 195, 264, 187, 191, 194, 197, 264, 185, 189, 186, 190, 193, 196, 264, 264, 264, 264, 264, 264, 264, 264, 264, 113, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 83, 112, 264, 264, 264, 264, 264, 264, 264, 264, 19, 264, 25, 264, 264, 264, 264, 264, 264, 265, 265, 264, 264, 265, 264, 264, 264, 264, 264, 91, 264, 264, 264, 264, 210, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 265, 199, 201, 264, 264, 264, 264, 264, 167, 265, 265, 264, 264, 264, 264, 265, 265, 265, 264, 265, 264, 264, 264, 264, 229, 264, 264, 264, 264, 264, 264, 264, 264, 93, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 20, 264, 264, 264, 264, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 111, 264, 264, 264, 265, 265, 264, 264, 265, 265, 264, 232, 32, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 163, 162, 265, 264, 264, 264, 264, 264, 265, 265, 265, 264, 218, 264, 264, 265, 265, 265, 264, 265, 226, 264, 264, 264, 264, 264, 10, 264, 264, 264, 264, 264, 40, 264, 265, 264, 264, 264, 141, 143, 142, 144, 158, 264, 161, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 103, 264, 206, 264, 264, 264, 264, 264, 264, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 52, 264, 264, 29, 264, 264, 136, 264, 264, 179, 265, 264, 264, 97, 95, 264, 150, 264, 264, 264, 264, 60, 264, 264, 42, 4, 264, 43, 264, 264, 264, 264, 265, 145, 264, 34, 264, 159, 265, 176, 177, 27, 152, 264, 265, 265, 265, 264, 265, 264, 44, 264, 45, 37, 264, 264, 264, 30, 264, 264, 265, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 86, 264, 264, 264, 264, 264, 264, 264, 264, 265, 265, 264, 264, 264, 264, 264, 264, 170, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 28, 264, 181, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 58, 264, 148, 265, 264, 264, 264, 265, 264, 104, 265, 265, 264, 265, 264, 264, 264, 264, 264, 264, 6, 265, 264, 76, 7, 264, 264, 14, 149, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 72, 61, 264, 264, 264, 264, 264, 50, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 265, 265, 264, 264, 264, 264, 264, 264, 264, 264, 77, 264, 264, 264, 264, 264, 264, 264, 264, 264, 12, 264, 219, 264, 51, 264, 24, 264, 264, 264, 13, 151, 264, 265, 140, 264, 228, 178, 231, 265, 106, 264, 224, 264, 264, 264, 264, 264, 217, 265, 122, 123, 124, 125, 126, 127, 128, 129, 264, 41, 264, 264, 21, 264, 264, 264, 264, 264, 264, 264, 121, 120, 57, 264, 22, 264, 264, 3, 264, 264, 18, 264, 17, 264, 237, 264, 264, 264, 84, 85, 264, 264, 264, 264, 264, 78, 264, 264, 264, 264, 264, 264, 264, 67, 264, 264, 26, 264, 264, 63, 264, 66, 264, 222, 264, 265, 264, 105, 265, 156, 223, 264, 264, 264, 264, 225, 264, 221, 264, 264, 264, 264, 264, 264, 264, 264, 47, 138, 160, 49, 264, 264, 264, 155, 264, 264, 264, 264, 264, 264, 264, 264, 264, 137, 64, 227, 264, 264, 264, 264, 11, 264, 264, 264, 59, 153, 202, 264, 265, 265, 264, 264, 264, 264, 23, 264, 264, 264, 264, 264, 71, 264, 264, 264, 264, 264, 154, 264, 264, 264, 73, 264, 264, 264, 264, 264, 264, 264, 139, 238, 264, 31, 264, 264, 264, 265, 265, 46, 68, 69, 70, 264, 264, 264, 118, 119, 117, 264, 264, 16, 264, 264, 15, 115, 116, 114, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 265, 265, 264, 81, 264, 146, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 98, 33, 107, 265, 264, 236, 264, 182, 264, 264, 264, 264, 264, 130, 133, 212, 264, 48, 264, 90, 265, 147, 264, 264, 264, 264, 264, 264, 53, 264, 108, 264, 264, 264, 264, 264, 264, 110, 264, 207, 264, 264, 74, 75, 157, 131, 134, 132, 135, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 6, 6, 8, 9, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 6, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 34, 34, 36, 37, 38, 39, 40, 1, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[71] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1 } ; static yyconst flex_int16_t yy_base[1229] = { 0, 0, 0, 2506, 2507, 69, 2502, 2507, 70, 2507, 2507, 2507, 2507, 2507, 0, 2507, 0, 0, 60, 119, 38, 2507, 2507, 2474, 2507, 2471, 171, 220, 2507, 2507, 2507, 2474, 227, 232, 103, 121, 248, 237, 108, 115, 2441, 37, 2445, 260, 126, 236, 273, 2440, 278, 298, 41, 286, 2449, 2507, 2507, 2507, 2507, 169, 2494, 2489, 172, 0, 2507, 358, 121, 411, 458, 2507, 2507, 2467, 165, 2466, 289, 485, 221, 120, 181, 231, 234, 228, 257, 249, 122, 296, 324, 148, 292, 227, 320, 328, 299, 313, 345, 348, 290, 351, 353, 365, 378, 367, 356, 374, 380, 352, 365, 355, 378, 388, 413, 147, 384, 415, 416, 417, 145, 391, 420, 390, 427, 393, 423, 424, 434, 436, 465, 441, 432, 439, 442, 460, 466, 429, 444, 479, 470, 486, 492, 481, 488, 527, 489, 504, 507, 505, 508, 510, 542, 511, 521, 523, 528, 522, 537, 530, 544, 547, 548, 550, 549, 552, 556, 551, 2507, 566, 2490, 2507, 608, 0, 0, 613, 614, 571, 574, 562, 559, 563, 598, 2464, 596, 602, 565, 617, 599, 595, 2463, 623, 603, 624, 2462, 641, 627, 629, 606, 634, 632, 633, 646, 639, 644, 652, 653, 654, 671, 2461, 657, 655, 658, 666, 668, 669, 2460, 670, 673, 674, 678, 677, 679, 680, 671, 681, 682, 693, 691, 696, 2459, 2458, 697, 712, 701, 706, 708, 711, 709, 728, 714, 716, 720, 722, 717, 723, 729, 721, 2457, 2456, 735, 726, 736, 730, 724, 731, 2455, 758, 750, 772, 766, 757, 2454, 760, 737, 2453, 765, 767, 2452, 2427, 781, 782, 772, 80, 774, 775, 789, 779, 798, 787, 783, 790, 799, 784, 786, 791, 802, 2450, 2449, 793, 812, 2469, 835, 794, 841, 817, 240, 845, 819, 821, 839, 840, 842, 847, 845, 843, 848, 844, 846, 852, 850, 854, 866, 851, 2428, 858, 860, 2446, 2445, 862, 865, 873, 879, 855, 875, 883, 884, 0, 0, 0, 0, 885, 889, 893, 894, 902, 2444, 895, 897, 898, 903, 904, 906, 905, 2443, 913, 909, 910, 2442, 911, 908, 2411, 927, 2440, 916, 2439, 2438, 917, 2409, 2436, 924, 930, 934, 932, 935, 2435, 936, 944, 940, 2434, 946, 945, 947, 948, 952, 953, 950, 954, 957, 959, 956, 976, 0, 0, 2406, 614, 960, 963, 964, 965, 978, 2432, 2400, 2400, 2399, 981, 983, 2428, 2427, 985, 986, 976, 987, 2409, 995, 997, 998, 992, 1000, 996, 1001, 1020, 1004, 1005, 2425, 1006, 1009, 1027, 1011, 0, 0, 0, 0, 1047, 0, 0, 0, 0, 1048, 0, 0, 0, 0, 0, 0, 1015, 564, 1029, 1012, 1030, 1045, 1032, 1051, 1046, 1052, 1053, 1057, 1054, 1058, 1061, 1062, 1059, 1067, 1068, 1065, 1069, 1063, 2393, 1066, 1079, 1089, 1074, 1098, 1099, 1102, 1105, 1084, 1106, 1075, 1104, 1107, 1108, 1109, 1110, 1111, 1112, 2423, 1113, 1119, 1120, 1121, 1122, 1123, 1126, 1127, 2409, 2391, 1133, 1128, 1110, 1141, 1138, 1143, 1148, 1145, 2420, 1149, 1151, 1152, 1154, 1157, 1159, 1160, 1161, 1163, 1164, 1166, 1168, 1167, 1170, 1185, 1195, 2404, 0, 0, 1177, 1172, 1174, 1192, 1193, 2431, 2404, 2403, 1196, 1197, 1199, 1201, 2388, 2387, 2389, 1200, 2394, 1202, 1204, 1203, 1205, 2411, 1206, 1207, 1210, 1217, 1219, 1222, 1211, 283, 2410, 1212, 1213, 2392, 1228, 1233, 1236, 1245, 1247, 1252, 1248, 1239, 1254, 1243, 1249, 1253, 1255, 1256, 1257, 1258, 1259, 1260, 1264, 1262, 1268, 1272, 1276, 1286, 1266, 1289, 2408, 1265, 1290, 1293, 1295, 1296, 1297, 2392, 1299, 1300, 1301, 1302, 1310, 1303, 1316, 1317, 2378, 1312, 1318, 1319, 1313, 1323, 1320, 1324, 1327, 1341, 1338, 1344, 1328, 1339, 1346, 1349, 1347, 1348, 1357, 2370, 2391, 1352, 1358, 2378, 2387, 1362, 2401, 2400, 1363, 1364, 1366, 1369, 1368, 1373, 1371, 1374, 1376, 1375, 1380, 1382, 1381, 1383, 1385, 1261, 2399, 2398, 2374, 1387, 1391, 1388, 1402, 1396, 2366, 2360, 2359, 1403, 2393, 1404, 1406, 2365, 2365, 2377, 1409, 2356, 2388, 1413, 1415, 1416, 1418, 1417, 2387, 1419, 1420, 1421, 1422, 1425, 2386, 1423, 2367, 1424, 1426, 1427, 2384, 2383, 2382, 2381, 2380, 1436, 2379, 1438, 1431, 1440, 1439, 1447, 1446, 1444, 1453, 1456, 1458, 1462, 1466, 1470, 1467, 1468, 1471, 1473, 1474, 1475, 1476, 1477, 1478, 1481, 1485, 1484, 1487, 0, 1486, 2378, 1489, 1493, 1496, 1498, 1499, 1504, 1502, 1505, 802, 1509, 1510, 1514, 1519, 1513, 1520, 1521, 1524, 1526, 1529, 1532, 1534, 1525, 1527, 2377, 1535, 1537, 2376, 1543, 1539, 2375, 1545, 1547, 0, 2339, 1549, 1550, 0, 0, 1554, 2373, 1555, 1557, 1559, 1561, 2372, 1566, 1552, 2371, 2370, 1570, 2369, 1565, 1571, 1567, 1572, 2337, 2367, 1575, 1583, 1580, 2366, 2352, 0, 0, 2364, 2363, 1585, 2330, 2343, 2326, 1589, 2328, 1593, 2358, 1594, 2357, 2356, 1596, 1597, 1600, 2355, 1602, 1603, 2321, 1574, 1604, 1606, 1608, 1615, 1609, 1618, 1619, 1629, 1620, 1622, 1624, 1625, 1626, 1627, 1630, 1634, 1640, 1642, 1631, 1638, 1644, 1645, 1647, 1649, 1652, 1653, 1654, 1656, 1658, 2353, 1661, 1662, 1664, 1666, 1669, 1675, 1679, 1676, 2354, 2359, 1680, 1681, 1682, 1684, 1690, 1685, 2350, 1691, 1686, 1694, 1696, 1697, 1699, 1701, 1704, 1706, 1708, 1711, 2349, 1710, 0, 1713, 1715, 1716, 1719, 1722, 1721, 1723, 1724, 1726, 1729, 1734, 1740, 2348, 1743, 2347, 2314, 1746, 1747, 1748, 2310, 1751, 0, 2323, 2326, 1752, 2325, 1753, 1754, 1755, 1756, 1758, 1759, 2341, 2309, 1797, 2339, 2338, 1769, 1762, 2337, 2336, 1760, 1761, 1767, 1782, 1765, 1799, 1800, 1801, 1802, 1781, 1766, 1772, 2335, 2334, 1804, 1805, 1806, 1808, 1810, 2333, 1815, 1816, 1818, 1817, 1820, 1822, 1823, 1826, 1819, 1827, 1824, 2338, 2340, 1830, 1844, 1847, 1848, 1828, 1831, 1849, 1834, 2330, 1851, 1852, 1853, 1854, 1863, 1862, 1864, 1867, 1865, 2329, 1866, 2328, 1870, 2327, 1868, 1874, 1869, 1871, 1875, 2326, 2325, 1876, 2307, 2323, 1877, 2322, 0, 2321, 2301, 2332, 1878, 0, 1887, 1888, 1892, 1893, 1897, 2318, 2300, 2316, 2315, 2314, 2313, 2312, 2311, 2310, 2309, 1899, 2308, 1900, 1903, 2307, 1901, 1902, 1904, 1909, 1916, 1911, 1910, 2306, 2305, 2304, 1908, 2303, 1917, 1922, 2302, 1912, 1924, 2301, 1926, 2300, 1928, 2299, 1930, 1935, 1938, 0, 0, 1940, 1941, 1945, 1944, 1946, 2298, 1948, 1952, 1942, 1955, 1949, 1957, 1956, 2297, 1950, 1960, 2296, 1962, 1973, 2295, 1974, 2294, 1975, 2293, 1976, 2264, 1978, 0, 1965, 2291, 2290, 1981, 1982, 1985, 1986, 0, 1991, 2289, 1984, 1993, 1989, 1999, 2000, 1987, 2002, 2018, 2288, 2287, 2286, 2285, 2007, 2020, 2022, 2284, 2024, 2025, 2027, 2028, 1995, 2030, 2035, 2031, 2039, 2283, 2282, 2281, 2033, 2036, 2037, 2003, 2280, 2046, 2026, 2042, 2279, 2278, 0, 2050, 2250, 2249, 2053, 2052, 2056, 2057, 2275, 2060, 2062, 2066, 2064, 2067, 2274, 2068, 2071, 2074, 2072, 2077, 2273, 2076, 2075, 2080, 2272, 2081, 2085, 2086, 2096, 2087, 2088, 2097, 2271, 2270, 2098, 2269, 2099, 2100, 2107, 2241, 2241, 2266, 2265, 2264, 2263, 2106, 2108, 2102, 2262, 2251, 2249, 2110, 2119, 2248, 2111, 2115, 2247, 2246, 2245, 2242, 2114, 2124, 2129, 2133, 2135, 2138, 2140, 2136, 2141, 2142, 2209, 2222, 2143, 2239, 2144, 2238, 2145, 2147, 2148, 2157, 2159, 2164, 2183, 2146, 2149, 2175, 2156, 2151, 2237, 2236, 0, 2213, 2176, 2232, 2178, 2231, 2184, 2185, 2186, 2187, 2188, 2230, 2229, 2227, 2189, 1998, 2190, 1996, 1969, 1906, 2194, 2195, 2196, 2197, 2191, 2201, 1770, 2202, 0, 2203, 2204, 2207, 2215, 2216, 2219, 1070, 2220, 1010, 2233, 2235, 792, 484, 446, 443, 386, 279, 220, 2507, 169, 2280, 2283, 2286 } ; static yyconst flex_int16_t yy_def[1229] = { 0, 1224, 1, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1225, 1224, 1225, 1225, 1225, 1225, 19, 1224, 1224, 1224, 1224, 1224, 1224, 26, 1224, 1224, 1224, 27, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1224, 1224, 1224, 1224, 1224, 1224, 1226, 1226, 1225, 1224, 1227, 19, 19, 65, 1224, 1224, 26, 1224, 27, 26, 32, 27, 26, 73, 73, 73, 27, 27, 27, 26, 27, 27, 27, 27, 27, 26, 26, 27, 27, 27, 26, 27, 27, 26, 73, 73, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1224, 1224, 1228, 1224, 1227, 66, 1225, 26, 27, 26, 73, 27, 27, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1226, 1225, 27, 1225, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 1225, 1225, 27, 27, 27, 27, 27, 27, 1225, 1225, 1225, 27, 27, 27, 27, 27, 27, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 1225, 1225, 27, 1225, 1225, 1225, 1225, 27, 1225, 1225, 1225, 1225, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 1225, 27, 27, 27, 27, 27, 1225, 1225, 1225, 27, 27, 27, 27, 1225, 1225, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 1225, 1225, 1225, 27, 27, 27, 27, 1225, 1225, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 1225, 1225, 1225, 27, 27, 27, 1225, 1225, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 1225, 27, 1225, 1225, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 1225, 27, 1225, 1225, 27, 1225, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1225, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 1224, 1224, 1224, 1224 } ; static yyconst flex_int16_t yy_nxt[2578] = { 0, 4, 5, 6, 7, 5, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 27, 28, 17, 29, 30, 31, 32, 33, 34, 35, 36, 37, 27, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 27, 27, 52, 27, 27, 53, 54, 55, 56, 57, 62, 61, 57, 59, 59, 63, 59, 59, 59, 59, 114, 59, 154, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 115, 155, 391, 392, 61, 60, 60, 60, 156, 59, 1224, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 88, 1224, 89, 1224, 90, 65, 108, 66, 91, 61, 109, 92, 110, 65, 65, 65, 65, 65, 65, 93, 123, 111, 112, 94, 57, 61, 1224, 57, 1224, 1224, 95, 174, 162, 180, 124, 168, 66, 61, 61, 61, 61, 61, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 163, 69, 168, 185, 69, 71, 71, 69, 61, 214, 220, 71, 69, 69, 69, 69, 69, 69, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 1224, 1224, 72, 69, 73, 71, 69, 1224, 1224, 69, 423, 424, 69, 71, 71, 71, 71, 71, 71, 74, 75, 173, 76, 77, 78, 177, 82, 175, 79, 1224, 103, 80, 83, 84, 125, 187, 85, 1224, 104, 86, 81, 96, 105, 97, 126, 176, 98, 127, 106, 87, 107, 128, 99, 139, 100, 117, 118, 119, 178, 1224, 101, 179, 169, 1224, 102, 120, 129, 121, 130, 1224, 1224, 140, 1224, 122, 131, 141, 1224, 132, 133, 1224, 157, 134, 158, 135, 136, 197, 137, 159, 181, 142, 143, 144, 145, 1224, 146, 147, 190, 160, 148, 186, 1224, 660, 149, 150, 1224, 170, 151, 182, 1224, 152, 153, 164, 164, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 183, 164, 1224, 191, 188, 1224, 189, 184, 1224, 1224, 1224, 202, 1224, 1224, 69, 164, 164, 164, 164, 164, 69, 198, 1224, 164, 1224, 164, 164, 69, 204, 194, 192, 1224, 193, 69, 208, 1224, 195, 1224, 200, 196, 199, 1224, 203, 1224, 210, 1224, 209, 1224, 1224, 211, 1224, 205, 206, 215, 164, 164, 164, 164, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 201, 207, 1224, 212, 1224, 1224, 1224, 61, 221, 1224, 224, 225, 1224, 1224, 226, 213, 1224, 216, 1224, 219, 217, 1224, 222, 1224, 223, 1224, 218, 227, 1224, 228, 1224, 1224, 1224, 1224, 242, 1224, 61, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 229, 235, 1224, 230, 231, 167, 236, 1224, 1224, 237, 238, 243, 1224, 167, 167, 167, 167, 167, 167, 171, 232, 1224, 69, 1224, 69, 172, 1224, 1224, 1224, 240, 1224, 1224, 239, 233, 1224, 246, 244, 234, 241, 71, 69, 251, 69, 69, 69, 247, 1224, 1224, 71, 1224, 1224, 71, 1224, 1224, 245, 248, 253, 249, 252, 250, 71, 254, 259, 1224, 1224, 1224, 256, 260, 266, 1224, 1224, 263, 1224, 262, 264, 265, 267, 257, 269, 1224, 258, 255, 261, 271, 1224, 275, 1224, 272, 273, 1224, 1224, 1224, 1224, 1224, 1224, 270, 268, 285, 1224, 551, 290, 1224, 274, 291, 1224, 1224, 1224, 1224, 69, 280, 281, 276, 282, 1224, 69, 283, 293, 285, 278, 279, 298, 284, 277, 164, 164, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 294, 164, 1224, 1224, 292, 1224, 1224, 286, 288, 1224, 1224, 507, 508, 1224, 304, 164, 164, 164, 164, 164, 1224, 1224, 296, 164, 1224, 164, 164, 303, 295, 297, 1224, 1224, 287, 289, 1224, 308, 1224, 299, 300, 1224, 1224, 1224, 306, 301, 307, 305, 1224, 302, 1224, 309, 311, 1224, 313, 1224, 164, 164, 164, 164, 312, 1224, 1224, 1224, 1224, 316, 1224, 1224, 317, 310, 321, 322, 323, 324, 314, 1224, 315, 1224, 1224, 1224, 1224, 326, 1224, 1224, 327, 318, 1224, 1224, 1224, 1224, 1224, 1224, 328, 319, 320, 330, 325, 332, 329, 333, 1224, 335, 1224, 331, 334, 1224, 1224, 336, 345, 339, 1224, 346, 338, 337, 341, 1224, 342, 1224, 1224, 344, 1224, 1224, 340, 1224, 352, 1224, 1224, 347, 343, 1224, 1224, 1224, 1224, 1224, 349, 1224, 350, 1224, 1224, 1224, 1224, 357, 364, 360, 1224, 1224, 1224, 348, 355, 361, 358, 351, 359, 366, 353, 363, 356, 367, 371, 1224, 365, 372, 379, 368, 362, 370, 1224, 1224, 354, 1224, 369, 376, 377, 383, 1224, 1224, 1224, 387, 388, 373, 375, 1224, 380, 1224, 1224, 395, 382, 374, 1224, 385, 1224, 1224, 1224, 1224, 397, 1224, 1224, 381, 1224, 1224, 1224, 1224, 1224, 1224, 826, 378, 827, 1224, 1224, 384, 402, 1224, 408, 389, 390, 393, 396, 401, 394, 398, 405, 1224, 406, 410, 407, 399, 1224, 409, 1224, 403, 1224, 404, 411, 412, 413, 414, 415, 416, 400, 417, 418, 419, 420, 421, 425, 426, 427, 428, 1224, 1224, 430, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 429, 1224, 1224, 1224, 422, 1224, 1224, 431, 432, 1224, 434, 1224, 435, 1224, 442, 436, 1224, 1224, 444, 433, 437, 438, 443, 440, 1224, 441, 1224, 439, 445, 446, 1224, 458, 452, 450, 1224, 1224, 1224, 455, 447, 456, 1224, 448, 457, 453, 1224, 1224, 1224, 460, 1224, 1224, 454, 449, 461, 1224, 1224, 1224, 1224, 1224, 467, 1224, 1224, 1224, 1224, 459, 1224, 480, 469, 1224, 1224, 470, 463, 465, 464, 462, 472, 1224, 474, 466, 1224, 478, 468, 1224, 471, 1224, 476, 1224, 1224, 1224, 481, 473, 475, 1224, 484, 477, 485, 1224, 1224, 1224, 1224, 1224, 482, 1224, 486, 1224, 1224, 1224, 487, 1224, 1224, 493, 1224, 1224, 491, 488, 1224, 1224, 1224, 489, 498, 504, 505, 490, 492, 503, 496, 497, 499, 1224, 501, 1224, 495, 500, 1224, 494, 1224, 510, 1224, 1224, 1224, 512, 502, 521, 522, 1224, 509, 511, 1224, 1224, 1224, 1224, 524, 1224, 1224, 517, 520, 1224, 1224, 1224, 523, 513, 1224, 1224, 1224, 1224, 518, 542, 1224, 526, 519, 528, 529, 1224, 531, 533, 540, 530, 541, 527, 1224, 532, 1224, 1224, 537, 1224, 534, 535, 536, 545, 538, 539, 543, 546, 548, 550, 547, 549, 1224, 1224, 1224, 1224, 553, 544, 1224, 1224, 1224, 1224, 554, 558, 1224, 1224, 1224, 552, 1224, 1224, 1224, 561, 1224, 1224, 1224, 1224, 1224, 1224, 585, 555, 556, 1224, 1224, 557, 559, 560, 1224, 563, 565, 570, 571, 1224, 562, 574, 567, 568, 1224, 569, 564, 573, 572, 575, 566, 578, 577, 1224, 1224, 580, 579, 1224, 587, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 583, 581, 582, 584, 586, 1224, 1224, 1224, 1224, 1224, 590, 592, 1224, 1224, 1224, 595, 588, 596, 593, 1224, 608, 609, 598, 600, 1224, 589, 601, 1224, 594, 1224, 603, 1224, 591, 606, 1224, 1224, 597, 1224, 1224, 599, 1224, 607, 610, 1224, 602, 1224, 1224, 1224, 611, 1224, 1224, 613, 1224, 1224, 1224, 619, 1224, 614, 1224, 617, 1224, 612, 620, 1224, 623, 629, 622, 615, 628, 616, 621, 1224, 618, 630, 624, 626, 632, 625, 1224, 1224, 627, 1224, 1224, 1224, 633, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 634, 635, 1224, 1224, 1224, 1224, 641, 643, 642, 1224, 649, 1224, 636, 650, 1224, 640, 652, 655, 662, 651, 1224, 656, 653, 657, 661, 1224, 658, 647, 1224, 667, 659, 1224, 654, 668, 670, 1224, 669, 1224, 672, 1224, 1224, 1224, 665, 664, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 666, 1224, 1224, 1224, 674, 1224, 677, 675, 671, 1224, 681, 673, 757, 1224, 678, 682, 692, 687, 676, 686, 683, 688, 679, 1224, 684, 689, 1224, 1224, 680, 694, 1224, 685, 1224, 1224, 1224, 690, 1224, 1224, 1224, 1224, 1224, 691, 693, 696, 695, 697, 699, 1224, 698, 1224, 1224, 703, 706, 1224, 1224, 1224, 1224, 1224, 704, 707, 1224, 1224, 705, 712, 1224, 1224, 708, 702, 713, 701, 709, 719, 714, 718, 710, 1224, 1224, 720, 1224, 715, 721, 1224, 716, 1224, 1224, 1224, 1224, 717, 722, 1224, 724, 723, 726, 729, 1224, 1224, 727, 728, 731, 1224, 1224, 1224, 733, 1224, 730, 1224, 1224, 734, 1224, 725, 1224, 1224, 1224, 1224, 743, 744, 737, 1224, 1224, 1224, 1224, 732, 1224, 747, 1224, 1224, 738, 745, 1224, 748, 750, 746, 741, 1224, 756, 749, 753, 742, 751, 1224, 1224, 1224, 761, 1224, 755, 754, 1224, 760, 759, 752, 1224, 762, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 763, 767, 773, 1224, 776, 769, 768, 778, 1224, 775, 1224, 1224, 1224, 787, 777, 789, 1224, 779, 1224, 1224, 790, 780, 781, 782, 784, 1224, 783, 785, 1224, 792, 1224, 791, 795, 796, 1224, 788, 793, 797, 1224, 1224, 1224, 794, 1224, 1224, 798, 1224, 1224, 1224, 1224, 1224, 1224, 801, 799, 1224, 803, 802, 1224, 1224, 1224, 1224, 800, 1224, 804, 805, 806, 1224, 807, 808, 1224, 810, 1224, 1224, 813, 814, 1224, 811, 1224, 1224, 819, 809, 816, 1224, 1224, 817, 812, 1224, 1224, 822, 815, 823, 825, 1224, 1224, 1224, 818, 820, 1224, 1224, 1224, 1224, 824, 1224, 821, 830, 1224, 828, 1224, 1224, 831, 1224, 840, 1224, 829, 833, 836, 1224, 832, 1224, 837, 1224, 841, 1224, 1224, 835, 1224, 834, 1224, 1224, 845, 1224, 838, 1224, 839, 1224, 842, 847, 843, 1224, 1224, 1224, 844, 858, 1224, 1224, 1224, 846, 1224, 1224, 849, 856, 853, 852, 1224, 860, 850, 1224, 851, 1224, 855, 859, 861, 1224, 854, 857, 863, 1224, 1224, 866, 1224, 1224, 862, 865, 1224, 867, 1224, 1224, 1224, 873, 1224, 876, 1224, 1224, 875, 883, 869, 877, 878, 1224, 881, 879, 1224, 1224, 1224, 891, 1224, 885, 1224, 1224, 1224, 1224, 880, 1224, 1224, 1224, 890, 886, 1224, 884, 894, 893, 1224, 887, 1224, 888, 1224, 892, 1224, 1224, 898, 1224, 895, 1224, 897, 899, 1224, 1224, 1224, 889, 1224, 900, 1224, 901, 906, 1224, 1224, 896, 1224, 902, 1224, 907, 904, 1224, 909, 910, 903, 908, 912, 1224, 1224, 915, 905, 1224, 1224, 1224, 1224, 911, 1224, 1224, 1224, 916, 914, 918, 1224, 1224, 919, 913, 1224, 917, 1224, 1224, 930, 1224, 926, 1224, 920, 923, 1224, 925, 1224, 927, 1224, 933, 1224, 1224, 928, 1224, 932, 1224, 1224, 929, 924, 1224, 935, 1224, 1224, 1224, 1224, 938, 1224, 940, 942, 1224, 936, 931, 934, 943, 1224, 944, 937, 939, 945, 949, 1224, 948, 946, 1224, 950, 941, 1224, 1224, 1224, 947, 951, 1224, 1224, 1224, 1224, 1224, 1224, 952, 1224, 1224, 1224, 1224, 1224, 955, 957, 1224, 1224, 1224, 964, 1224, 1224, 956, 1224, 982, 966, 967, 969, 968, 953, 980, 985, 1224, 1224, 959, 962, 981, 965, 971, 972, 973, 974, 975, 976, 977, 978, 984, 979, 1224, 983, 1224, 1224, 1224, 1224, 991, 1224, 1224, 1224, 990, 1224, 992, 1224, 986, 987, 988, 989, 1224, 1224, 1224, 1224, 1224, 1224, 993, 1224, 1224, 1224, 997, 1224, 1224, 1224, 996, 1224, 1224, 995, 1000, 1224, 994, 1002, 1001, 1003, 1005, 1008, 1007, 1011, 1006, 1224, 998, 999, 1224, 1224, 1224, 1004, 1224, 1224, 1224, 1224, 1018, 1012, 1016, 1015, 1013, 1014, 1017, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1019, 1020, 1224, 1224, 1224, 1224, 1224, 1024, 1022, 1023, 1026, 1029, 1030, 1021, 1031, 1224, 1224, 1035, 1033, 1025, 1224, 1224, 1037, 1027, 1028, 1224, 1040, 1224, 1224, 1224, 1224, 1224, 1224, 1032, 1224, 1034, 1224, 1224, 1224, 1224, 1224, 1043, 1044, 1047, 1224, 1224, 1045, 1041, 1049, 1042, 1224, 1056, 1224, 1057, 1224, 1052, 1224, 1051, 1224, 1048, 1053, 1050, 1055, 1224, 1058, 1054, 1224, 1059, 1224, 1224, 1224, 1060, 1224, 1224, 1224, 1064, 1224, 1224, 1224, 1061, 1224, 1062, 1063, 1224, 1224, 1224, 1071, 1065, 1224, 1074, 1224, 1067, 1068, 1066, 1069, 1070, 1073, 1076, 1077, 1075, 1072, 1224, 1224, 1224, 1224, 1078, 1224, 1089, 1090, 1224, 1224, 1079, 1224, 1224, 1224, 1224, 1205, 1224, 1080, 1224, 1085, 1224, 1081, 1224, 1224, 1088, 1224, 1224, 1224, 1083, 1224, 1224, 1086, 1082, 1084, 1224, 1095, 1092, 1096, 1091, 1093, 1094, 1097, 1098, 1099, 1100, 1224, 1102, 1224, 1101, 1224, 1104, 1224, 1224, 1224, 1224, 1224, 1111, 1224, 1224, 1103, 1224, 1106, 1224, 1224, 1224, 1105, 1224, 1121, 1107, 1224, 1108, 1109, 1110, 1224, 1112, 1116, 1113, 1224, 1117, 1224, 1224, 1114, 1119, 1224, 1224, 1115, 1122, 1224, 1123, 1224, 1125, 1224, 1118, 1224, 1224, 1224, 1120, 1128, 1224, 1224, 1132, 1224, 1224, 1224, 1224, 1129, 1124, 1224, 1224, 1130, 1131, 1134, 1224, 1224, 1224, 1224, 1133, 1140, 1139, 1141, 1142, 1143, 1138, 1224, 1224, 1224, 1224, 1224, 1135, 1224, 1151, 1136, 1137, 1224, 1224, 1224, 1147, 1224, 1224, 1144, 1149, 1224, 1224, 1148, 1145, 1146, 1224, 1159, 1150, 1156, 1161, 1224, 1154, 1153, 1162, 1155, 1224, 1152, 1163, 1165, 1224, 1160, 1224, 1224, 1166, 1224, 1164, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1170, 1224, 1168, 1174, 1186, 1187, 1224, 1224, 1175, 1224, 1181, 1167, 1171, 1180, 1224, 1191, 1169, 1179, 1172, 1184, 1190, 1185, 1173, 1188, 1189, 1224, 1224, 1193, 1224, 1176, 1182, 1194, 1183, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1192, 1196, 1224, 1224, 1224, 1224, 1197, 1201, 1202, 1224, 1224, 1224, 1224, 1198, 1203, 1224, 1199, 1200, 1207, 1206, 1210, 1208, 1209, 1224, 1224, 1204, 1213, 1224, 1224, 1214, 1211, 1220, 1221, 1222, 1223, 1224, 1212, 1224, 1224, 1224, 1224, 1224, 1195, 1224, 1224, 1224, 1224, 1224, 1178, 1177, 1224, 1219, 1215, 1224, 1224, 1224, 1224, 1224, 1217, 1224, 1216, 1218, 59, 59, 166, 166, 166, 164, 164, 164, 1224, 1224, 1224, 1224, 1224, 1158, 1157, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1127, 1126, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1087, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1046, 1224, 1039, 1038, 1224, 1224, 1224, 1036, 1224, 1224, 1224, 1224, 1224, 1224, 1010, 1009, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 970, 1224, 963, 961, 960, 958, 954, 1224, 1224, 1224, 1224, 922, 921, 1224, 882, 1224, 1224, 1224, 1224, 874, 872, 871, 870, 1224, 1224, 868, 1224, 1224, 864, 1224, 1224, 1224, 1224, 1224, 848, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 786, 1224, 1224, 1224, 774, 772, 771, 770, 1224, 766, 765, 764, 758, 1224, 1224, 1224, 1224, 740, 739, 736, 735, 711, 700, 1224, 663, 1224, 1224, 648, 646, 645, 644, 639, 638, 637, 631, 1224, 605, 604, 1224, 576, 1224, 525, 1224, 1224, 516, 515, 514, 1224, 506, 1224, 1224, 1224, 483, 1224, 1224, 1224, 479, 1224, 1224, 1224, 1224, 1224, 451, 1224, 1224, 1224, 386, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 165, 1224, 1224, 162, 58, 161, 138, 116, 113, 1224, 68, 67, 58, 1224, 3, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224 } ; static yyconst flex_int16_t yy_chk[2578] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 18, 20, 5, 8, 8, 18, 8, 8, 8, 8, 41, 8, 50, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 41, 50, 267, 267, 20, 8, 8, 8, 50, 8, 267, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 34, 75, 34, 82, 34, 19, 38, 19, 34, 64, 38, 34, 39, 19, 19, 19, 19, 19, 19, 35, 44, 39, 39, 35, 57, 1225, 114, 57, 109, 85, 35, 75, 60, 82, 44, 70, 19, 26, 64, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 60, 76, 70, 85, 26, 26, 26, 76, 26, 109, 114, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 1223, 74, 32, 77, 32, 27, 78, 87, 79, 77, 290, 290, 78, 27, 27, 27, 27, 27, 27, 32, 32, 74, 32, 32, 32, 79, 33, 77, 32, 81, 37, 32, 33, 33, 45, 87, 33, 80, 37, 33, 32, 36, 37, 36, 45, 78, 36, 45, 37, 33, 37, 45, 36, 48, 36, 43, 43, 43, 80, 1222, 36, 81, 72, 538, 36, 43, 46, 43, 46, 72, 94, 48, 86, 43, 46, 48, 83, 46, 46, 90, 51, 46, 51, 46, 46, 94, 46, 51, 83, 48, 49, 49, 49, 91, 49, 49, 90, 51, 49, 86, 88, 538, 49, 49, 84, 72, 49, 83, 89, 49, 49, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 84, 63, 92, 91, 88, 93, 89, 84, 95, 103, 96, 99, 105, 100, 97, 63, 63, 63, 63, 63, 97, 95, 104, 63, 99, 63, 63, 98, 100, 93, 92, 101, 92, 98, 103, 106, 93, 102, 97, 93, 96, 110, 99, 1221, 105, 107, 104, 117, 115, 106, 119, 101, 102, 110, 63, 63, 63, 63, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 98, 102, 108, 107, 111, 112, 113, 65, 115, 116, 117, 118, 120, 121, 119, 108, 118, 111, 131, 113, 112, 126, 116, 122, 116, 123, 112, 120, 127, 121, 125, 128, 1220, 132, 131, 1219, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 122, 125, 129, 123, 123, 66, 126, 124, 130, 127, 128, 132, 134, 66, 66, 66, 66, 66, 66, 73, 124, 133, 73, 137, 73, 73, 1218, 73, 135, 130, 138, 140, 129, 124, 136, 134, 133, 124, 130, 73, 73, 137, 73, 73, 73, 135, 141, 143, 73, 142, 144, 73, 145, 147, 133, 135, 139, 136, 138, 136, 73, 139, 142, 148, 151, 149, 140, 143, 147, 139, 150, 146, 153, 145, 146, 146, 148, 141, 149, 152, 141, 139, 144, 150, 146, 153, 154, 151, 151, 155, 156, 158, 157, 161, 159, 149, 148, 163, 160, 430, 171, 174, 152, 172, 173, 175, 430, 180, 172, 158, 159, 154, 160, 171, 172, 160, 174, 163, 156, 157, 180, 161, 155, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 175, 166, 183, 178, 173, 176, 182, 169, 170, 179, 186, 379, 379, 192, 183, 166, 166, 166, 166, 166, 169, 170, 178, 166, 181, 166, 166, 182, 176, 179, 185, 187, 169, 170, 190, 189, 191, 181, 181, 194, 195, 193, 186, 181, 187, 185, 197, 181, 189, 190, 192, 198, 194, 196, 166, 166, 166, 166, 193, 199, 200, 201, 205, 197, 204, 206, 198, 191, 202, 202, 202, 202, 195, 207, 196, 208, 209, 211, 218, 205, 212, 213, 206, 199, 215, 214, 216, 217, 219, 220, 207, 200, 201, 209, 204, 212, 208, 213, 222, 215, 221, 211, 214, 223, 226, 216, 227, 219, 228, 227, 218, 217, 221, 229, 222, 230, 232, 226, 231, 227, 220, 234, 233, 235, 238, 228, 223, 236, 241, 237, 239, 248, 230, 245, 231, 233, 240, 247, 249, 236, 241, 238, 244, 246, 258, 229, 234, 239, 236, 232, 237, 245, 233, 240, 235, 246, 249, 252, 244, 251, 254, 246, 239, 248, 255, 251, 233, 257, 247, 253, 253, 258, 260, 254, 261, 264, 265, 251, 252, 266, 255, 268, 269, 270, 257, 251, 271, 261, 264, 265, 274, 277, 272, 278, 273, 255, 270, 275, 279, 1217, 283, 287, 711, 253, 711, 272, 276, 260, 274, 280, 278, 266, 266, 268, 271, 273, 269, 272, 276, 284, 276, 280, 277, 272, 289, 279, 292, 275, 293, 275, 283, 284, 286, 286, 286, 286, 272, 287, 288, 288, 288, 288, 291, 291, 291, 291, 294, 295, 293, 296, 299, 301, 298, 302, 297, 300, 292, 304, 307, 303, 289, 305, 317, 294, 295, 309, 297, 310, 297, 313, 302, 297, 314, 306, 304, 296, 297, 298, 303, 300, 315, 301, 318, 299, 305, 306, 316, 317, 309, 307, 319, 320, 325, 314, 306, 315, 326, 306, 316, 310, 327, 328, 331, 319, 332, 333, 313, 306, 320, 329, 334, 335, 337, 336, 331, 344, 340, 341, 343, 318, 339, 346, 333, 348, 351, 334, 326, 328, 327, 325, 336, 354, 339, 329, 346, 344, 332, 355, 335, 357, 341, 356, 358, 360, 348, 337, 340, 362, 354, 343, 355, 361, 365, 364, 366, 367, 351, 370, 356, 368, 369, 371, 357, 374, 372, 365, 373, 380, 362, 358, 381, 382, 383, 360, 370, 375, 375, 361, 364, 374, 368, 369, 371, 375, 373, 384, 367, 372, 389, 366, 390, 381, 393, 394, 396, 383, 373, 395, 395, 401, 380, 382, 398, 403, 399, 400, 396, 402, 404, 389, 394, 406, 407, 409, 395, 384, 410, 1214, 412, 432, 390, 411, 429, 398, 393, 399, 400, 405, 402, 404, 410, 401, 410, 398, 411, 403, 431, 433, 406, 435, 405, 405, 405, 412, 407, 409, 411, 417, 422, 429, 417, 422, 434, 437, 417, 422, 432, 411, 436, 438, 439, 441, 433, 435, 440, 442, 445, 431, 443, 444, 450, 438, 448, 452, 446, 447, 449, 1212, 460, 434, 434, 455, 462, 434, 436, 437, 453, 440, 442, 446, 446, 460, 439, 449, 443, 444, 454, 445, 441, 448, 447, 450, 442, 453, 452, 456, 457, 455, 454, 458, 462, 463, 459, 461, 464, 465, 466, 467, 468, 469, 471, 458, 456, 457, 459, 461, 472, 473, 474, 475, 476, 465, 467, 477, 478, 482, 471, 463, 472, 468, 481, 483, 483, 473, 475, 485, 464, 476, 484, 469, 486, 478, 488, 466, 481, 487, 490, 472, 491, 492, 474, 493, 482, 484, 494, 477, 495, 496, 497, 485, 498, 499, 487, 500, 502, 501, 494, 503, 488, 510, 492, 511, 486, 495, 509, 498, 504, 497, 490, 503, 491, 496, 504, 493, 505, 499, 501, 509, 500, 512, 513, 502, 505, 517, 518, 510, 519, 524, 520, 526, 528, 527, 529, 531, 532, 511, 512, 533, 537, 540, 541, 518, 520, 519, 534, 526, 535, 513, 527, 536, 517, 529, 533, 541, 528, 543, 534, 531, 535, 540, 544, 536, 524, 545, 546, 537, 550, 532, 547, 549, 552, 548, 546, 551, 547, 549, 553, 544, 543, 548, 554, 551, 555, 556, 557, 558, 559, 560, 628, 562, 545, 561, 570, 567, 553, 563, 556, 554, 550, 564, 560, 552, 628, 565, 557, 561, 567, 563, 555, 562, 561, 564, 558, 566, 561, 565, 568, 571, 559, 570, 572, 561, 573, 574, 575, 566, 577, 578, 579, 580, 582, 566, 568, 572, 571, 573, 575, 581, 574, 586, 589, 579, 580, 583, 584, 587, 588, 591, 579, 581, 590, 592, 579, 586, 593, 597, 582, 578, 586, 577, 583, 589, 586, 588, 584, 595, 598, 590, 594, 586, 591, 596, 586, 599, 601, 602, 600, 587, 592, 606, 594, 593, 595, 598, 603, 607, 596, 597, 600, 610, 613, 614, 602, 615, 599, 617, 616, 603, 619, 594, 618, 620, 622, 621, 614, 615, 606, 623, 625, 624, 626, 601, 627, 618, 632, 634, 607, 616, 633, 619, 621, 617, 610, 636, 627, 620, 624, 613, 622, 635, 640, 642, 634, 643, 626, 625, 647, 633, 632, 623, 650, 635, 651, 652, 654, 653, 656, 657, 658, 659, 662, 664, 660, 665, 666, 636, 640, 647, 675, 651, 643, 642, 653, 672, 650, 674, 677, 676, 664, 652, 666, 680, 654, 679, 678, 672, 656, 657, 658, 660, 681, 659, 662, 682, 675, 683, 674, 678, 679, 684, 665, 676, 680, 685, 687, 688, 677, 686, 689, 681, 690, 691, 692, 693, 694, 695, 684, 682, 696, 686, 685, 698, 697, 701, 699, 683, 703, 687, 688, 689, 704, 690, 691, 705, 693, 706, 707, 696, 697, 709, 694, 708, 710, 704, 692, 699, 712, 713, 701, 695, 716, 714, 707, 698, 708, 710, 715, 717, 718, 703, 705, 719, 724, 720, 725, 709, 721, 706, 714, 722, 712, 723, 727, 715, 728, 724, 731, 713, 717, 720, 730, 716, 733, 721, 734, 725, 737, 738, 719, 749, 718, 741, 743, 731, 744, 722, 745, 723, 746, 727, 734, 728, 754, 748, 756, 730, 749, 752, 755, 757, 733, 787, 760, 737, 746, 744, 743, 762, 754, 738, 761, 741, 769, 745, 752, 755, 773, 744, 748, 757, 775, 777, 761, 780, 781, 756, 760, 782, 762, 784, 785, 788, 773, 789, 777, 790, 792, 775, 787, 769, 780, 781, 791, 785, 782, 793, 794, 796, 795, 797, 789, 798, 799, 800, 801, 784, 795, 802, 806, 794, 790, 803, 788, 798, 797, 807, 791, 804, 792, 805, 796, 808, 809, 802, 810, 799, 811, 801, 803, 812, 813, 814, 793, 815, 804, 816, 805, 810, 818, 819, 800, 820, 806, 821, 811, 808, 822, 813, 814, 807, 812, 816, 823, 825, 820, 809, 824, 828, 829, 830, 815, 831, 833, 836, 821, 819, 823, 832, 835, 824, 818, 837, 822, 838, 839, 836, 840, 831, 841, 825, 828, 842, 830, 843, 832, 844, 839, 847, 845, 833, 849, 838, 850, 851, 835, 829, 852, 841, 854, 853, 855, 856, 844, 857, 847, 850, 858, 842, 837, 840, 851, 859, 852, 843, 845, 853, 857, 860, 856, 854, 862, 858, 849, 865, 866, 867, 855, 859, 869, 873, 875, 876, 877, 878, 860, 879, 880, 890, 891, 887, 865, 867, 894, 900, 892, 875, 886, 1203, 866, 901, 891, 877, 878, 880, 879, 862, 887, 894, 899, 893, 869, 873, 890, 876, 883, 883, 883, 883, 883, 883, 883, 883, 893, 886, 883, 892, 895, 896, 897, 898, 900, 904, 905, 906, 899, 907, 901, 908, 895, 896, 897, 898, 910, 911, 913, 912, 918, 914, 904, 915, 916, 920, 908, 917, 919, 927, 907, 923, 928, 906, 912, 930, 905, 914, 913, 915, 917, 920, 919, 923, 918, 924, 910, 911, 925, 926, 929, 916, 932, 933, 934, 935, 930, 924, 928, 927, 925, 926, 929, 937, 936, 938, 940, 942, 939, 946, 948, 944, 949, 932, 933, 947, 950, 953, 956, 962, 937, 935, 936, 939, 944, 946, 934, 947, 964, 965, 953, 949, 938, 966, 967, 956, 940, 942, 968, 962, 979, 981, 984, 985, 982, 986, 948, 1196, 950, 994, 987, 990, 989, 999, 966, 967, 979, 988, 996, 968, 964, 982, 965, 997, 990, 1000, 994, 1002, 986, 1004, 985, 1006, 981, 987, 984, 989, 1007, 996, 988, 1008, 997, 1011, 1012, 1019, 999, 1014, 1013, 1015, 1006, 1017, 1021, 1025, 1000, 1018, 1002, 1004, 1020, 1023, 1022, 1015, 1007, 1026, 1019, 1028, 1011, 1012, 1008, 1013, 1014, 1018, 1021, 1022, 1020, 1017, 1029, 1031, 1033, 1035, 1023, 1037, 1039, 1039, 1042, 1043, 1025, 1049, 1044, 1045, 1054, 1195, 1051, 1026, 1047, 1033, 1050, 1028, 1069, 1194, 1037, 1192, 1052, 1053, 1031, 1055, 1080, 1035, 1029, 1031, 1061, 1047, 1043, 1049, 1042, 1044, 1045, 1050, 1051, 1052, 1053, 1056, 1055, 1062, 1054, 1063, 1061, 1065, 1066, 1083, 1067, 1068, 1069, 1070, 1072, 1056, 1077, 1063, 1071, 1078, 1079, 1062, 1073, 1080, 1065, 1084, 1066, 1067, 1068, 1082, 1070, 1072, 1071, 1088, 1073, 1092, 1091, 1071, 1078, 1093, 1094, 1071, 1082, 1096, 1083, 1097, 1088, 1099, 1077, 1098, 1100, 1102, 1079, 1091, 1103, 1105, 1096, 1104, 1109, 1108, 1106, 1092, 1084, 1110, 1112, 1093, 1094, 1098, 1113, 1114, 1116, 1117, 1097, 1105, 1104, 1106, 1106, 1108, 1103, 1115, 1118, 1121, 1123, 1124, 1099, 1134, 1117, 1100, 1102, 1132, 1125, 1133, 1113, 1138, 1141, 1109, 1115, 1147, 1142, 1114, 1110, 1112, 1139, 1132, 1116, 1125, 1134, 1148, 1123, 1121, 1138, 1124, 1149, 1118, 1139, 1142, 1150, 1133, 1151, 1154, 1147, 1152, 1141, 1153, 1155, 1156, 1159, 1161, 1163, 1170, 1164, 1165, 1171, 1150, 1174, 1149, 1154, 1168, 1168, 1173, 1166, 1155, 1167, 1163, 1148, 1151, 1161, 1168, 1171, 1149, 1159, 1152, 1166, 1170, 1167, 1153, 1169, 1169, 1172, 1179, 1173, 1181, 1156, 1164, 1174, 1165, 1169, 1183, 1184, 1185, 1186, 1187, 1191, 1193, 1201, 1172, 1179, 1197, 1198, 1199, 1200, 1181, 1186, 1187, 1202, 1204, 1206, 1207, 1183, 1191, 1208, 1184, 1185, 1198, 1197, 1201, 1199, 1200, 1209, 1210, 1193, 1206, 1211, 1213, 1207, 1202, 1215, 1215, 1216, 1216, 1190, 1204, 1189, 1188, 1182, 1180, 1215, 1178, 1216, 1176, 1175, 1162, 1160, 1158, 1157, 1146, 1213, 1208, 1145, 1144, 1143, 1140, 1137, 1210, 1136, 1209, 1211, 1226, 1226, 1227, 1227, 1227, 1228, 1228, 1228, 1135, 1131, 1130, 1129, 1128, 1127, 1126, 1122, 1120, 1119, 1111, 1107, 1101, 1095, 1090, 1089, 1086, 1085, 1081, 1076, 1075, 1074, 1064, 1060, 1059, 1058, 1057, 1048, 1041, 1040, 1036, 1034, 1032, 1030, 1027, 1024, 1016, 1005, 1003, 1001, 998, 995, 993, 992, 991, 983, 980, 978, 977, 976, 975, 974, 973, 972, 971, 970, 969, 961, 960, 959, 957, 955, 954, 952, 951, 945, 943, 941, 931, 922, 921, 909, 903, 902, 889, 888, 885, 884, 882, 881, 874, 872, 871, 868, 864, 863, 861, 846, 834, 827, 826, 817, 786, 783, 779, 778, 776, 774, 772, 771, 770, 768, 767, 764, 763, 759, 758, 753, 751, 750, 747, 742, 736, 732, 729, 726, 702, 673, 671, 670, 669, 668, 667, 663, 661, 655, 649, 648, 646, 645, 644, 641, 639, 638, 637, 631, 630, 629, 612, 611, 609, 608, 605, 604, 585, 576, 569, 542, 539, 530, 525, 523, 522, 521, 516, 515, 514, 506, 489, 480, 479, 470, 451, 408, 397, 392, 391, 388, 387, 386, 385, 378, 363, 359, 353, 352, 350, 349, 347, 345, 342, 338, 330, 312, 311, 308, 285, 282, 281, 263, 262, 259, 256, 250, 243, 242, 225, 224, 210, 203, 188, 184, 177, 164, 71, 69, 59, 58, 52, 47, 42, 40, 31, 25, 23, 6, 3, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224 } ; static yyconst flex_int16_t yy_rule_linenum[271] = { 0, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 118, 119, 120, 121, 122, 123, 125, 127, 128, 129, 131, 132, 133, 134, 135, 137, 138, 139, 140, 142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 267, 268, 269, 271, 272, 273, 274, 275, 277, 278, 279, 281, 283, 284, 285, 286, 287, 288, 289, 291, 293, 294, 295, 296, 297, 298, 299, 301, 302, 303, 305, 306, 307, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 333, 334, 335, 337, 338, 339, 340 } ; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "../s/bif.l" /****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the BIF file */ /* Run the bif.y file first through bison to generate the bif.tab.h file, which is included herein */ /* Then run this file through flex to generate the bif.yy.c source code */ #line 23 "../s/bif.l" #include #include "bifscanner.h" #include "bif.tab.hpp" #include "authentication.h" #include "encryption.h" typedef BIF::BisonParser::token tok; /* see http://www.lysator.liu.se/c/ANSI-C-grammar-l.html */ #line 36 "../s/bif.l" # define YY_USER_ACTION yylloc->columns (yyleng); #line 1523 "../bisonflex/bif.yy.cpp" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ #include /* %endif */ #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* %if-c-only Reentrant structure and macros (non-C++). */ /* %if-reentrant */ /* %if-c-only */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif End reentrant structures and macros. */ /* %if-bison-bridge */ /* %endif */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #endif /* %if-c-only */ /* %endif */ /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define ECHO LexerOutput( yytext, yyleng ) /* %endif */ #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ /* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ \ /* %if-c++-only C++ definition \ */\ if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); /* %endif */ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR /* %if-c-only */ /* %endif */ /* %if-c++-only */ #define YY_FATAL_ERROR(msg) LexerError( msg ) /* %endif */ #endif /* %if-tables-serialization structures and prototypes */ /* %not-for-header */ /* %ok-for-header */ /* %not-for-header */ /* %tables-yydmap generated elements */ /* %endif */ /* end tables serialization structures and prototypes */ /* %ok-for-header */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define YY_DECL int yyFlexLexer::yylex() /* %endif */ #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif /* %% [6.0] YY_RULE_SETUP definition goes here */ #define YY_RULE_SETUP \ YY_USER_ACTION /* %not-for-header */ /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; /* %% [7.0] user's declarations go here */ #line 39 "../s/bif.l" yylloc->step (); #line 1687 "../bisonflex/bif.yy.cpp" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyin = & std::cin; /* %endif */ if ( ! yyout ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyout = & std::cout; /* %endif */ if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { /* %% [8.0] yymore()-related code goes here */ yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; /* %% [9.0] code to set up and find next match goes here */ yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1225 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 1224 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: /* %% [10.0] code to find the action number goes here */ yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; /* %% [11.0] code for yylineno update goes here */ do_action: /* This label is used only to access EOF actions. */ /* %% [12.0] debug code goes here */ if ( yy_flex_debug ) { if ( yy_act == 0 ) std::cerr << "--scanner backing up\n"; else if ( yy_act < 271 ) std::cerr << "--accepting rule at line " << yy_rule_linenum[yy_act] << "(\"" << yytext << "\")\n"; else if ( yy_act == 271 ) std::cerr << "--accepting default rule (\"" << yytext << "\")\n"; else if ( yy_act == 272 ) std::cerr << "--(end of buffer or a NUL)\n"; else std::cerr << "--EOF (start condition " << YY_START << ")\n"; } switch ( yy_act ) { /* beginning of action switch */ /* %% [13.0] actions go here */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 45 "../s/bif.l" { comment(); } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 46 "../s/bif.l" yylloc->lines (1); yylloc->step (); YY_BREAK case 3: YY_RULE_SETUP #line 48 "../s/bif.l" return tok::BOOTLOADER; YY_BREAK case 4: YY_RULE_SETUP #line 49 "../s/bif.l" return tok::PRESIGN; YY_BREAK case 5: YY_RULE_SETUP #line 50 "../s/bif.l" return tok::AC; YY_BREAK case 6: YY_RULE_SETUP #line 51 "../s/bif.l" return tok::UDF_DATA; YY_BREAK case 7: YY_RULE_SETUP #line 52 "../s/bif.l" return tok::XIP_MODE; YY_BREAK case 8: YY_RULE_SETUP #line 53 "../s/bif.l" return tok::BOOT; YY_BREAK case 9: YY_RULE_SETUP #line 54 "../s/bif.l" return tok::USER; YY_BREAK case 10: YY_RULE_SETUP #line 55 "../s/bif.l" return tok::STATIC; YY_BREAK case 11: YY_RULE_SETUP #line 56 "../s/bif.l" return tok::NOAUTOSTART; YY_BREAK case 12: YY_RULE_SETUP #line 57 "../s/bif.l" return tok::MULTIBOOT; YY_BREAK case 13: YY_RULE_SETUP #line 58 "../s/bif.l" return tok::PROTECTED; YY_BREAK case 14: YY_RULE_SETUP #line 59 "../s/bif.l" return tok::ALIGNMENT; YY_BREAK case 15: YY_RULE_SETUP #line 60 "../s/bif.l" return tok::EARLY_HANDOFF; YY_BREAK case 16: YY_RULE_SETUP #line 61 "../s/bif.l" return tok::DELAY_HANDOFF; YY_BREAK case 17: YY_RULE_SETUP #line 62 "../s/bif.l" return tok::DELAY_LOAD; YY_BREAK case 18: YY_RULE_SETUP #line 63 "../s/bif.l" return tok::DELAY_AUTH; YY_BREAK case 19: YY_RULE_SETUP #line 64 "../s/bif.l" return tok::HIVEC; YY_BREAK case 20: YY_RULE_SETUP #line 65 "../s/bif.l" return tok::BLOCKS; YY_BREAK case 21: YY_RULE_SETUP #line 66 "../s/bif.l" return tok::AUTHBLOCKS; YY_BREAK case 22: YY_RULE_SETUP #line 67 "../s/bif.l" return tok::BIGENDIAN; YY_BREAK case 23: YY_RULE_SETUP #line 68 "../s/bif.l" return tok::A32_MODE; YY_BREAK case 24: YY_RULE_SETUP #line 69 "../s/bif.l" return tok::PARTITION; YY_BREAK case 25: YY_RULE_SETUP #line 70 "../s/bif.l" return tok::IMAGE; YY_BREAK case 26: YY_RULE_SETUP #line 71 "../s/bif.l" return tok::METAHEADER; YY_BREAK case 27: YY_RULE_SETUP #line 72 "../s/bif.l" return tok::BIF_SECTION; YY_BREAK case 28: YY_RULE_SETUP #line 73 "../s/bif.l" return tok::LOCKSTEP; YY_BREAK case 29: YY_RULE_SETUP #line 74 "../s/bif.l" return tok::INCLUDE; YY_BREAK case 30: YY_RULE_SETUP #line 75 "../s/bif.l" return tok::TCM_BOOT; YY_BREAK case 31: YY_RULE_SETUP #line 76 "../s/bif.l" return tok::OPTIONAL_DATA; YY_BREAK case 32: YY_RULE_SETUP #line 78 "../s/bif.l" yylval->number = tok::OFFSET; return tok::OFFSET; YY_BREAK case 33: YY_RULE_SETUP #line 79 "../s/bif.l" yylval->number = tok::RESERVE_LEGACY; return tok::RESERVE_LEGACY; YY_BREAK case 34: YY_RULE_SETUP #line 80 "../s/bif.l" yylval->number = tok::RESERVE; return tok::RESERVE; YY_BREAK case 35: YY_RULE_SETUP #line 81 "../s/bif.l" yylval->number = tok::LOAD; return tok::LOAD; YY_BREAK case 36: YY_RULE_SETUP #line 82 "../s/bif.l" yylval->number = tok::COPY; return tok::COPY; YY_BREAK case 37: YY_RULE_SETUP #line 83 "../s/bif.l" yylval->number = tok::STARTUP; return tok::STARTUP; YY_BREAK case 38: YY_RULE_SETUP #line 84 "../s/bif.l" yylval->number = tok::PARTITION_NUM; return tok::PARTITION_NUM; YY_BREAK case 39: YY_RULE_SETUP #line 85 "../s/bif.l" yylval->number = tok::INIT; return tok::INIT; YY_BREAK case 40: YY_RULE_SETUP #line 86 "../s/bif.l" yylval->number = tok::UDF_BH; return tok::UDF_BH; YY_BREAK case 41: YY_RULE_SETUP #line 87 "../s/bif.l" yylval->number = tok::AES_KEY_FILE; return tok::AES_KEY_FILE; YY_BREAK case 42: YY_RULE_SETUP #line 88 "../s/bif.l" yylval->number = tok::PPK_FILE; return tok::PPK_FILE; YY_BREAK case 43: YY_RULE_SETUP #line 89 "../s/bif.l" yylval->number = tok::PSK_FILE; return tok::PSK_FILE; YY_BREAK case 44: YY_RULE_SETUP #line 90 "../s/bif.l" yylval->number = tok::SPK_FILE; return tok::SPK_FILE; YY_BREAK case 45: YY_RULE_SETUP #line 91 "../s/bif.l" yylval->number = tok::SSK_FILE; return tok::SSK_FILE; YY_BREAK case 46: YY_RULE_SETUP #line 92 "../s/bif.l" yylval->number = tok::SPK_SIGNATURE_FILE; return tok::SPK_SIGNATURE_FILE; YY_BREAK case 47: YY_RULE_SETUP #line 93 "../s/bif.l" yylval->number = tok::BH_SIGNATURE_FILE; return tok::BH_SIGNATURE_FILE; YY_BREAK case 48: YY_RULE_SETUP #line 94 "../s/bif.l" yylval->number = tok::HEADER_SIGNATURE_FILE; return tok::HEADER_SIGNATURE_FILE; YY_BREAK case 49: YY_RULE_SETUP #line 95 "../s/bif.l" yylval->number = tok::BOOTVECTORS; return tok::BOOTVECTORS; YY_BREAK case 50: YY_RULE_SETUP #line 96 "../s/bif.l" yylval->number = tok::BOOTIMAGE; return tok::BOOTIMAGE; YY_BREAK case 51: YY_RULE_SETUP #line 97 "../s/bif.l" yylval->number = tok::PARENT_ID; return tok::PARENT_ID; YY_BREAK case 52: YY_RULE_SETUP #line 98 "../s/bif.l" yylval->number = tok::ID_CODE; return tok::ID_CODE; YY_BREAK case 53: YY_RULE_SETUP #line 99 "../s/bif.l" yylval->number = tok::EXT_ID_CODE; return tok::EXT_ID_CODE; YY_BREAK case 54: YY_RULE_SETUP #line 100 "../s/bif.l" yylval->number = tok::ID; return tok::ID; YY_BREAK case 55: YY_RULE_SETUP #line 101 "../s/bif.l" yylval->number = tok::NAME; return tok::NAME; YY_BREAK case 56: YY_RULE_SETUP #line 102 "../s/bif.l" yylval->number = tok::PFILE; return tok::PFILE; YY_BREAK case 57: YY_RULE_SETUP #line 103 "../s/bif.l" yylval->number = tok::BH_KEY_FILE; return tok::BH_KEY_FILE; YY_BREAK case 58: YY_RULE_SETUP #line 104 "../s/bif.l" yylval->number = tok::PUF_HELPER_FILE; return tok::PUF_HELPER_FILE; YY_BREAK case 59: YY_RULE_SETUP #line 105 "../s/bif.l" yylval->number = tok::PMUFW_IMAGE; return tok::PMUFW_IMAGE; YY_BREAK case 60: YY_RULE_SETUP #line 106 "../s/bif.l" yylval->number = tok::PMCDATA; return tok::PMCDATA; YY_BREAK case 61: YY_RULE_SETUP #line 107 "../s/bif.l" yylval->number = tok::BH_KEY_IV; return tok::BH_KEY_IV; YY_BREAK case 62: YY_RULE_SETUP #line 108 "../s/bif.l" yylval->number = tok::UNIQUE_ID; return tok::UNIQUE_ID; YY_BREAK case 63: YY_RULE_SETUP #line 109 "../s/bif.l" yylval->number = tok::PARENT_UNIQUE_ID; return tok::PARENT_UNIQUE_ID; YY_BREAK case 64: YY_RULE_SETUP #line 110 "../s/bif.l" yylval->number = tok::FUNCTION_ID; return tok::FUNCTION_ID; YY_BREAK case 65: YY_RULE_SETUP #line 111 "../s/bif.l" yylval->number = tok::PCR_NUMBER; return tok::PCR_NUMBER; YY_BREAK case 66: YY_RULE_SETUP #line 112 "../s/bif.l" yylval->number = tok::PCR_MEASUREMENT_INDEX; return tok::PCR_MEASUREMENT_INDEX; YY_BREAK case 67: YY_RULE_SETUP #line 113 "../s/bif.l" yylval->number = tok::IMAGE_STORE; return tok::IMAGE_STORE; YY_BREAK case 68: YY_RULE_SETUP #line 114 "../s/bif.l" yylval->number = tok::TCM_A_REGION; return tok::TCM_A_REGION; YY_BREAK case 69: YY_RULE_SETUP #line 115 "../s/bif.l" yylval->number = tok::TCM_B_REGION; return tok::TCM_B_REGION; YY_BREAK case 70: YY_RULE_SETUP #line 116 "../s/bif.l" yylval->number = tok::TCM_C_REGION; return tok::TCM_C_REGION; YY_BREAK case 71: YY_RULE_SETUP #line 118 "../s/bif.l" yylval->number = tok::BBRAM_KEK_IV; return tok::BBRAM_KEK_IV; YY_BREAK case 72: YY_RULE_SETUP #line 119 "../s/bif.l" yylval->number = tok::BH_KEK_IV; return tok::BH_KEK_IV; YY_BREAK case 73: YY_RULE_SETUP #line 120 "../s/bif.l" yylval->number = tok::EFUSE_KEK_IV; return tok::EFUSE_KEK_IV; YY_BREAK case 74: YY_RULE_SETUP #line 121 "../s/bif.l" yylval->number = tok::EFUSE_USER_KEK0_IV; return tok::EFUSE_USER_KEK0_IV; YY_BREAK case 75: YY_RULE_SETUP #line 122 "../s/bif.l" yylval->number = tok::EFUSE_USER_KEK1_IV; return tok::EFUSE_USER_KEK1_IV; YY_BREAK case 76: YY_RULE_SETUP #line 123 "../s/bif.l" yylval->number = tok::USER_KEYS; return tok::USER_KEYS; YY_BREAK case 77: YY_RULE_SETUP #line 125 "../s/bif.l" yylval->number = tok::FAMILY_KEY; return tok::FAMILY_KEY; YY_BREAK case 78: YY_RULE_SETUP #line 127 "../s/bif.l" return tok::ENCRYPTION; YY_BREAK case 79: YY_RULE_SETUP #line 128 "../s/bif.l" yylval->number = 0; return tok::NONE; YY_BREAK case 80: YY_RULE_SETUP #line 129 "../s/bif.l" yylval->number = Encryption::AES; return tok::ENCRVALUE; YY_BREAK case 81: YY_RULE_SETUP #line 131 "../s/bif.l" return tok::AUTHENTICATION; YY_BREAK case 82: YY_RULE_SETUP #line 132 "../s/bif.l" yylval->number = Authentication::RSA; return tok::AUTHVALUE; YY_BREAK case 83: YY_RULE_SETUP #line 133 "../s/bif.l" yylval->number = Authentication::ECDSA; return tok::AUTHVALUE; YY_BREAK case 84: YY_RULE_SETUP #line 134 "../s/bif.l" yylval->number = Authentication::ECDSA; return tok::AUTHVALUE; YY_BREAK case 85: YY_RULE_SETUP #line 135 "../s/bif.l" yylval->number = Authentication::ECDSAp521; return tok::AUTHVALUE; YY_BREAK case 86: YY_RULE_SETUP #line 137 "../s/bif.l" return tok::CHECKSUM; YY_BREAK case 87: YY_RULE_SETUP #line 138 "../s/bif.l" yylval->number = Checksum::MD5; return tok::CHECKSUMVALUE; YY_BREAK case 88: YY_RULE_SETUP #line 139 "../s/bif.l" yylval->number = Checksum::SHA2; return tok::CHECKSUMVALUE; YY_BREAK case 89: YY_RULE_SETUP #line 140 "../s/bif.l" yylval->number = Checksum::SHA3; return tok::CHECKSUMVALUE; YY_BREAK case 90: YY_RULE_SETUP #line 142 "../s/bif.l" return tok::PARTITION_OWNER; YY_BREAK case 91: YY_RULE_SETUP #line 143 "../s/bif.l" return tok::PARTITION_OWNER; YY_BREAK case 92: YY_RULE_SETUP #line 144 "../s/bif.l" yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; YY_BREAK case 93: YY_RULE_SETUP #line 145 "../s/bif.l" yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; YY_BREAK case 94: YY_RULE_SETUP #line 146 "../s/bif.l" yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; YY_BREAK case 95: YY_RULE_SETUP #line 147 "../s/bif.l" yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; YY_BREAK case 96: YY_RULE_SETUP #line 148 "../s/bif.l" yylval->number = PartitionOwner::FSBL; return tok::POWNERVALUE ; YY_BREAK case 97: YY_RULE_SETUP #line 149 "../s/bif.l" yylval->number = PartitionOwner::UBOOT; return tok::POWNERVALUE ; YY_BREAK case 98: YY_RULE_SETUP #line 151 "../s/bif.l" return tok::PARTITION_TYPE; YY_BREAK case 99: YY_RULE_SETUP #line 152 "../s/bif.l" return tok::PARTITION_TYPE; YY_BREAK case 100: YY_RULE_SETUP #line 153 "../s/bif.l" yylval->number = PartitionType::CONFIG_DATA_OBJ; return tok::PTYPEVALUE; YY_BREAK case 101: YY_RULE_SETUP #line 154 "../s/bif.l" yylval->number = PartitionType::RAW; return tok::PTYPEVALUE; YY_BREAK case 102: YY_RULE_SETUP #line 155 "../s/bif.l" yylval->number = PartitionType::CFI; return tok::PTYPEVALUE; YY_BREAK case 103: YY_RULE_SETUP #line 156 "../s/bif.l" yylval->number = PartitionType::CFI_GSC; return tok::PTYPEVALUE; YY_BREAK case 104: YY_RULE_SETUP #line 157 "../s/bif.l" yylval->number = PartitionType::SLR_BOOT; return tok::PTYPEVALUE; YY_BREAK case 105: YY_RULE_SETUP #line 158 "../s/bif.l" yylval->number = PartitionType::SLR_CONFIG; return tok::PTYPEVALUE; YY_BREAK case 106: YY_RULE_SETUP #line 159 "../s/bif.l" yylval->number = PartitionType::SLR_SLAVE; return tok::PTYPEVALUE; YY_BREAK case 107: YY_RULE_SETUP #line 160 "../s/bif.l" yylval->number = PartitionType::SLR_SLAVE_BOOT; return tok::PTYPEVALUE; YY_BREAK case 108: YY_RULE_SETUP #line 161 "../s/bif.l" yylval->number = PartitionType::SLR_SLAVE_CONFIG; return tok::PTYPEVALUE; YY_BREAK case 109: YY_RULE_SETUP #line 162 "../s/bif.l" yylval->number = PartitionType::ELF; return tok::PTYPEVALUE; YY_BREAK case 110: YY_RULE_SETUP #line 164 "../s/bif.l" yylval->number = tok::KEYSRC_ENCRYPTION; return tok::KEYSRC_ENCRYPTION; YY_BREAK case 111: YY_RULE_SETUP #line 165 "../s/bif.l" yylval->number = tok::KEYSRC_ENCRYPTION; return tok::KEYSRC_ENCRYPTION; YY_BREAK case 112: YY_RULE_SETUP #line 166 "../s/bif.l" yylval->number = KeySource::EfuseRedKey; return tok::KEY_SRC; YY_BREAK case 113: YY_RULE_SETUP #line 167 "../s/bif.l" yylval->number = KeySource::BbramRedKey; return tok::KEY_SRC; YY_BREAK case 114: YY_RULE_SETUP #line 168 "../s/bif.l" yylval->number = KeySource::EfuseRedKey; return tok::KEY_SRC; YY_BREAK case 115: YY_RULE_SETUP #line 169 "../s/bif.l" yylval->number = KeySource::EfuseBlkKey; return tok::KEY_SRC; YY_BREAK case 116: YY_RULE_SETUP #line 170 "../s/bif.l" yylval->number = KeySource::EfuseGryKey; return tok::KEY_SRC; YY_BREAK case 117: YY_RULE_SETUP #line 171 "../s/bif.l" yylval->number = KeySource::BbramRedKey; return tok::KEY_SRC; YY_BREAK case 118: YY_RULE_SETUP #line 172 "../s/bif.l" yylval->number = KeySource::BbramBlkKey; return tok::KEY_SRC; YY_BREAK case 119: YY_RULE_SETUP #line 173 "../s/bif.l" yylval->number = KeySource::BbramGryKey; return tok::KEY_SRC; YY_BREAK case 120: YY_RULE_SETUP #line 174 "../s/bif.l" yylval->number = KeySource::BhGryKey; return tok::KEY_SRC; YY_BREAK case 121: YY_RULE_SETUP #line 175 "../s/bif.l" yylval->number = KeySource::BhBlkKey; return tok::KEY_SRC; YY_BREAK case 122: YY_RULE_SETUP #line 176 "../s/bif.l" yylval->number = KeySource::UserKey0; return tok::KEY_SRC; YY_BREAK case 123: YY_RULE_SETUP #line 177 "../s/bif.l" yylval->number = KeySource::UserKey1; return tok::KEY_SRC; YY_BREAK case 124: YY_RULE_SETUP #line 178 "../s/bif.l" yylval->number = KeySource::UserKey2; return tok::KEY_SRC; YY_BREAK case 125: YY_RULE_SETUP #line 179 "../s/bif.l" yylval->number = KeySource::UserKey3; return tok::KEY_SRC; YY_BREAK case 126: YY_RULE_SETUP #line 180 "../s/bif.l" yylval->number = KeySource::UserKey4; return tok::KEY_SRC; YY_BREAK case 127: YY_RULE_SETUP #line 181 "../s/bif.l" yylval->number = KeySource::UserKey5; return tok::KEY_SRC; YY_BREAK case 128: YY_RULE_SETUP #line 182 "../s/bif.l" yylval->number = KeySource::UserKey6; return tok::KEY_SRC; YY_BREAK case 129: YY_RULE_SETUP #line 183 "../s/bif.l" yylval->number = KeySource::UserKey7; return tok::KEY_SRC; YY_BREAK case 130: YY_RULE_SETUP #line 184 "../s/bif.l" yylval->number = KeySource::EfuseUserKey0; return tok::KEY_SRC; YY_BREAK case 131: YY_RULE_SETUP #line 185 "../s/bif.l" yylval->number = KeySource::EfuseUserBlkKey0; return tok::KEY_SRC; YY_BREAK case 132: YY_RULE_SETUP #line 186 "../s/bif.l" yylval->number = KeySource::EfuseUserGryKey0; return tok::KEY_SRC; YY_BREAK case 133: YY_RULE_SETUP #line 187 "../s/bif.l" yylval->number = KeySource::EfuseUserKey1; return tok::KEY_SRC; YY_BREAK case 134: YY_RULE_SETUP #line 188 "../s/bif.l" yylval->number = KeySource::EfuseUserBlkKey1; return tok::KEY_SRC; YY_BREAK case 135: YY_RULE_SETUP #line 189 "../s/bif.l" yylval->number = KeySource::EfuseUserGryKey1; return tok::KEY_SRC; YY_BREAK case 136: YY_RULE_SETUP #line 190 "../s/bif.l" yylval->number = KeySource::BhKupKey; return tok::KEY_SRC; YY_BREAK case 137: YY_RULE_SETUP #line 192 "../s/bif.l" yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; YY_BREAK case 138: YY_RULE_SETUP #line 193 "../s/bif.l" yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; YY_BREAK case 139: YY_RULE_SETUP #line 194 "../s/bif.l" yylval->number = tok::FSBL_CONFIG; return tok::FSBL_CONFIG; YY_BREAK case 140: YY_RULE_SETUP #line 195 "../s/bif.l" yylval->number = Core::R5Single; return tok::CORE; YY_BREAK case 141: YY_RULE_SETUP #line 196 "../s/bif.l" yylval->number = Core::A53Singlex32; return tok::CORE; YY_BREAK case 142: YY_RULE_SETUP #line 197 "../s/bif.l" yylval->number = Core::A53Singlex32; return tok::CORE; YY_BREAK case 143: YY_RULE_SETUP #line 198 "../s/bif.l" yylval->number = Core::A53Singlex64; return tok::CORE; YY_BREAK case 144: YY_RULE_SETUP #line 199 "../s/bif.l" yylval->number = Core::A53Singlex64; return tok::CORE; YY_BREAK case 145: YY_RULE_SETUP #line 200 "../s/bif.l" yylval->number = Core::R5Dual; return tok::CORE; YY_BREAK case 146: YY_RULE_SETUP #line 201 "../s/bif.l" yylval->number = BhRsa::BhRsaEnable; return tok::BH_RSA; YY_BREAK case 147: YY_RULE_SETUP #line 202 "../s/bif.l" yylval->number = AuthHash::Sha2; return tok::AUTH_HASH; YY_BREAK case 148: YY_RULE_SETUP #line 203 "../s/bif.l" yylval->number = PufHdLoc::PUFinBH; return tok::PUFHD_LOC; YY_BREAK case 149: YY_RULE_SETUP #line 204 "../s/bif.l" yylval->number = AuthOnly::Enabled; return tok::AUTH_ONLY; YY_BREAK case 150: YY_RULE_SETUP #line 205 "../s/bif.l" yylval->number = OptKey::OptKeyinSecHdr; return tok::OPT_KEY; YY_BREAK case 151: YY_RULE_SETUP #line 206 "../s/bif.l" yylval->number = PufMode::PUF4K; return tok::PUF4KMODE; YY_BREAK case 152: YY_RULE_SETUP #line 207 "../s/bif.l" yylval->number = tok::SHUTTER; return tok::SHUTTER; YY_BREAK case 153: YY_RULE_SETUP #line 208 "../s/bif.l" yylval->number = tok::PUFROSWAP; return tok::PUFROSWAP; YY_BREAK case 154: YY_RULE_SETUP #line 209 "../s/bif.l" yylval->number = DpaCM::DpaCMEnable; return tok::DPA_CM; YY_BREAK case 155: YY_RULE_SETUP #line 210 "../s/bif.l" yylval->number = tok::DICE; return tok::DICE; YY_BREAK case 156: YY_RULE_SETUP #line 211 "../s/bif.l" yylval->number = tok::SMAP_WIDTH; return tok::SMAP_WIDTH; YY_BREAK case 157: YY_RULE_SETUP #line 212 "../s/bif.l" yylval->number = tok::BYPASS_IDCODE_CHECK; return tok::BYPASS_IDCODE_CHECK; YY_BREAK case 158: YY_RULE_SETUP #line 213 "../s/bif.l" yylval->number = tok::A_HWROT; return tok::A_HWROT; YY_BREAK case 159: YY_RULE_SETUP #line 214 "../s/bif.l" yylval->number = tok::S_HWROT; return tok::S_HWROT; YY_BREAK case 160: YY_RULE_SETUP #line 216 "../s/bif.l" return tok::BOOT_DEVICE; YY_BREAK case 161: YY_RULE_SETUP #line 217 "../s/bif.l" yylval->number = tok::ADDRESS; return tok::ADDRESS; YY_BREAK case 162: YY_RULE_SETUP #line 218 "../s/bif.l" yylval->number = BootDevice::QSPI32; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 163: YY_RULE_SETUP #line 219 "../s/bif.l" yylval->number = BootDevice::QSPI24; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 164: YY_RULE_SETUP #line 220 "../s/bif.l" yylval->number = BootDevice::NAND; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 165: YY_RULE_SETUP #line 221 "../s/bif.l" yylval->number = BootDevice::SD0; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 166: YY_RULE_SETUP #line 222 "../s/bif.l" yylval->number = BootDevice::SD1; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 167: YY_RULE_SETUP #line 223 "../s/bif.l" yylval->number = BootDevice::SDLS; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 168: YY_RULE_SETUP #line 224 "../s/bif.l" yylval->number = BootDevice::MMC; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 169: YY_RULE_SETUP #line 225 "../s/bif.l" yylval->number = BootDevice::USB; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 170: YY_RULE_SETUP #line 226 "../s/bif.l" yylval->number = BootDevice::ETHERNET; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 171: YY_RULE_SETUP #line 227 "../s/bif.l" yylval->number = BootDevice::PCIE; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 172: YY_RULE_SETUP #line 228 "../s/bif.l" yylval->number = BootDevice::SATA; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 173: YY_RULE_SETUP #line 229 "../s/bif.l" yylval->number = BootDevice::OSPI; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 174: YY_RULE_SETUP #line 230 "../s/bif.l" yylval->number = BootDevice::SMAP; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 175: YY_RULE_SETUP #line 231 "../s/bif.l" yylval->number = BootDevice::SBI; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 176: YY_RULE_SETUP #line 232 "../s/bif.l" yylval->number = BootDevice::SD0RAW; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 177: YY_RULE_SETUP #line 233 "../s/bif.l" yylval->number = BootDevice::SD1RAW; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 178: YY_RULE_SETUP #line 234 "../s/bif.l" yylval->number = BootDevice::SDLSRAW; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 179: YY_RULE_SETUP #line 235 "../s/bif.l" yylval->number = BootDevice::MMCRAW; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 180: YY_RULE_SETUP #line 236 "../s/bif.l" yylval->number = BootDevice::MMC0; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 181: YY_RULE_SETUP #line 237 "../s/bif.l" yylval->number = BootDevice::MMC0RAW; return tok::BOOT_DEVICE_TYPE ; YY_BREAK case 182: YY_RULE_SETUP #line 239 "../s/bif.l" return tok::DEST_CPU; YY_BREAK case 183: YY_RULE_SETUP #line 240 "../s/bif.l" return tok::DEST_CPU; YY_BREAK case 184: YY_RULE_SETUP #line 241 "../s/bif.l" yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; YY_BREAK case 185: YY_RULE_SETUP #line 242 "../s/bif.l" yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; YY_BREAK case 186: YY_RULE_SETUP #line 243 "../s/bif.l" yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; YY_BREAK case 187: YY_RULE_SETUP #line 244 "../s/bif.l" yylval->number = DestinationCPU::A53_0; return tok::DEST_CPU_TYPE; YY_BREAK case 188: YY_RULE_SETUP #line 245 "../s/bif.l" yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; YY_BREAK case 189: YY_RULE_SETUP #line 246 "../s/bif.l" yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; YY_BREAK case 190: YY_RULE_SETUP #line 247 "../s/bif.l" yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; YY_BREAK case 191: YY_RULE_SETUP #line 248 "../s/bif.l" yylval->number = DestinationCPU::A53_1; return tok::DEST_CPU_TYPE; YY_BREAK case 192: YY_RULE_SETUP #line 249 "../s/bif.l" yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; YY_BREAK case 193: YY_RULE_SETUP #line 250 "../s/bif.l" yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; YY_BREAK case 194: YY_RULE_SETUP #line 251 "../s/bif.l" yylval->number = DestinationCPU::A53_2; return tok::DEST_CPU_TYPE; YY_BREAK case 195: YY_RULE_SETUP #line 252 "../s/bif.l" yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; YY_BREAK case 196: YY_RULE_SETUP #line 253 "../s/bif.l" yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; YY_BREAK case 197: YY_RULE_SETUP #line 254 "../s/bif.l" yylval->number = DestinationCPU::A53_3; return tok::DEST_CPU_TYPE; YY_BREAK case 198: YY_RULE_SETUP #line 255 "../s/bif.l" yylval->number = DestinationCPU::R5_0; return tok::DEST_CPU_TYPE; YY_BREAK case 199: YY_RULE_SETUP #line 256 "../s/bif.l" yylval->number = DestinationCPU::R5_0; return tok::DEST_CPU_TYPE; YY_BREAK case 200: YY_RULE_SETUP #line 257 "../s/bif.l" yylval->number = DestinationCPU::R5_1; return tok::DEST_CPU_TYPE; YY_BREAK case 201: YY_RULE_SETUP #line 258 "../s/bif.l" yylval->number = DestinationCPU::R5_1; return tok::DEST_CPU_TYPE; YY_BREAK case 202: YY_RULE_SETUP #line 259 "../s/bif.l" yylval->number = DestinationCPU::R5_lockstep; return tok::DEST_CPU_TYPE; YY_BREAK case 203: YY_RULE_SETUP #line 260 "../s/bif.l" yylval->number = DestinationCPU::PMU; return tok::DEST_CPU_TYPE; YY_BREAK case 204: YY_RULE_SETUP #line 261 "../s/bif.l" yylval->number = DestinationCPU::PMU; return tok::DEST_CPU_TYPE; YY_BREAK case 205: YY_RULE_SETUP #line 262 "../s/bif.l" yylval->number = DestinationCPU::AIE; return tok::DEST_CPU_TYPE; YY_BREAK case 206: YY_RULE_SETUP #line 263 "../s/bif.l" yylval->number = tok::CLUSTER_NUM; return tok::CLUSTER_NUM; YY_BREAK case 207: YY_RULE_SETUP #line 265 "../s/bif.l" return tok::DEST_DEVICE; YY_BREAK case 208: YY_RULE_SETUP #line 266 "../s/bif.l" yylval->number = DestinationDevice::DEST_DEV_PS; return tok::DEST_DEVICE_TYPE; YY_BREAK case 209: YY_RULE_SETUP #line 267 "../s/bif.l" yylval->number = DestinationDevice::DEST_DEV_PL; return tok::DEST_DEVICE_TYPE; YY_BREAK case 210: YY_RULE_SETUP #line 268 "../s/bif.l" yylval->number = DestinationDevice::DEST_DEV_PMU; return tok::DEST_DEVICE_TYPE; YY_BREAK case 211: YY_RULE_SETUP #line 269 "../s/bif.l" yylval->number = DestinationDevice::DEST_DEV_XIP; return tok::DEST_DEVICE_TYPE; YY_BREAK case 212: YY_RULE_SETUP #line 271 "../s/bif.l" return tok::EXCEPTION_LEVEL; YY_BREAK case 213: YY_RULE_SETUP #line 272 "../s/bif.l" yylval->number = ExceptionLevel::EL0; return tok::EXCEPTION_LEVEL_TYPE; YY_BREAK case 214: YY_RULE_SETUP #line 273 "../s/bif.l" yylval->number = ExceptionLevel::EL1; return tok::EXCEPTION_LEVEL_TYPE; YY_BREAK case 215: YY_RULE_SETUP #line 274 "../s/bif.l" yylval->number = ExceptionLevel::EL2; return tok::EXCEPTION_LEVEL_TYPE; YY_BREAK case 216: YY_RULE_SETUP #line 275 "../s/bif.l" yylval->number = ExceptionLevel::EL3; return tok::EXCEPTION_LEVEL_TYPE; YY_BREAK case 217: YY_RULE_SETUP #line 277 "../s/bif.l" return tok::TRUSTZONE; YY_BREAK case 218: YY_RULE_SETUP #line 278 "../s/bif.l" yylval->number = TrustZone::Secure; return tok::TRUSTZONE_TYPE; YY_BREAK case 219: YY_RULE_SETUP #line 279 "../s/bif.l" yylval->number = TrustZone::NonSecure; return tok::TRUSTZONE_TYPE; YY_BREAK case 220: YY_RULE_SETUP #line 281 "../s/bif.l" yylval->number = tok::SLR_NUM; return tok::SLR_NUM; YY_BREAK case 221: YY_RULE_SETUP #line 283 "../s/bif.l" yylval->number = tok::AUTH_PARAMS; return tok::AUTH_PARAMS; YY_BREAK case 222: YY_RULE_SETUP #line 284 "../s/bif.l" yylval->number = tok::PPK_SELECT; return tok::PPK_SELECT; YY_BREAK case 223: YY_RULE_SETUP #line 285 "../s/bif.l" yylval->number = tok::SPK_SELECT; return tok::SPK_SELECT; YY_BREAK case 224: YY_RULE_SETUP #line 286 "../s/bif.l" yylval->number = SpkSelect::SPK_eFUSE; return tok::SPKSELECT; YY_BREAK case 225: YY_RULE_SETUP #line 287 "../s/bif.l" yylval->number = SpkSelect::USER_eFUSE; return tok::SPKSELECT; YY_BREAK case 226: YY_RULE_SETUP #line 288 "../s/bif.l" yylval->number = tok::SPK_ID; return tok::SPK_ID; YY_BREAK case 227: YY_RULE_SETUP #line 289 "../s/bif.l" return tok::HEADER_AUTH; YY_BREAK case 228: YY_RULE_SETUP #line 291 "../s/bif.l" yylval->number = tok::REVOKE_ID; return tok::REVOKE_ID; YY_BREAK case 229: YY_RULE_SETUP #line 293 "../s/bif.l" yylval->number = tok::SPLIT; return tok::SPLIT; YY_BREAK case 230: YY_RULE_SETUP #line 294 "../s/bif.l" yylval->number = tok::SPLIT_MODE; return tok::SPLIT_MODE; YY_BREAK case 231: YY_RULE_SETUP #line 295 "../s/bif.l" yylval->number = SplitMode::SlaveMode; return tok::SPLITMODE; YY_BREAK case 232: YY_RULE_SETUP #line 296 "../s/bif.l" yylval->number = SplitMode::Normal; return tok::SPLITMODE; YY_BREAK case 233: YY_RULE_SETUP #line 297 "../s/bif.l" yylval->number = tok::SPLIT_FMT; return tok::SPLIT_FMT; YY_BREAK case 234: YY_RULE_SETUP #line 298 "../s/bif.l" return tok::MCS; YY_BREAK case 235: YY_RULE_SETUP #line 299 "../s/bif.l" return tok::BIN; YY_BREAK case 236: YY_RULE_SETUP #line 301 "../s/bif.l" yylval->number = tok::AUTHJTAG_CONFIG; return tok::AUTHJTAG_CONFIG; YY_BREAK case 237: YY_RULE_SETUP #line 302 "../s/bif.l" yylval->number = tok::DEVICE_DNA; return tok::DEVICE_DNA; YY_BREAK case 238: YY_RULE_SETUP #line 303 "../s/bif.l" yylval->number = tok::JTAG_TIMEOUT; return tok::JTAG_TIMEOUT; YY_BREAK case 239: YY_RULE_SETUP #line 305 "../s/bif.l" yylval->number=atoi(yytext); return tok::DECVALUE; YY_BREAK case 240: YY_RULE_SETUP #line 306 "../s/bif.l" yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; YY_BREAK case 241: YY_RULE_SETUP #line 307 "../s/bif.l" yylval->string=strdup(yytext); return tok::HEXWORD; YY_BREAK case 242: YY_RULE_SETUP #line 309 "../s/bif.l" return tok::COLON; YY_BREAK case 243: YY_RULE_SETUP #line 310 "../s/bif.l" return tok::SEMICOLON; YY_BREAK case 244: YY_RULE_SETUP #line 311 "../s/bif.l" return tok::EQUAL; YY_BREAK case 245: YY_RULE_SETUP #line 312 "../s/bif.l" return tok::COMMA; YY_BREAK case 246: YY_RULE_SETUP #line 313 "../s/bif.l" return tok::OBRACKET; YY_BREAK case 247: YY_RULE_SETUP #line 314 "../s/bif.l" return tok::EBRACKET; YY_BREAK case 248: YY_RULE_SETUP #line 315 "../s/bif.l" return tok::OBRACE; YY_BREAK case 249: YY_RULE_SETUP #line 316 "../s/bif.l" return tok::EBRACE; YY_BREAK case 250: YY_RULE_SETUP #line 317 "../s/bif.l" return tok::LPAREN; YY_BREAK case 251: YY_RULE_SETUP #line 318 "../s/bif.l" return tok::RPAREN; YY_BREAK case 252: YY_RULE_SETUP #line 319 "../s/bif.l" return tok::ASTERISK; YY_BREAK case 253: YY_RULE_SETUP #line 321 "../s/bif.l" return tok::PLUS; YY_BREAK case 254: YY_RULE_SETUP #line 322 "../s/bif.l" return tok::MINUS; YY_BREAK case 255: YY_RULE_SETUP #line 323 "../s/bif.l" return tok::LSHIFT; YY_BREAK case 256: YY_RULE_SETUP #line 324 "../s/bif.l" return tok::RSHIFT; YY_BREAK case 257: YY_RULE_SETUP #line 325 "../s/bif.l" return tok::MULT; YY_BREAK case 258: YY_RULE_SETUP #line 326 "../s/bif.l" return tok::DIVIDE; YY_BREAK case 259: YY_RULE_SETUP #line 327 "../s/bif.l" return tok::MODULO; YY_BREAK case 260: YY_RULE_SETUP #line 328 "../s/bif.l" return tok::NEGATION; YY_BREAK case 261: YY_RULE_SETUP #line 329 "../s/bif.l" return tok::AND; YY_BREAK case 262: YY_RULE_SETUP #line 330 "../s/bif.l" return tok::OR; YY_BREAK case 263: YY_RULE_SETUP #line 331 "../s/bif.l" return tok::XOR; YY_BREAK case 264: YY_RULE_SETUP #line 333 "../s/bif.l" yylval->string=strdup(yytext); return tok::WORD; YY_BREAK case 265: YY_RULE_SETUP #line 334 "../s/bif.l" yylval->string=strdup(yytext); return tok::FILENAME; YY_BREAK case 266: YY_RULE_SETUP #line 335 "../s/bif.l" yylval->string=strdup(yytext+1); yylval->string[strlen(yytext)-2]=0; return tok::QFILENAME; YY_BREAK case 267: YY_RULE_SETUP #line 337 "../s/bif.l" yylloc->step (); YY_BREAK case 268: /* rule 268 can match eol */ YY_RULE_SETUP #line 338 "../s/bif.l" yylloc->lines (yyleng); yylloc->step (); YY_BREAK case 269: YY_RULE_SETUP #line 339 "../s/bif.l" /* ignore (Linux only) */ YY_BREAK case 270: YY_RULE_SETUP #line 340 "../s/bif.l" printf("WARNING: bad character! '%s' (0x%02X)\n",yytext,yytext[0]); YY_BREAK case 271: YY_RULE_SETUP #line 341 "../s/bif.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 3153 "../bisonflex/bif.yy.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* %ok-for-header */ /* %if-c++-only */ /* %not-for-header */ /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ) { yyin = arg_yyin; yyout = arg_yyout; yy_c_buf_p = 0; yy_init = 0; yy_start = 0; yy_flex_debug = 0; yylineno = 1; // this will only get updated if %option yylineno yy_did_buffer_switch_on_eof = 0; yy_looking_for_trail_begin = 0; yy_more_flag = 0; yy_more_len = 0; yy_more_offset = yy_prev_more_offset = 0; yy_start_stack_ptr = yy_start_stack_depth = 0; yy_start_stack = NULL; yy_buffer_stack = 0; yy_buffer_stack_top = 0; yy_buffer_stack_max = 0; yy_state_buf = 0; } /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::~yyFlexLexer() { delete [] yy_state_buf; biffree(yy_start_stack ); yy_delete_buffer( YY_CURRENT_BUFFER ); biffree(yy_buffer_stack ); } /* The contents of this function are C++ specific, so the () macro is not used. */ void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out ) { if ( new_in ) { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); } if ( new_out ) yyout = new_out; } #ifdef YY_INTERACTIVE int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) #else int yyFlexLexer::LexerInput( char* buf, int max_size ) #endif { if ( yyin->eof() || yyin->fail() ) return 0; #ifdef YY_INTERACTIVE yyin->get( buf[0] ); if ( yyin->eof() ) return 0; if ( yyin->bad() ) return -1; return 1; #else (void) yyin->read( buf, max_size ); if ( yyin->bad() ) return -1; else return yyin->gcount(); #endif } void yyFlexLexer::LexerOutput( const char* buf, int size ) { (void) yyout->write( buf, size ); } /* %ok-for-header */ /* %endif */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_get_next_buffer() /* %endif */ { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ bifrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) bifrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ /* %if-c-only */ /* %not-for-header */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_get_previous_state() /* %endif */ { register yy_state_type yy_current_state; register char *yy_cp; /* %% [15.0] code to get the start state into yy_current_state goes here */ yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { /* %% [16.0] code to find the next state goes here */ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1225 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) /* %endif */ { register int yy_is_jam; /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1225 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 1224); return yy_is_jam ? 0 : yy_current_state; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyunput( int c, register char* yy_bp) /* %endif */ { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; /* %% [18.0] update yylineno here */ (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yyinput() /* %endif */ { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); /* %% [19.0] update BOL and yylineno */ return c; } /* %if-c-only */ /* %endif */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyrestart( std::istream* input_file ) /* %endif */ { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_init_buffer( YY_CURRENT_BUFFER, input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) /* %endif */ { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_load_buffer_state() /* %endif */ { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size ) /* %endif */ { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) bifalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) bifalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) biffree((void *) b->yy_ch_buf ); biffree((void *) b ); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ extern "C" int isatty (int ); /* %endif */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file ) /* %endif */ { int oerrno = errno; yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ b->yy_is_interactive = 0; /* %endif */ errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /* %if-c-or-c++ */ /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer) /* %endif */ { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /* %endif */ /* %if-c-or-c++ */ /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypop_buffer_state (void) /* %endif */ { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* %endif */ /* %if-c-or-c++ */ /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyensure_buffer_stack(void) /* %endif */ { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)bifalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)bifrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_push_state( int new_state ) /* %endif */ { if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) { yy_size_t new_size; (yy_start_stack_depth) += YY_START_STACK_INCR; new_size = (yy_start_stack_depth) * sizeof( int ); if ( ! (yy_start_stack) ) (yy_start_stack) = (int *) bifalloc(new_size ); else (yy_start_stack) = (int *) bifrealloc((void *) (yy_start_stack),new_size ); if ( ! (yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; BEGIN(new_state); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_pop_state() /* %endif */ { if ( --(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_top_state() /* %endif */ { return (yy_start_stack)[(yy_start_stack_ptr) - 1]; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::LexerError( yyconst char msg[] ) { std::cerr << msg << std::endl; exit( YY_EXIT_FAILURE ); } /* %endif */ /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /* %if-c-only */ /* %if-reentrant */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif */ /* %if-reentrant */ /* %if-bison-bridge */ /* %endif */ /* %endif if-c-only */ /* %if-c-only */ /* %endif */ /* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ /* %if-reentrant */ /* %endif */ /* %endif */ /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *bifalloc (yy_size_t size ) { return (void *) malloc( size ); } void *bifrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void biffree (void * ptr ) { free( (char *) ptr ); /* see bifrealloc() for (char *) cast */ } /* %if-tables-serialization definitions */ /* %define-yytables The name for this specific scanner's tables. */ #define YYTABLES_NAME "yytables" /* %endif */ /* %ok-for-header */ #line 341 "../s/bif.l" void BIF::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); if (c == '\n') yylloc->lines (1); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/bifoptions.cpp000077500000000000000000002045311475706442400174560ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************************ HEADER FILES ***** ------------------------------------------------------------------------------- */ #include #include #include #include "bifoptions.h" #include "bifscanner.h" #include "encryptutils.h" #include "cdo-command.h" #include /* Forward Class Declaration */ class BootImage; static bool delay_load_warning_given; static bool delay_handoff_warning_given; /* ------------------------------------------------------------------------------- *************************************************************** FUNCTIONS ***** ------------------------------------------------------------------------------- */ /******************************************************************************/ BifOptions::BifOptions(Arch::Type architecture, const char* name) : groupname("") , regInitFile("") , udfBhFile("") , ppkFile("") , pskFile("") , headerSignatureFile("") , bhKeyFile("") , pufHelperFile("") , bhKekIVFile("") , bbramKekIVFile("") , efuseKekIVFile("") , efuseUserKek0IVFile("") , efuseUserKek1IVFile("") , familyKeyFile("") , keySourceEncryption(KeySource::None) , bootDevice(BootDevice::DEFAULT) , bootDeviceAddress(0) , bhAuthEnable(BhRsa::BhRsaDisable) , pufHdLoc(PufHdLoc::PUFinEFuse) , pufHdinBHEnable(false) , authOnly(AuthOnly::None) , pufMode(PufMode::PUF12K) , optKey(OptKey::None) , shutterVal(SHUTTER_VAL) , pufRoSwapConfigVal(0) , dpaCM(DpaCM::DpaCMDisable) , ppkSelect(0) , spkSelect(1) , spkId(0x00000000) , headerAuthParam(false) , createHeaderAC(false) , doHeaderEncryption(false) , splitMode(SplitMode::None) , splitFmt(File::Unknown) , xipMode(false) , pmcCdoLoadAddress(DEFAULT_PMCDATA_LOADADDR) , pmcdataSize(0) , totalpmcdataSize(0) , pmcDataBuffer(NULL) , pdiId(0) , parentId(0) , idCode(0) , extendedIdCode(0) , bypassIdCode(false) , smapWidth(32) , core(Core::A53Singlex64) , isPPKSelectGlobal(false) , isSPKSelectGlobal(false) , isSpkIdGlobal(false) , slrBootCnt(0) , slrConfigCnt(0) , aHwrot(false) , sHwrot(false) , pmcdataBlocks(0) , dice(DICE::DiceDisable) , slrNum(0xFF) , pdiType(PartitionType::RESERVED) , revokeId(0x00000000) { arch = architecture; SetGroupName(name); delay_handoff_warning_given = false; delay_load_warning_given = false; metaHdrAttributes.encrypt = Encryption::None; metaHdrAttributes.encrKeySource = KeySource::None; metaHdrAttributes.encrKeyFile = ""; metaHdrAttributes.authenticate = Authentication::None; metaHdrAttributes.ppk = metaHdrAttributes.spk = metaHdrAttributes.psk = metaHdrAttributes.ssk = ""; metaHdrAttributes.presign = metaHdrAttributes.spkSignature = ""; metaHdrAttributes.revokeId = 0; metaHdrAttributes.checksum = Checksum::None; metaHdrAttributes.dpaCM = DpaCM::DpaCMDisable; metaHdrAttributes.pufHdLoc = PufHdLoc::PUFinEFuse; authJtagInfo.jtagTimeout = 0; authJtagInfo.userDeviceDNA = false; memset(authJtagInfo.deviceDNA, 0, sizeof(authJtagInfo.deviceDNA)); authJtagInfo.revokeId = 0; authJtagInfo.userRevokeId = false; } /******************************************************************************/ PartitionBifOptions::PartitionBifOptions() : aesKeyFile("") , ppkFile("") , pskFile("") , spkFile("") , sskFile("") , spkSignatureFile("") , bootImage(false) , pmuFwImage(false) , pmcData(false) , presignFile("") , acFile("") , udfDataFile("") , encryptType(Encryption::None) , authType(Authentication::None) , checksumType(Checksum::None) , ownerType(PartitionOwner::FSBL) , partitionType(PartitionType::RESERVED) , destCPUType(DestinationCPU::NONE) , destDeviceType(DestinationDevice::DEST_DEV_PS) , exceptionLevel(ExceptionLevel::EL3) , trustzone(TrustZone::NonSecure) , bootloader(false) , early_handoff(false) , hivec(false) , authblockattr(0) , pid(0) , blocks(0) , defBlockSize(0) , spkSelect(1) , spkSelLocal(false) , spkId(0x00000000) , spkIdLocal(false) , fileType(0) , filename("") , arch (Arch::ZYNQ) , partitionId(0) , keySrc(KeySource::None) , boot(false) , user(false) , Static(false) , Protected(false) , multiboot(false) , noautostart(false) , blockSize(0) , bigEndian(false) , a32Mode(false) , dpaCM(DpaCM::DpaCMDisable) , revokeId(0x00000000) , slrNum(0xFF) , pufHdLoc(PufHdLoc::PUFinEFuse) , versalNetSeries(false) , clusterNum(0) , lockstep(false) , updateReserveInPh(false) , bifSection("") , delayAuth(false) , imageStoreId(0xFF) , erasePartition(false) , tcmBoot(false) , tcmARegionAddr(0) , tcmBRegionAddr(0) , tcmCRegionAddr(0) { } /******************************************************************************/ void BifOptions::SetHeaderAC(bool flag) { createHeaderAC = flag; } /******************************************************************************/ void BifOptions::SetHeaderEncryption(bool flag) { doHeaderEncryption = flag; } /******************************************************************************/ void BifOptions::Add(PartitionBifOptions* currentPartitionBifOptions, ImageBifOptions* currentImageBifOptions) { //filespec->Dump(); switch (currentPartitionBifOptions->fileType) { case BIF::BisonParser::token::INIT: SetRegInitFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::UDF_BH: SetUdfBHFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::AES_KEY_FILE: SetAESKeyFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::FAMILY_KEY: SetFamilyKeyFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::PPK_FILE: SetPPKFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::PSK_FILE: SetPSKFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::SPK_FILE: SetSPKFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::SSK_FILE: SetSSKFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::SPK_SIGNATURE_FILE: SetSPKSignFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::BH_SIGNATURE_FILE: SetBHSignFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::HEADER_SIGNATURE_FILE: SetHeaderSignFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::BH_KEY_FILE: SetBHKeyFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::PUF_HELPER_FILE: SetPUFHelperFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::BH_KEY_IV: SetBHKekIVFileName(currentPartitionBifOptions->filename); break; case BIF::BisonParser::token::PMUFW_IMAGE: SetPmufwImageFileName(currentPartitionBifOptions); break; case BIF::BisonParser::token::PMCDATA: SetPmcdataFile(currentPartitionBifOptions->filename); SetPmcCdoFileList(currentPartitionBifOptions->filename); currentPartitionBifOptions->filename = currentPartitionBifOptions->filelist.at(0); if ((currentPartitionBifOptions)->load.Value() != 0) { pmcCdoLoadAddress = (currentPartitionBifOptions)->load.Value(); } if ((currentPartitionBifOptions)->aesKeyFile != "") { SetPmcDataAesFile((currentPartitionBifOptions)->aesKeyFile); } //If no key file found in partition specific attributes - Generate aeskeyfile with partition_name.nky else { SetPmcDataAesFile(StringUtils::RemoveExtension(StringUtils::BaseName((currentPartitionBifOptions)->filename)) + ".nky"); } if(!(currentPartitionBifOptions->pmcData)) partitionBifOptionList.push_back(currentPartitionBifOptions); currentPartitionBifOptions->pmcData = true; break; case 0: if (currentImageBifOptions != NULL) { if (currentImageBifOptions->GetImageType() == PartitionType::SLR_BOOT) { slrBootCnt++; currentPartitionBifOptions->partitionType = PartitionType::SLR_BOOT; } if (currentImageBifOptions->GetImageType() == PartitionType::SLR_CONFIG) { slrConfigCnt++; currentImageBifOptions->slrConfigCnt++; currentPartitionBifOptions->partitionType = PartitionType::SLR_CONFIG; } if (currentPartitionBifOptions->partitionType == PartitionType::RESERVED) { currentPartitionBifOptions->partitionType = currentImageBifOptions->GetImageType(); } currentImageBifOptions->partitionBifOptionsList.push_back(currentPartitionBifOptions); if (lastPartitionBifOption == currentPartitionBifOptions) { currentImageBifOptions->partitionBifOptionsList.pop_back(); } } if (lastPartitionBifOption == currentPartitionBifOptions) { partitionBifOptionList.pop_back(); currentPartitionBifOptions->filename = currentPartitionBifOptions->filelist.front(); } partitionBifOptionList.push_back(currentPartitionBifOptions); lastPartitionBifOption = currentPartitionBifOptions; } } /******************************************************************************/ void BifOptions::AddFiles(int type, std::string filename) { //filespec->Dump(); switch (type) { case BIF::BisonParser::token::INIT: SetRegInitFileName(filename); break; case BIF::BisonParser::token::UDF_BH: SetUdfBHFileName(filename); break; case BIF::BisonParser::token::AES_KEY_FILE: SetAESKeyFileName(filename); break; case BIF::BisonParser::token::FAMILY_KEY: SetFamilyKeyFileName(filename); break; case BIF::BisonParser::token::PPK_FILE: SetPPKFileName(filename); break; case BIF::BisonParser::token::PSK_FILE: SetPSKFileName(filename); break; case BIF::BisonParser::token::SPK_FILE: SetSPKFileName(filename); break; case BIF::BisonParser::token::SSK_FILE: SetSSKFileName(filename); break; case BIF::BisonParser::token::SPK_SIGNATURE_FILE: SetSPKSignFileName(filename); break; case BIF::BisonParser::token::BH_SIGNATURE_FILE: SetBHSignFileName(filename); break; case BIF::BisonParser::token::HEADER_SIGNATURE_FILE: SetHeaderSignFileName(filename); break; case BIF::BisonParser::token::BH_KEY_FILE: SetBHKeyFileName(filename); break; case BIF::BisonParser::token::PUF_HELPER_FILE: SetPUFHelperFileName(filename); break; case BIF::BisonParser::token::BH_KEK_IV: SetBHKekIVFileName(filename); break; case BIF::BisonParser::token::BBRAM_KEK_IV: SetBbramKekIVFileName(filename); break; case BIF::BisonParser::token::EFUSE_KEK_IV: SetEfuseKekIVFileName(filename); break; case BIF::BisonParser::token::EFUSE_USER_KEK0_IV: SetEfuseUserKek0IVFileName(filename); break; case BIF::BisonParser::token::EFUSE_USER_KEK1_IV: SetEfuseUserKek1IVFileName(filename); break; case BIF::BisonParser::token::USER_KEYS: SetUserKeysFileName(filename); break; } } /******************************************************************************/ void BifOptions::SetRegInitFileName(std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } regInitFile = filename; LOG_TRACE("Setting Register initialization file as %s", regInitFile.c_str()); } /******************************************************************************/ std::string BifOptions::GetRegInitFileName() { return regInitFile; } /******************************************************************************/ std::string BifOptions::GetGroupName() { return groupname; } /******************************************************************************/ std::string BifOptions::GetAESKeyFileName(void) { return aesKeyFile; } /******************************************************************************/ void BifOptions::SetUdfBHFileName(std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } udfBhFile = filename; LOG_TRACE("Setting UDF of BH as %s", udfBhFile.c_str()); } /******************************************************************************/ void BifOptions::SetPmufwImageFileName(PartitionBifOptions* currentPartitionBifOptions) { if (arch != Arch::ZYNQMP) { LOG_ERROR("BIF attribute error !!!\n\t\t'[pmufw_image]' is supported only in ZYNQMP architecture"); } std::ifstream f(currentPartitionBifOptions->filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", currentPartitionBifOptions->filename.c_str()); } if (currentPartitionBifOptions->authType != Authentication::None) { LOG_ERROR("BIF attribute error !!!\n\t\tBif option 'authentication' is not supported with [pmufw_image].\n\t\tpmufw will be signed along with bootloader, if authentication is enabled for bootloader."); } if (currentPartitionBifOptions->encryptType != Encryption::None) { LOG_ERROR("BIF attribute error !!!\n\t\tBif option 'encryption' is not supported with [pmufw_image].\n\t\tpmufw will be encrypted if encryption is enabled for bootloader."); } if (currentPartitionBifOptions->checksumType != Checksum::None) { LOG_ERROR("BIF attribute error !!!\n\t\tBif option 'checksum' is not supported with [pmufw_image].\n\t\tpmufw will be checksummed if checksum is enabled for bootloader."); } if (currentPartitionBifOptions->destCPUType != DestinationCPU::NONE) { LOG_ERROR("BIF attribute error !!!\n\t\tBif option 'destination_cpu' is not supported with [pmufw_image]."); } pmuFwImageFile = currentPartitionBifOptions->filename; LOG_TRACE("Setting PMU FW Image file as %s", pmuFwImageFile.c_str()); } /******************************************************************************/ void BifOptions::SetPmcdataFile(const std::string& filename) { if (arch != Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t[pmcdata] supported only in VERSAL architecture"); } pmcdataFile = filename; } /******************************************************************************/ void BifOptions::ClearPmcCdoFileList() { pmcCdoFileList.clear(); } /******************************************************************************/ void BifOptions::SetPmcCdoFileList(const std::string& filename) { pmcCdoFileList.push_back(filename); } /******************************************************************************/ void BifOptions::SetGroupName(std::string name) { groupname = name; } /******************************************************************************/ void BifOptions::SetPPKFileName(std::string filename) { std::ifstream f(filename.c_str()); ppkFile = filename; } /******************************************************************************/ void BifOptions::SetPSKFileName(std::string filename) { std::ifstream f(filename.c_str()); pskFile = filename; } /******************************************************************************/ void BifOptions::SetSPKFileName(std::string filename) { std::ifstream f(filename.c_str()); spkFile = filename; } /******************************************************************************/ void BifOptions::SetSSKFileName(std::string filename) { std::ifstream f(filename.c_str()); sskFile = filename; } /******************************************************************************/ void BifOptions::SetSPKSignFileName(std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } spkSignatureFile = filename; } /******************************************************************************/ void BifOptions::SetBHSignFileName(std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } bhSignatureFile = filename; } /******************************************************************************/ void BifOptions::SetHeaderSignFileName(std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } headerSignatureFile = filename; } /******************************************************************************/ void BifOptions::SetBHKeyFileName(std::string filename) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'[bh_keyfile]' not supported in ZYNQ architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } bhKeyFile = filename; LOG_TRACE("Setting BH Key file as %s", bhKeyFile.c_str()); } /******************************************************************************/ void BifOptions::SetTotalpmcdataSize(uint32_t size) { totalpmcdataSize = size; } /******************************************************************************/ void BifOptions::SetOptKey(OptKey::Type type) { optKey = type; } /******************************************************************************/ void BifOptions::SetPufMode(PufMode::Type type) { pufMode = type; } /******************************************************************************/ void BifOptions::SetShutterValue(uint32_t value) { shutterVal = value; if (arch == Arch::VERSAL) { if((shutterVal & 0x80000000) == 0) { LOG_ERROR("The PUF shutter value specified in the BIF file indicates that the Global Variation Filter was not enabled during PUF registration/provisioning.\n\t The Global Variation Filter must be used during PUF registration/provisioning to avoid PUF key encryption keys with lower than expected entropy "); } } } /******************************************************************************/ void BifOptions::SetPufRingOscilltorSwapConfigValue(uint32_t value) { pufRoSwapConfigVal = value; } /******************************************************************************/ void BifOptions::SetDiceEnable() { dice = DICE::DiceEnable; } /******************************************************************************/ void BifOptions::SetPUFHelperFileName(std::string filename) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'[puf_file]' not supported in ZYNQ architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } pufHelperFile = filename; LOG_TRACE("Setting PUF Helper Data file as %s", pufHelperFile.c_str()); } /******************************************************************************/ void BifOptions::SetBHKekIVFileName(std::string filename) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'bh_key_iv/bh_kek_iv' not supported in ZYNQ architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } bhKekIVFile = filename; LOG_TRACE("Setting BH Kek IV file as %s", bhKekIVFile.c_str()); } /******************************************************************************/ void BifOptions::SetBbramKekIVFileName(std::string filename) { if (arch != Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t'bbram_kek_iv' supported only in VERSAL architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } bbramKekIVFile = filename; LOG_TRACE("Setting Bbram Kek IV file as %s", bbramKekIVFile.c_str()); } /******************************************************************************/ void BifOptions::SetEfuseKekIVFileName(std::string filename) { if (arch != Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t'efuse_kek_iv' is supported only in VERSAL architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } efuseKekIVFile = filename; LOG_TRACE("Setting Efuse Kek IV file as %s", efuseKekIVFile.c_str()); } /******************************************************************************/ void BifOptions::SetEfuseUserKek0IVFileName(std::string filename) { if (arch != Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t'efuse_user_kek0_iv' is supported only in VERSAL architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } efuseUserKek0IVFile = filename; LOG_TRACE("Setting Efuse User Kek0 IV file as %s", efuseUserKek0IVFile.c_str()); } /******************************************************************************/ void BifOptions::SetEfuseUserKek1IVFileName(std::string filename) { if (arch != Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t'efuse_user_kek1_iv' is supported only in VERSAl architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } efuseUserKek1IVFile = filename; LOG_TRACE("Setting Efuse User Kek1 IV file as %s", efuseUserKek1IVFile.c_str()); } /******************************************************************************/ void BifOptions::SetUserKeysFileName(std::string filename) { if (arch == Arch::ZYNQ || arch == Arch::ZYNQMP) { LOG_ERROR("BIF attribute error !!!\n\t\t'userkeys' is not supported for ZYNQ/ZYNQMP architectures"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } userKeyFile = filename; ParseUserKeyFile(userKeyFile); } /******************************************************************************/ void static SetUserKey(const uint8_t* key, uint32_t* userKey) { for (uint32_t index = 0; index < WORDS_PER_AES_KEY; index++) { userKey[index] = ReadBigEndian32(key); key += sizeof(uint32_t); } } /******************************************************************************/ void BifOptions::ParseUserKeyFile(std::string inputFileName) { LOG_TRACE("Reading the user key file %s",inputFileName.c_str()); std::ifstream keyFile(inputFileName.c_str()); if (!keyFile) { LOG_ERROR("Failure reading user key file - %s", inputFileName.c_str()); } while (keyFile) { std::string word; keyFile >> word; if (word == "") { return; } //char c = ' '; int c = (int)word.back() - 48; word.pop_back(); if (word == "user_key") { if (c > 7 && c < 0) { LOG_ERROR("The AES user keys available are from 0 to 7. user_key%d is not supported", c); } word = ""; keyFile >> word; uint8_t hexData[256] = { 0 }; if (!(word.size() == (WORDS_PER_AES_KEY * 8) || word.size() == (WORDS_PER_AES_KEY * 4))) { LOG_ERROR("An AES user key must be 128/256 bits long - %s", word.c_str()); } if (word.size() & 1) { LOG_ERROR("Error parsing AES user key \n\t\t Hex String - %s - does not have even no.of hex digits", word.c_str()); } for (uint32_t i = 0, j = 0; i < word.size(); i += 2, j++) { std::string byte = word.substr(i, 2); if (!isxdigit(byte[0]) || !isxdigit(byte[1])) { LOG_ERROR("Error parsing AES user key\n\t\t Hex String - %s - is has a non hex digit", word.c_str()); } if (word.size() == WORDS_PER_AES_KEY * 4) { hexData[j+16] = (uint8_t)strtoul(byte.c_str(), NULL, 16); } else { hexData[j] = (uint8_t)strtoul(byte.c_str(), NULL, 16); } } SetUserKey(hexData, (uint32_t*)&(user_keys.user_keys_array[c][0])); } else { /* If the word is neither of the above */ LOG_DEBUG(DEBUG_STAMP, "'user_key' identifier expected, '%s' found instead", word.c_str()); LOG_ERROR("Error parsing User key file - %s", inputFileName.c_str()); } } } /******************************************************************************/ void BifOptions::SetFamilyKeyFileName(std::string filename) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'[familykey]' not supported in ZYNQ architecture"); } std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } familyKeyFile = filename; LOG_TRACE("Setting Family Key file as %s", familyKeyFile.c_str()); } /******************************************************************************/ void BifOptions::SetAESKeyFileName(std::string filename) { std::ifstream f(filename.c_str()); aesKeyFile = filename; } /******************************************************************************/ void BifOptions::SetBootVectorArray(uint32_t vector) { static bool warningGiven = false; if (!warningGiven) { LOG_TRACE("Setting bootvector array"); } warningGiven = true; bootvectors.push_back(vector); if (bootvectors.size() > 8) { LOG_ERROR("BIF attribute error !!!\n\t\t[bootvectors] cannot take more than 8 vector addresses"); } } /******************************************************************************/ void BifOptions::SetXipMode() { xipMode = true; } /******************************************************************************/ bool BifOptions::GetXipMode(void) { return xipMode; } /******************************************************************************/ void BifOptions::SetSplitMode(SplitMode::Type type) { LOG_TRACE("Setting Split Mode as %d", type ); splitMode = type; } /******************************************************************************/ void BifOptions::SetSplitFmt(File::Type type) { LOG_TRACE("Setting Split Format as %d", type); splitFmt = type; } /******************************************************************************/ void BifOptions::SetEncryptionKeySource(KeySource::Type type) { if (arch == Arch::ZYNQ) { if ((type != KeySource::BbramRedKey) && (type != KeySource::EfuseRedKey) && (type != KeySource::None)) { LOG_DEBUG(DEBUG_STAMP, "Key Source = %d", type); LOG_ERROR("BIF attribute error !!!\n\t\tUnknown option for 'keysrc_encryption' in BIF file\n\t\tZynq Architecture supports 'efuse' & 'bbram' key sources"); } } keySourceEncryption = type; } /******************************************************************************/ void BifOptions::SetBootDevice(BootDevice::Type type) { LOG_TRACE("Setting Boot Device as %d", type); bootDevice = type; } /******************************************************************************/ void BifOptions::SetBootDeviceAddress(uint32_t address) { bootDeviceAddress = address; } /******************************************************************************/ OptKey::Type BifOptions::GetAesOptKeyFlag(void) { return optKey; } /******************************************************************************/ std::string BifOptions::GetKeySourceName(KeySource::Type type) { switch (type) { case KeySource::None: return "None"; break; case KeySource::BbramRedKey: return "bbram_red_key"; break; case KeySource::EfuseRedKey: return "efuse_red_key"; break; case KeySource::EfuseBlkKey: return "efuse_blk_key"; break; case KeySource::BhBlkKey: return "bh_blk_key"; break; case KeySource::EfuseGryKey: return "efuse_gry_key"; break; case KeySource::BhGryKey: return "bh_gry_key"; break; case KeySource::BhKupKey: return "kup_key"; break; case KeySource::BbramBlkKey: return "bbram_blk_key"; break; case KeySource::BbramGryKey: return "bbram_gry_key"; break; case KeySource::UserKey0: return "user_key0"; break; case KeySource::UserKey1: return "user_key1"; break; case KeySource::UserKey2: return "user_key2"; break; case KeySource::UserKey3: return "user_key3"; break; case KeySource::UserKey4: return "user_key4"; break; case KeySource::UserKey5: return "user_key5"; break; case KeySource::UserKey6: return "user_key6"; break; case KeySource::UserKey7: return "user_key7"; break; case KeySource::EfuseUserKey0: return "efuse_user_key0"; break; case KeySource::EfuseUserBlkKey0: return "efuse_user_blk_key0"; break; case KeySource::EfuseUserGryKey0: return "efuse_user_gry_key0"; break; case KeySource::EfuseUserKey1: return "efuse_user_key1"; break; case KeySource::EfuseUserBlkKey1: return "efuse_user_blk_key1"; break; case KeySource::EfuseUserGryKey1: return "efuse_user_gry_key1"; break; default: return "None"; break; } } /******************************************************************************/ void BifOptions::CheckForSameKeyandKeySrcPair(std::vector> aesKeyandKeySrc) { static bool warningGiven = false; std::multimap key0_keysrc; for (uint32_t i = 0; i < aesKeyandKeySrc.size(); i++) { std::stringstream key0String; for (uint32_t j = 0; j < WORDS_PER_AES_KEY; j++) { key0String << std::setfill('0') << std::setw(2) << std::hex << aesKeyandKeySrc[i].second[j]; } key0_keysrc.insert(std::pair(key0String.str(), GetKeySourceName(aesKeyandKeySrc[i].first))); } for (auto unique_key0s = key0_keysrc.begin(), end = key0_keysrc.end(); unique_key0s != end; unique_key0s = key0_keysrc.upper_bound((unique_key0s->first))) { std::string warnKeySrc = ""; int count = 0; std::multimap::iterator keysrc_itr = key0_keysrc.find(unique_key0s->first); for (uint32_t i = 0; i < key0_keysrc.count(unique_key0s->first); i++) { if (warnKeySrc.find(keysrc_itr->second.c_str()) == std::string::npos) { warnKeySrc += keysrc_itr->second.c_str(); warnKeySrc += ", "; count++; } ++keysrc_itr; } if (warnKeySrc != "" && count > 1) { warnKeySrc.erase(warnKeySrc.size() - 2); if (!warningGiven) { LOG_MSG("[WARNING]: Same Key0 is used for different KeySources.\n"); warningGiven = true; } LOG_MSG("\t Key Sources : %s", warnKeySrc.c_str()); LOG_MSG("\t Key0 Used : %s\n", unique_key0s->first.c_str()); } } } /******************************************************************************/ void BifOptions::CheckForBadKeyandKeySrcPair(std::vector> aesKeyandKeySrc, std::string aesFilename) { std::string errorKeySrc = ""; for (uint32_t i = 0; i < aesKeyandKeySrc.size(); i++) { uint32_t j = aesKeyandKeySrc.size() - 1; if (i != j) { if (aesKeyandKeySrc[i].first == aesKeyandKeySrc[j].first) { if (memcmp(aesKeyandKeySrc[i].second, aesKeyandKeySrc[j].second, AES_GCM_KEY_SZ) != 0) { if (errorKeySrc.find(GetKeySourceName(aesKeyandKeySrc[i].first)) == std::string::npos) { errorKeySrc += GetKeySourceName(aesKeyandKeySrc[i].first); errorKeySrc += ", "; } } } } } if (errorKeySrc != "") { errorKeySrc.erase(errorKeySrc.size() - 2); LOG_ERROR("Check %s\n\t Key0 must be same across the BIF for a given KeySource : %s", aesFilename.c_str(), errorKeySrc.c_str()); } } /******************************************************************************/ static void ValidateEncryptionKeySource(KeySource::Type type, bool versalNetSeries) { if (!versalNetSeries) { if ((type == KeySource::EfuseGryKey) || (type == KeySource::BhGryKey) || (type == KeySource::BbramGryKey) || (type == KeySource::EfuseUserGryKey0) || (type == KeySource::EfuseUserGryKey1)) { LOG_ERROR("The usage of obfuscated keys is deprecated in Versal.\n\t Refer 'bootgen -arch versal -bif_help keysrc' for valid key sources."); } } static bool bhBlkKek = false; static bool bhGryKek = false; if ((type == KeySource::BhBlkKey && bhGryKek) || (type == KeySource::BhGryKey && bhBlkKek)) { LOG_ERROR("'bh_blk_key and bh_gry_key' cannot be used in a single boot image."); } else if (type == KeySource::BhBlkKey) { bhBlkKek = true; } else if (type == KeySource::BhGryKey) { bhGryKek = true; } static bool bbramBlkKek = false; static bool bbramGryKek = false; if ((type == KeySource::BbramBlkKey && bbramGryKek) || (type == KeySource::BbramGryKey && bbramBlkKek)) { LOG_ERROR("'bbram_blk_key and bbram_gry_key' cannot be used in a single boot image."); } else if (type == KeySource::BbramBlkKey) { bbramBlkKek = true; } else if (type == KeySource::BbramGryKey) { bbramGryKek = true; } static bool efuseBlkKek = false; static bool efuseGryKek = false; if ((type == KeySource::EfuseBlkKey && efuseGryKek) || (type == KeySource::EfuseGryKey && efuseBlkKek)) { LOG_ERROR("'efuse_blk_key and efuse_gry_key' cannot be used in a single boot image."); } else if (type == KeySource::EfuseBlkKey) { efuseBlkKek = true; } else if (type == KeySource::EfuseGryKey) { efuseGryKek = true; } static bool efuseUserBlkKek0 = false; static bool efuseUserGryKek0 = false; if ((type == KeySource::EfuseUserBlkKey0 && efuseUserGryKek0) || (type == KeySource::EfuseUserGryKey0 && efuseUserBlkKek0)) { LOG_ERROR("'efuse_user_blk_key0 and efuse_user_gry_key0' cannot be used in a single boot image."); } else if (type == KeySource::EfuseUserBlkKey0) { efuseUserBlkKek0 = true; } else if (type == KeySource::EfuseUserGryKey0) { efuseUserGryKek0 = true; } static bool efuseUserBlkKek1 = false; static bool efuseUserGryKek1 = false; if ((type == KeySource::EfuseUserBlkKey1 && efuseUserGryKek1) || (type == KeySource::EfuseUserGryKey1 && efuseUserBlkKek1)) { LOG_ERROR("'efuse_user_blk_key1 and efuse_user_gry_key1' cannot be used in a single boot image."); } else if (type == KeySource::EfuseUserBlkKey1) { efuseUserBlkKek1 = true; } else if (type == KeySource::EfuseUserGryKey1) { efuseUserGryKek1 = true; } } /******************************************************************************/ void BifOptions::SetMetaHeaderEncryptionKeySource(KeySource::Type type, bool versalNetSeries) { ValidateEncryptionKeySource(type, versalNetSeries); metaHdrAttributes.encrKeySource = type; } /******************************************************************************/ void BifOptions::SetMetaHeaderEncryptType(Encryption::Type type) { metaHdrAttributes.encrypt = type; } /******************************************************************************/ void BifOptions::SetMetaHeaderEncryptionKeyFile(std::string file) { metaHdrAttributes.encrKeyFile = file; } /******************************************************************************/ void BifOptions::SetMetaHeaderAuthType(Authentication::Type type) { if (type == Authentication::ECDSAp521) { LOG_ERROR("BIF attribute error !!!\n\t\t 'ecdsa-p521' not supported for Meta Header"); } metaHdrAttributes.authenticate = type; } /******************************************************************************/ void BifOptions::SetPufHdinBHFlag() { pufHdinBHEnable = true; } /******************************************************************************/ void BifOptions::SetAuthJtagRevokeID(uint32_t value) { if (value > 0xFF) { LOG_ERROR("revoke_id can only take values from 0x0 to 0xFF."); } authJtagInfo.revokeId = value; authJtagInfo.userRevokeId = true; } /******************************************************************************/ void BifOptions::SetAuthJtagDeviceDna(std::string hexString) { authJtagInfo.userDeviceDNA = true; uint32_t hexStringLength = (uint32_t)hexString.size(); if (hexStringLength & 1) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - does not have even no. of hex digits", hexString.c_str()); LOG_ERROR("Error parsing Device DNA"); } for (uint32_t i = 0,j = 0; i < hexStringLength; i += 2,j++) { std::string byte = hexString.substr(i, 2); if (!isxdigit(byte[0]) || !isxdigit(byte[1])) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - is has a non hex digit", hexString.c_str()); LOG_ERROR("Error parsing Device DNA"); } authJtagInfo.deviceDNA[j] = (uint8_t)strtoul(byte.c_str(), NULL, 16); } } /******************************************************************************/ void BifOptions::SetAuthJtagTimeOut(uint32_t value) { authJtagInfo.jtagTimeout = value; } /******************************************************************************/ void PartitionBifOptions::SetEncryptionKeySource(KeySource::Type type) { ValidateEncryptionKeySource(type, versalNetSeries); keySrc = type; } /******************************************************************************/ void PartitionBifOptions::SetArchType(Arch::Type type, bool flag) { arch = type; versalNetSeries = flag; } /******************************************************************************/ void PartitionBifOptions::SetEncryptionBlocks(uint32_t size, uint32_t num) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'blocks' not supported in ZYNQ architecture"); } /* The size of each block is considered in bytes */ if ((size & 0x3) != 0) { LOG_DEBUG(DEBUG_STAMP, "Encryption Block Size Error - Block Size - %d", size); LOG_ERROR("BIF attribute 'blocks' must specify sizes which are multiples of 4, for word alignment."); } if (arch == Arch::VERSAL) { if (size < 64) { LOG_ERROR("BIF attribute error !!!\n\t\tThe minimum block size allowed is 4 AES encryption blocks (i.e., 64 bytes)"); } if(size % 16 != 0) { LOG_ERROR("BIF attribute error !!!\n\t\tThe block size specified must be 16 byte aligned. Block size - %d",size); } } if (num == 0) { SetDefaultEncryptionBlockSize(size); } else if (defBlockSize == 0) { for (uint32_t i = 0; i < num; i++) { blocks.push_back(size); } } else { LOG_ERROR("Cannot choose block size after choosing a default block size."); } } /******************************************************************************/ void PartitionBifOptions::SetDefaultEncryptionBlockSize(uint32_t blk) { defBlockSize = blk; } /******************************************************************************/ void BifOptions::InsertEncryptionBlock(uint32_t blk) { blocks.push_back(blk); } /******************************************************************************/ void PartitionBifOptions::SetDestCpu(DestinationCPU::Type type) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'destination_cpu' not supported in ZYNQ architecture"); } destCPUType = type; } /******************************************************************************/ void PartitionBifOptions::SetDestDevice(DestinationDevice::Type type) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'destination_device' not supported in ZYNQ architecture"); } if (type == DestinationDevice::DEST_DEV_PMU) { LOG_ERROR("BIF attribute 'destination_device=pmufw' is not supported.\ Please use 'destination_cpu=pmu'"); } if (type == DestinationDevice::DEST_DEV_XIP) { LOG_ERROR("BIF attribute 'destination_device=xip' is not supported.\ Please use the attribute 'xip_mode'. \ For more info, see 'bootgen -bif_help xip_mode'"); } destDeviceType = type; } /******************************************************************************/ void PartitionBifOptions::SetAuthType(Authentication::Type type) { authType = type; } /******************************************************************************/ void PartitionBifOptions::SetEncryptType(Encryption::Type type) { encryptType = type; } /******************************************************************************/ void PartitionBifOptions::SetChecksumType(Checksum::Type type) { if (type == Checksum::SHA2) { LOG_ERROR("BIF cksum BIF attribute error !!!\n\t\t'checksum=sha2' is not supported."); } if ((arch == Arch::ZYNQ) && (type == Checksum::SHA3)) { LOG_ERROR("BIF attribute error !!!\n\t\t'checksum=sha3' not supported in ZYNQ architecture"); } if ((arch == Arch::ZYNQMP) && (type == Checksum::MD5)) { LOG_ERROR("BIF attribute error !!!\n\t\t'checksum=md5' not supported in ZYNQMP architecture"); } checksumType = type; } /******************************************************************************/ void PartitionBifOptions::SetOwnerType(PartitionOwner::Type type) { ownerType = type; } /******************************************************************************/ void PartitionBifOptions::SetPartitionType(PartitionType::Type type) { partitionType = type; } /******************************************************************************/ void PartitionBifOptions::SetDpaCM(DpaCM::Type value) { dpaCM = value; } /******************************************************************************/ void PartitionBifOptions::SetExceptionLevel(ExceptionLevel::Type type) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'exception_level' not supported in ZYNQ architecture"); } exceptionLevel = type; } /******************************************************************************/ void PartitionBifOptions::SetSpkId(uint32_t id) { if (arch != Arch::ZYNQMP) { //LOG_ERROR("BIF attribute error !!!\n\t\t'spk_id' is supported only in ZYNQMP architecture"); } spkId = id; spkIdLocal = true; } /******************************************************************************/ void BifOptions::SetFsblFilename(std::string filename) { fsblFilename = filename; } /******************************************************************************/ void PartitionBifOptions::SetTrustZone(TrustZone::Type type) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'trustzone' not supported in ZYNQ architecture"); } trustzone = type; } /******************************************************************************/ void PartitionBifOptions::SetEarlyHandoff(bool flag) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'early_handoff' not supported in ZYNQ architecture"); } if (bootloader == true) { LOG_ERROR("BIF attribute error !!!\n\t\t'early_handoff' not supported for bootloader partitions"); } early_handoff = flag; } /******************************************************************************/ void PartitionBifOptions::SetHivec(bool flag) { if (arch == Arch::ZYNQ) { LOG_ERROR("BIF attribute error !!!\n\t\t'hivec' not supported in ZYNQ architecture"); } hivec = flag; } /******************************************************************************/ void PartitionBifOptions::SetRevokeId(uint32_t id) { if (id > 0xFF) { LOG_ERROR("revoke_id can only take values from 0x0 to 0xFF."); } revokeId = id; } /******************************************************************************/ void PartitionBifOptions::SetSlrNum(uint8_t id) { slrNum = id; } /******************************************************************************/ void PartitionBifOptions::SetClusterNum(uint8_t id) { if (arch == Arch::VERSAL && versalNetSeries) { if (id != 0 && id != 1 && id != 2 && id != 3) { LOG_ERROR("cluster can only take values from 0 to 3."); } clusterNum = id; } else { LOG_ERROR("BIF attribute error !!!\n\t 'cluster' is supported only in VersalNet architecture"); } } /******************************************************************************/ void BifOptions::SetRevokeId(uint32_t id) { if (id > 0xFF) { LOG_ERROR("revoke_id can only take values from 0x0 to 0xFF."); } revokeId = id; } /******************************************************************************/ uint32_t BifOptions::GetRevokeId() { return revokeId; } /******************************************************************************/ void PartitionBifOptions::SetLockStepFlag() { if (arch == Arch::VERSAL && versalNetSeries) { lockstep = true; } else { LOG_ERROR("BIF attribute error !!!\n\t 'lockstep' is supported only in VersalNet architecture"); } } /******************************************************************************/ void PartitionBifOptions::SetTcmARegion(uint64_t address) { if ((arch == Arch::VERSAL && versalNetSeries) && (destCPUType == DestinationCPU::R5_0 || destCPUType == DestinationCPU::R5_1 || destCPUType == DestinationCPU::R5_lockstep)) { tcmARegionAddr = address; } else { LOG_ERROR("BIF attribute error !!!\n\t 'tcm_a_region' is supported only in VersalNet architecture"); } } /******************************************************************************/ void PartitionBifOptions::SetTcmBRegion(uint64_t address) { if ((arch == Arch::VERSAL && versalNetSeries) && (destCPUType == DestinationCPU::R5_0 || destCPUType == DestinationCPU::R5_1 || destCPUType == DestinationCPU::R5_lockstep)) { tcmBRegionAddr = address; } else { LOG_ERROR("BIF attribute error !!!\n\t 'tcm_b_region' is supported only in VersalNet architecture"); } } /******************************************************************************/ void PartitionBifOptions::SetTcmCRegion(uint64_t address) { if ((arch == Arch::VERSAL && versalNetSeries) && (destCPUType == DestinationCPU::R5_0 || destCPUType == DestinationCPU::R5_1 || destCPUType == DestinationCPU::R5_lockstep)) { tcmCRegionAddr = address; } else { LOG_ERROR("BIF attribute error !!!\n\t 'tcm_c_region' is supported only in VersalNet architecture"); } } /******************************************************************************/ std::vector& PartitionBifOptions::GetEncryptionBlocks(void) { return blocks; } /******************************************************************************/ std::vector& BifOptions::GetEncryptionBlocksList(void) { return blocks; } /******************************************************************************/ void PartitionBifOptions::SetAuthBlockAttr(size_t authBlockAttr) { if (authBlockAttr != 4 && authBlockAttr != 8 && authBlockAttr != 16 && authBlockAttr != 32 && authBlockAttr != 64) { LOG_ERROR("'authblock' option supports only 4,8,16,32,64 sizes (taken in MB)"); } if (arch != Arch::ZYNQMP) { LOG_ERROR("BIF attribute error !!!\n\t\t'authblock' option supported only for ZYNQMP architecture '-arch zynqmp'"); } authblockattr = authBlockAttr; } /******************************************************************************/ void PartitionBifOptions::SetPufHdLocation(PufHdLoc::Type type) { pufHdLoc = type; } /******************************************************************************/ void PartitionBifOptions::SetReserveLength(uint64_t length, bool flag) { reserve = length; updateReserveInPh = flag; if (updateReserveInPh) { static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("The existing reserve functionality is updated.\n\t Please refer the section 'reserve' under 'Appendix A BIF Attribute Reference' in UG1283 for more details."); warningGiven = true; } } } /******************************************************************************/ void PartitionBifOptions::SetDelayAuth(bool flag) { delayAuth = flag; } /******************************************************************************/ void PartitionBifOptions::SetTcmBootFlag() { if (arch == Arch::VERSAL && versalNetSeries) { tcmBoot = true; } else { LOG_ERROR("BIF attribute error !!!\n\t 'tcmboot' is supported only in VersalNet architecture"); } } /******************************************************************************/ uint32_t PartitionBifOptions::GetDefaultEncryptionBlockSize(void) { return defBlockSize; } /******************************************************************************/ KeySource::Type PartitionBifOptions::GetEncryptionKeySource(void) { return keySrc; } /******************************************************************************/ DpaCM::Type PartitionBifOptions::GetDpaCM(void) { return dpaCM; } /******************************************************************************/ uint32_t PartitionBifOptions::GetRevokeId(void) { return revokeId; } /******************************************************************************/ PufHdLoc::Type PartitionBifOptions::GetPufHdLocation(void) { return pufHdLoc; } /******************************************************************************/ std::string PartitionBifOptions::GetOutputFileFromBifSection(std::string out_file, std::string bif_section, PartitionType::Type part_type) { std::string filename = StringUtils::RemoveExtension(out_file) + "_" + bif_section + StringUtils::GetExtension(out_file); if (part_type == PartitionType::SLR_BOOT || part_type == PartitionType::SLR_CONFIG) { filename = StringUtils::RemoveExtension(out_file) + "_" + bif_section + ".bin"; } return filename; } /******************************************************************************/ void BifOptions::SetTotalPmcFwSize(uint32_t size) { totalpmcdataSize = size; } /******************************************************************************/ void BifOptions::SetPmcFwSize(uint32_t size) { pmcdataSize = size; } /******************************************************************************/ void BifOptions::SetPPKSelection(uint32_t ppkSelection) { if ((ppkSelection == 0) | (ppkSelection == 1)) { ppkSelect = ppkSelection; isPPKSelectGlobal = true; LOG_TRACE("Setting PPK Selection in Auth Certificate as %d", ppkSelect); } else { LOG_DEBUG(DEBUG_STAMP, "PPK Select - %d", ppkSelect); LOG_ERROR("BIF attribute error !!!\n\t\t'ppk_select' can either be 0 or 1"); } } /******************************************************************************/ void BifOptions::SetSPKSelection(uint32_t spkSelection) { spkSelect = spkSelection; isSPKSelectGlobal = true; LOG_TRACE("Setting SPK Selection in Auth Certificate as %d", spkSelect); } /******************************************************************************/ void BifOptions::SetSpkId(uint32_t id) { spkId = id; isSpkIdGlobal = true; LOG_TRACE("Setting SPK ID in Auth Certificate as 0x%x", id); } /******************************************************************************/ void BifOptions::SetHeaderAuthentication() { headerAuthParam = true; SetHeaderAC(true); LOG_TRACE("Setting Header Authentication"); } /******************************************************************************/ void BifOptions::SetSmapWidth(uint32_t value) { smapWidth = value; } /******************************************************************************/ std::string BifOptions::GetFamilyKeyFileName() { return familyKeyFile; } /******************************************************************************/ BhRsa::Type BifOptions::GetBhRsa(void) { return bhAuthEnable; } /******************************************************************************/ BootDevice::Type BifOptions::GetBootDevice(void) { return bootDevice; } /******************************************************************************/ uint32_t BifOptions::GetBootDeviceAddress(void) { return bootDeviceAddress; } /******************************************************************************/ uint32_t BifOptions::GetSmapWidth(void) { return smapWidth; } /******************************************************************************/ uint32_t BifOptions::GetPmcCdoLoadAddress(void) { return pmcCdoLoadAddress; } /******************************************************************************/ uint32_t BifOptions::GetPmcFwSize(void) { return pmcdataSize; } /******************************************************************************/ uint32_t BifOptions::GetTotalPmcFwSize(void) { return totalpmcdataSize; } /******************************************************************************/ uint32_t BifOptions::GetPdiId(void) { return pdiId; } /******************************************************************************/ uint32_t BifOptions::GetParentId(void) { return parentId; } /******************************************************************************/ KeySource::Type BifOptions::GetEncryptionKeySource(void) { return keySourceEncryption; } /******************************************************************************/ bool BifOptions::GetPufHdinBHFlag(void) { return pufHdinBHEnable; } /******************************************************************************/ uint8_t* BifOptions::GetPmcDataBuffer(void) { return pmcDataBuffer; } /******************************************************************************/ uint32_t BifOptions::GetTotalpmcdataSize(void) { return totalpmcdataSize; } /******************************************************************************/ std::string BifOptions::GetPmcdataFile(void) { return pmcdataFile; } /******************************************************************************/ std::vector BifOptions::GetPmcCdoFileList(void) { return pmcCdoFileList; } /******************************************************************************/ void BifOptions::SetPmcDataAesFile(std::string filename) { pmcDataAesFile = filename; } /******************************************************************************/ std::string BifOptions::GetPmcDataAesFile(void) { return pmcDataAesFile; } /******************************************************************************/ PufMode::Type BifOptions::GetPufMode(void) { return pufMode; } /******************************************************************************/ PufHdLoc::Type BifOptions::GetPufHdLoc(void) { return pufHdLoc; } /******************************************************************************/ OptKey::Type BifOptions::GetOptKey(void) { return optKey; } /******************************************************************************/ AuthOnly::Type BifOptions::GetAuthOnly(void) { return authOnly; } /******************************************************************************/ uint32_t BifOptions::GetPpkSelection(void) { return ppkSelect; } /******************************************************************************/ bool BifOptions::GetPpkSelectionGlobal() { return isPPKSelectGlobal; } /******************************************************************************/ std::string BifOptions::GetPPKFileName(void) { return ppkFile; } /******************************************************************************/ std::string BifOptions::GetPSKFileName(void) { return pskFile; } /******************************************************************************/ uint32_t BifOptions::GetSpkSelection(void) { return spkSelect; } /******************************************************************************/ bool BifOptions::GetSpkSelectionGlobal() { return isSPKSelectGlobal; } /******************************************************************************/ std::string BifOptions::GetSPKFileName(void) { return spkFile; } /******************************************************************************/ std::string BifOptions::GetSSKFileName(void) { return sskFile; } /******************************************************************************/ uint32_t BifOptions::GetSpkId(void) { return spkId; } /******************************************************************************/ bool BifOptions::GetSpkIdGlobal() { return isSpkIdGlobal; } /******************************************************************************/ bool BifOptions::GetHeaderAC() { if (arch == Arch::VERSAL) { createHeaderAC = false; if (metaHdrAttributes.authenticate != Authentication::None) createHeaderAC = true; } return createHeaderAC; } /******************************************************************************/ bool BifOptions::GetHeaderEncyption() { if (arch == Arch::VERSAL) { doHeaderEncryption = false; if (metaHdrAttributes.encrypt != Encryption::None) doHeaderEncryption = true; } return doHeaderEncryption; } /******************************************************************************/ std::string BifOptions::GetBhKeyFile(void) { return bhKeyFile; } /******************************************************************************/ uint32_t BifOptions::GetShutterValue(void) { return shutterVal; } /******************************************************************************/ uint32_t BifOptions::GetPufRingOscilltorSwapConfigValue(void) { return pufRoSwapConfigVal; } /******************************************************************************/ DICE::Type BifOptions::GetDice(void) { return dice; } /******************************************************************************/ DpaCM::Type BifOptions::GetDpaCM(void) { return dpaCM; } /******************************************************************************/ std::string BifOptions::GetHeaderSignatureFile(void) { return headerSignatureFile; } /******************************************************************************/ std::string BifOptions::GetPufHelperFile(void) { return pufHelperFile; } /******************************************************************************/ std::string BifOptions::GetPmuFwImageFile(void) { return pmuFwImageFile; } /******************************************************************************/ std::string BifOptions::GetBHKekIVFile(void) { return bhKekIVFile; } /******************************************************************************/ std::string BifOptions::GetBbramKekIVFile(void) { return bbramKekIVFile; } /******************************************************************************/ std::string BifOptions::GetEfuseKekIVFile(void) { return efuseKekIVFile; } /******************************************************************************/ std::string BifOptions::GetEfuseUserKek0IVFile(void) { return efuseUserKek0IVFile; } /******************************************************************************/ std::string BifOptions::GetEfuseUserKek1IVFile(void) { return efuseUserKek1IVFile; } /******************************************************************************/ std::string BifOptions::GetUserKeysFileName(void) { return userKeyFile; } /******************************************************************************/ std::string BifOptions::GetUdfBhFile(void) { return udfBhFile; } /******************************************************************************/ SplitMode::Type BifOptions::GetSplitMode(void) { return splitMode; } /******************************************************************************/ File::Type BifOptions::GetSplitFormat(void) { return splitFmt; } /******************************************************************************/ std::vector& BifOptions::GetBootVectorArray(void) { return bootvectors; } /******************************************************************************/ std::string BifOptions::GetSPKSignFileName(void) { return spkSignatureFile; } /******************************************************************************/ std::string BifOptions::GetBHSignFileName(void) { return bhSignatureFile; } /******************************************************************************/ void BifOptions::SetAuthOnly(AuthOnly::Type type) { authOnly = type; } /******************************************************************************/ void BifOptions::SetPdiId(uint32_t id) { pdiId = id; } /******************************************************************************/ void BifOptions::SetIdCode(uint32_t id) { idCode = id; } /******************************************************************************/ void BifOptions::SetExtendedIdCode(uint32_t id) { if (id > 0x3F) { LOG_ERROR("Invalid extended ID code. Maximum length of extended_id_code is 6-bits"); } extendedIdCode = id; } /******************************************************************************/ void BifOptions::SetPdiType(PartitionType::Type type) { pdiType = type; } /******************************************************************************/ void BifOptions::SetBypassIdcodeFlag(bool flag) { bypassIdCode = flag; } /******************************************************************************/ void BifOptions::SetAHwRoTFlag(bool flag) { aHwrot = flag; } /******************************************************************************/ void BifOptions::SetSHwRoTFlag(bool flag) { sHwrot = flag; } /******************************************************************************/ void BifOptions::SetParentId(uint32_t id) { parentId = id; } /******************************************************************************/ void BifOptions::SetBhRsa(BhRsa::Type value) { bhAuthEnable = value; } /******************************************************************************/ void BifOptions::SetPufHdLoc(PufHdLoc::Type value) { pufHdLoc= value; } /******************************************************************************/ void BifOptions::SetCore(Core::Type type) { core = type; } /******************************************************************************/ Core::Type BifOptions::GetCore(void) { return core; } /******************************************************************************/ void BifOptions::SetDpaCM(DpaCM::Type value) { dpaCM = value; } /******************************************************************************/ uint32_t BifOptions::GetIdCode(void) { return idCode; } /******************************************************************************/ uint32_t BifOptions::GetExtendedIdCode(void) { return extendedIdCode; } /******************************************************************************/ bool BifOptions::GetBypassIdcodeFlag(void) { return bypassIdCode; } /******************************************************************************/ void PartitionBifOptions::SetAesKeyFile(std::string filename) { aesKeyFile = filename; } /******************************************************************************/ void PartitionBifOptions::SetUdfDataFile(std::string filename) { if (arch == Arch::VERSAL) { LOG_ERROR("BIF attribute error !!!\n\t\t'udf_data' is not supported in VERSAL architecture"); } udfDataFile = filename; } /******************************************************************************/ std::string PartitionBifOptions::GetUdfDataFile(void) { return udfDataFile; } /******************************************************************************/ void ImageBifOptions::SetDelayHandoff(bool flag) { if (!delay_handoff_warning_given) { delay_handoff_warning_given = true; LOG_WARNING("delay_handoff is specified, this may cause some issues if not handled properly"); } delayHandoff = flag; } /******************************************************************************/ void ImageBifOptions::SetDelayLoad(bool flag) { if (!delay_load_warning_given) { delay_load_warning_given = true; LOG_WARNING("delay_load is specified, this may cause some issues if not handled properly"); } delayLoad = flag; }xilinx-bootgen-2024.2/bifoptions.h000077500000000000000000000442751475706442400171320ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BIFOPTIONS_H_ #define _BIFOPTIONS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "options.h" #include "imageheadertable.h" /* Forward Class References */ class Options; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define SHUTTER_VAL 0x01000020 #define DEFAULT_PMCDATA_LOADADDR 0xF2000000 #define DEFAULT_ID_CODE_S80 0x04ca8093 typedef struct { Encryption::Type encrypt; KeySource::Type encrKeySource; std::string encrKeyFile; std::vector encrBlocks; uint32_t defEncrBlockSize; Authentication::Type authenticate; std::string ppk; std::string psk; std::string spk; std::string ssk; std::string spkSignature; std::string presign; uint32_t revokeId; Checksum::Type checksum; DpaCM::Type dpaCM; PufHdLoc::Type pufHdLoc; std::vector> ihtOptionalDataInfo; } MetaHdrInfo; typedef struct { uint32_t revokeId; bool userRevokeId; uint8_t deviceDNA[16]; uint32_t jtagTimeout; bool userDeviceDNA; } AuthJtagInfo; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class PartitionBifOptions { public: PartitionBifOptions(); void SetArchType(Arch::Type type, bool versalNetSeries); void SetEncryptionBlocks(uint32_t size, uint32_t num = 1); void SetDefaultEncryptionBlockSize(uint32_t blk); void SetDestCpu(DestinationCPU::Type); void SetDestDevice(DestinationDevice::Type); void SetAuthType(Authentication::Type); void SetEncryptType(Encryption::Type); void SetChecksumType(Checksum::Type); void SetOwnerType(PartitionOwner::Type); void SetPartitionType(PartitionType::Type); void SetDpaCM(DpaCM::Type); void SetExceptionLevel(ExceptionLevel::Type); void SetSpkId(uint32_t); void SetTrustZone(TrustZone::Type); void SetEarlyHandoff(bool); void SetHivec(bool); void SetRevokeId(uint32_t); void SetSlrNum(uint8_t); void SetClusterNum(uint8_t id); void SetLockStepFlag(); void SetAesKeyFile(std::string filename); void SetUdfDataFile(std::string filename); void SetEncryptionKeySource(KeySource::Type type); void SetAuthBlockAttr(size_t blocksizeattr); void SetPufHdLocation(PufHdLoc::Type); void SetReserveLength(uint64_t length, bool flag); void SetDelayAuth(bool flag); void SetTcmBootFlag(); void SetTcmARegion(uint64_t tcm_a_region); void SetTcmBRegion(uint64_t tcm_b_region); void SetTcmCRegion(uint64_t tcm_c_region); std::string GetUdfDataFile(void); std::vector& GetEncryptionBlocks(void); uint32_t GetDefaultEncryptionBlockSize(void); KeySource::Type GetEncryptionKeySource(void); DpaCM::Type GetDpaCM(void); uint32_t GetRevokeId(void); PufHdLoc::Type GetPufHdLocation(void); std::string GetOutputFileFromBifSection(std::string, std::string, PartitionType::Type); bool IsVersalNetSeries(void) { return versalNetSeries; } void Dump(void) { LOG_INFO("Filename: %s", filename.c_str()); if (alignment.IsSet()) { LOG_INFO(" Alignment: %x", alignment.Value()); } if (offset.IsSet()) { LOG_INFO(" Offset: %x", offset.Value()); } if (reserve.IsSet()) { LOG_INFO(" Reserve: %x", reserve.Value()); } if (load.IsSet()) { LOG_INFO(" Load: %x", load.Value()); } } //private: std::string aesKeyFile; std::string spkFile; std::string sskFile; std::string ppkFile; std::string pskFile; std::string spkSignatureFile; bool bootImage; bool pmuFwImage; bool pmcData; std::string presignFile; std::string acFile; std::string udfDataFile; Encryption::Type encryptType; Authentication::Type authType; Checksum::Type checksumType; PartitionOwner::Type ownerType; PartitionType::Type partitionType; DestinationCPU::Type destCPUType; DestinationDevice::Type destDeviceType; ExceptionLevel::Type exceptionLevel; TrustZone::Type trustzone; DpaCM::Type dpaCM; PufHdLoc::Type pufHdLoc; uint8_t slrNum; uint8_t clusterNum; bool tcmBoot; uint64_t tcmARegionAddr; uint64_t tcmBRegionAddr; uint64_t tcmCRegionAddr; //no default declared Override alignment; Override offset; Override reserve; Override load; Override startup; bool bigEndian; bool a32Mode; uint32_t partitionId; uint32_t imageStoreId; bool boot; bool user; bool Static; bool Protected; bool multiboot; bool noautostart; bool early_handoff; bool bootloader; bool hivec; bool lockstep; KeySource::Type keySrc; size_t authblockattr; size_t pid; std::vector blocks; uint32_t defBlockSize; uint32_t revokeId; //no default declared uint32_t blockSize; uint32_t spkSelect; bool spkSelLocal; uint32_t spkId; bool spkIdLocal; int fileType; std::string bifSection; std::string filename; std::vector filelist; bool updateReserveInPh; Arch::Type arch; bool delayAuth; bool erasePartition; private: bool versalNetSeries; }; /******************************************************************************/ class ImageBifOptions { public: ImageBifOptions() : imageId(0x1c000000) , imageName("default_subsys") , delayHandoff(false) , delayLoad(false) , memCopyAddr(0xFFFFFFFFFFFFFFFF) , imageType(PartitionType::RESERVED) , uniqueId(0xFFFFFFFF) , parentUniqueId(0xFFFFFFFF) , functionId(0xFFFFFFFF) , pcrNumber(0xFFFF) , pcrMeasurementIndex(0xFFFF) , slrConfigCnt(0) , slrConfigPartitionIndex(0) { partitionBifOptionsList.clear(); } void SetDelayHandoff(bool flag); void SetDelayLoad(bool flag); void SetImageId(uint32_t id) { imageId = id; } void SetImageName(std::string name) { imageName = name; } void SetUniqueId(uint32_t id) { uniqueId = id; } void SetParentUniqueId(uint32_t id) { parentUniqueId = id; } void SetFunctionId(uint32_t id) { functionId = id; } void SetMemCopyAddress(uint64_t addr) { memCopyAddr = addr; } void SetImageType(PartitionType::Type type) { imageType = type; } void SetPcrNumber(uint16_t num) { if ((2 > num) || (num > 7)) { LOG_ERROR("'pcr' is specified as '%d' for the Image:'%s'\n\t The permitted values range from 2 to 7.", num, GetImageName().c_str()); } pcrNumber = num; } void SetPcrMeasurementIndex(uint16_t pcrIndex) { pcrMeasurementIndex = pcrIndex; } uint32_t GetImageId(void) { return imageId; } std::string GetImageName(void) { return imageName; } uint32_t GetUniqueId(void) { return uniqueId; } uint32_t GetParentUniqueId(void) { return parentUniqueId; } uint32_t GetFunctionId(void) { return functionId; } void GetMemCopyAddress(uint64_t addr) { memCopyAddr = addr; } void GetImageType(PartitionType::Type type) { imageType = type; } bool GetDelayHandoff(void) { return delayHandoff; } bool GetDelayLoad(void) { return delayLoad; } uint64_t GetMemCopyAddress(void) { return memCopyAddr; } PartitionType::Type GetImageType(void) { return imageType; } uint16_t GetPcrNumber(void) { return pcrNumber; } uint16_t GetPcrMeasurementIndex(void) { return pcrMeasurementIndex; } std::list partitionBifOptionsList; uint32_t slrConfigCnt; uint32_t slrConfigPartitionIndex; std::list slrConfigPdiInfo; private: uint32_t imageId; std::string imageName; bool delayHandoff; bool delayLoad; uint64_t memCopyAddr; PartitionType::Type imageType; uint32_t uniqueId; uint32_t parentUniqueId; uint32_t functionId; uint32_t pcrNumber; uint32_t pcrMeasurementIndex; }; /******************************************************************************/ class BifOptions { public: BifOptions(Arch::Type architecture, const char* name); void Add(PartitionBifOptions* currentPartitionBifOptions, ImageBifOptions* currentImageBifOptions = NULL); void AddFiles(int type, std::string filename); void CheckForSameKeyandKeySrcPair(std::vector> aesKeyandKeySrc); void CheckForBadKeyandKeySrcPair(std::vector> aesKeyandKeySrc, std::string aesFilename); void SetRegInitFileName(std::string filename); void SetUdfBHFileName(std::string filename); void SetPmufwImageFileName(PartitionBifOptions* currentPartitionBifOptions); void SetPPKFileName(std::string filename); void SetPSKFileName(std::string filename); void SetSPKFileName(std::string filename); void SetSSKFileName(std::string filename); void SetSPKSignFileName(std::string filename); void SetBHSignFileName(std::string filename); void SetHeaderSignFileName(std::string filename); void SetBHKeyFileName(std::string filename); void SetPUFHelperFileName(std::string filename); void SetBHKekIVFileName(std::string filename); void SetBbramKekIVFileName(std::string filename); void SetEfuseKekIVFileName(std::string filename); void SetEfuseUserKek0IVFileName(std::string filename); void SetEfuseUserKek1IVFileName(std::string filename); void SetUserKeysFileName(std::string filename); void ParseUserKeyFile(std::string filename); void SetFamilyKeyFileName(std::string filename); void SetAESKeyFileName(std::string filename); void SetEncryptionKeySource(KeySource::Type type); void SetBootDevice(BootDevice::Type type); void SetBootDeviceAddress(uint32_t address); void SetBootVectorArray(uint32_t vector); void SetXipMode(); void SetFsblFilename(std::string); void SetTotalPmcFwSize(uint32_t); void SetPmcFwSize(uint32_t); void SetPPKSelection(uint32_t ppkSelection); void SetSPKSelection(uint32_t spkSelection); void SetSpkId(uint32_t spkId); void SetHeaderAuthentication(); void SetSmapWidth(uint32_t); void SetSplitMode(SplitMode::Type type); void SetSplitFmt(File::Type type); void SetPmcdataFile(const std::string & filename); void ClearPmcCdoFileList(); void SetPmcCdoFileList(const std::string & filename); void SetPdiId(uint32_t id); void SetGroupName(std::string name); void SetParentId(uint32_t id); void SetBhRsa(BhRsa::Type value); void SetPufHdLoc(PufHdLoc::Type value); void SetDpaCM(DpaCM::Type value); void SetHeaderAC(bool flag); void SetHeaderEncryption(bool flag); void SetTotalpmcdataSize(uint32_t size); void SetAuthOnly(AuthOnly::Type type); void SetOptKey(OptKey::Type type); void SetPufMode(PufMode::Type type); void SetShutterValue(uint32_t value); void SetPufRingOscilltorSwapConfigValue(uint32_t value); void SetDiceEnable(); void InsertEncryptionBlock(uint32_t size); void SetCore(Core::Type type); void SetMetaHeaderEncryptionKeySource(KeySource::Type type, bool versalNetSeries); void SetMetaHeaderEncryptType(Encryption::Type type); void SetMetaHeaderEncryptionKeyFile(std::string file); void SetMetaHeaderAuthType(Authentication::Type type); void SetPufHdinBHFlag(); void SetAuthJtagRevokeID(uint32_t value); void SetAuthJtagDeviceDna(std::string string); void SetAuthJtagTimeOut(uint32_t value); void SetPmcDataAesFile(std::string filename); void SetRevokeId(uint32_t id); std::string GetGroupName(void); std::string GetAESKeyFileName(void); std::string GetRegInitFileName(); OptKey::Type GetAesOptKeyFlag(void); std::vector& GetEncryptionBlocksList(void); BhRsa::Type GetBhRsa(void); DpaCM::Type GetDpaCM(void); BootDevice::Type GetBootDevice(void); uint32_t GetBootDeviceAddress(void); uint32_t GetShutterValue(void); uint32_t GetPufRingOscilltorSwapConfigValue(void); DICE::Type GetDice(void); std::string GetHeaderSignatureFile(void); PufMode::Type GetPufMode(void); PufHdLoc::Type GetPufHdLoc(void); OptKey::Type GetOptKey(void); void SetIdCode(uint32_t id); void SetExtendedIdCode(uint32_t id); void SetPdiType(PartitionType::Type type); void SetBypassIdcodeFlag(bool flag); void SetAHwRoTFlag(bool flag); void SetSHwRoTFlag(bool flag); AuthOnly::Type GetAuthOnly(void); uint32_t GetPpkSelection(void); uint32_t GetSpkSelection(void); uint32_t GetSmapWidth(void); std::string GetPPKFileName(void); std::string GetPSKFileName(void); std::string GetSPKFileName(void); std::string GetSSKFileName(void); uint32_t GetSpkId(void); bool GetHeaderAC(void); bool GetHeaderEncyption(void); bool GetPpkSelectionGlobal(void); bool GetSpkSelectionGlobal(void); bool GetSpkIdGlobal(void); bool GetXipMode(void); std::string GetBhKeyFile(void); std::string GetPufHelperFile(void); std::string GetPmuFwImageFile(void); std::string GetBHKekIVFile(void); std::string GetBbramKekIVFile(void); std::string GetEfuseKekIVFile(void); std::string GetEfuseUserKek0IVFile(void); std::string GetEfuseUserKek1IVFile(void); std::string GetUserKeysFileName(void); std::string GetUdfBhFile(void); SplitMode::Type GetSplitMode(void); uint32_t GetIdCode(void); uint32_t GetExtendedIdCode(void); bool GetBypassIdcodeFlag(void); File::Type GetSplitFormat(void); std::vector& GetBootVectorArray(void); std::string GetSPKSignFileName(void); std::string GetBHSignFileName(void); uint32_t GetPmcCdoLoadAddress(void); std::string GetPmcdataFile(void); std::vector GetPmcCdoFileList(void); std::string GetPmcDataAesFile(void); uint32_t GetTotalPmcFwSize(void); uint32_t GetPmcFwSize(void); uint8_t* GetPmcDataBuffer(void); uint32_t GetTotalpmcdataSize(void); uint32_t GetPdiId(void); uint32_t GetParentId(void); KeySource::Type GetEncryptionKeySource(void); std::string GetKeySourceName(KeySource::Type type); bool GetPufHdinBHFlag(void); std::string GetFamilyKeyFileName(); std::list aie_elfs; std::list imageBifOptionList; std::list partitionBifOptionList; Core::Type GetCore(void); uint32_t GetRevokeId(); //Versal Binary::Address_t pmcCdoLoadAddress; uint32_t idCode; uint32_t extendedIdCode; PartitionType::Type pdiType; bool bypassIdCode; bool aHwrot; bool sHwrot; uint32_t pmcdataSize; uint32_t totalpmcdataSize; uint8_t* pmcDataBuffer; MetaHdrInfo metaHdrAttributes; AuthJtagInfo authJtagInfo; uint32_t slrBootCnt; uint32_t slrConfigCnt; PartitionBifOptions* lastPartitionBifOption; BootDevice::Type bootDevice; std::vector pmcdataBlocks; uint8_t slrNum; private: std::string pmcDataAesFile; std::string regInitFile; std::string udfBhFile; std::string pmuFwImageFile; std::string pmcdataFile; std::vector pmcCdoFileList; std::string fsblFilename; std::string ppkFile; std::string pskFile; std::string spkFile; std::string sskFile; std::string spkSignatureFile; std::string bhSignatureFile; std::string headerSignatureFile; std::string bhKeyFile; std::string pufHelperFile; std::string bhKekIVFile; std::string bbramKekIVFile; std::string efuseKekIVFile; std::string efuseUserKek0IVFile; std::string efuseUserKek1IVFile; std::string familyKeyFile; std::string aesKeyFile; std::string userKeyFile; KeySource::Type keySourceEncryption; uint32_t bootDeviceAddress; std::vector bootvectors; BhRsa::Type bhAuthEnable; PufHdLoc::Type pufHdLoc; bool pufHdinBHEnable; AuthOnly::Type authOnly; PufMode::Type pufMode; OptKey::Type optKey; uint32_t shutterVal; uint32_t pufRoSwapConfigVal; DpaCM::Type dpaCM; DICE::Type dice; bool xipMode; uint32_t ppkSelect; bool isPPKSelectGlobal; uint32_t spkSelect; bool isSPKSelectGlobal; uint32_t spkId; bool isSpkIdGlobal; bool headerAuthParam; bool createHeaderAC; bool doHeaderEncryption; SplitMode::Type splitMode; File::Type splitFmt; std::string groupname; Arch::Type arch; std::vector blocks; Core::Type core; // Versal uint32_t pdiId; uint32_t parentId; uint32_t revokeId; uint32_t smapWidth; }; #endif xilinx-bootgen-2024.2/bifscanner.h000077500000000000000000000051001475706442400170500ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BIFSCANNER_H_ #define _BIFSCANNER_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ // Only include FlexLexer.h if it hasn't been already included #if ! defined(yyFlexLexerOnce) #undef yyFlexLexer #define yyFlexLexer bifFlexLexer #include "FlexLexer.h" #endif // Override the interface for yylex since we namespaced it #undef YY_DECL #define YY_DECL int BIF::FlexScanner::yylex() // Include Bison for types / tokens #include "bif.tab.hpp" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ namespace BIF { class FlexScanner : public yyFlexLexer { public: // save the pointer to yylval so we can change it, and invoke scanner int yylex(BIF::BisonParser::semantic_type * lval, BIF::BisonParser::location_type* loc) { yylval = lval; yylloc = loc; return yylex(); } void comment(); std::string filename; private: // Scanning function created by Flex; make this private to force usage // of the overloaded method so we can get a pointer to Bison's yylval int yylex(); // point to yylval (provided by Bison in overloaded yylex) BIF::BisonParser::semantic_type * yylval; BIF::BisonParser::location_type * yylloc; }; } #endif xilinx-bootgen-2024.2/binary-versal.cpp000077500000000000000000000161631475706442400200620ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "binary-versal.h" #include "bootgenexception.h" #include "options.h" #include "stringutils.h" #include "bifoptions.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalBinary::~VersalBinary() { for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { delete *i; } Sections.clear(); } /******************************************************************************/ void VersalBinary::StackAndAlign(Options& options) { std::string logmsg; Binary::Address_t runningAddress = options.GetBaseAddress(); Binary::Address_t reservedAddress = 0; Binary::Address_t unalignedRunningAddress = 0; for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& sec(**i); if (!sec.continuation) { if (runningAddress < reservedAddress) { runningAddress = reservedAddress; } } if (sec.isBootloader) { if (options.totalHeadersSize == 0) { options.totalHeadersSize = runningAddress; } if (options.allHeaderSize == 0) { options.allHeaderSize = options.totalHeadersSize - options.bootheaderSize; } if (options.bootloaderSize == 0) { options.bootloaderSize = runningAddress; } else { options.bootloaderSize += sec.Length; } } if (sec.Length == 0) { LOG_WARNING("Section %s length is zero"); } if (sec.Address != 0) { if (runningAddress > sec.Address) { LOG_DUMP_IMAGE(*this); LOG_ERROR("Section %s offset of 0x%X overlaps with prior section end address of 0x%X", sec.Name.c_str(), sec.Address, runningAddress); } } else { if (sec.Alignment) { runningAddress = (runningAddress + sec.Alignment - 1) & ~(sec.Alignment - 1); } sec.Address = runningAddress; } if (sec.Reserve != 0) { reservedAddress = sec.Address + sec.Reserve; } runningAddress = sec.Address + sec.Length; runningAddress = (runningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); // align if necessary if (!sec.Name.compare("BootHeader")) { options.bootheaderSize = runningAddress; } if ((!StringUtils::GetExtension(sec.Name).compare(".sha384") || !StringUtils::GetExtension(sec.Name).compare(".sha256")) && sec.Name.find(StringUtils::BaseName(options.GetFsblFilename())) != std::string::npos) { options.totalHeadersSize = runningAddress; options.allHeaderSize = options.totalHeadersSize - options.bootheaderSize; options.bootloaderSize = runningAddress; } if (sec.isBootloader) { options.bootloaderSize = runningAddress - options.bootloaderSize; } } if (options.bifOptions->GetHeaderAC()) { /* Substract the size of AC, since AC sits infront of headers */ options.totalHeadersSize -= VERSAL_AC_SIZE; options.allHeaderSize -= VERSAL_AC_SIZE; options.bootloaderSize -= VERSAL_AC_SIZE; } runningAddress = options.GetBaseAddress(); //Binary::Address_t unalignedRunningAddress = 0; std::string acBootloader = ""; for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& section(**i); if (!section.Name.compare("BootHeader")) { unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); } if (section.isBootloader) { acBootloader = section.Name + ".sha384"; } } for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& section(**i); if (!section.Name.compare(acBootloader)) { section.Address = runningAddress; runningAddress = section.Address + section.Length; //unalignedRunningAddress = section.Address + section.Length; //runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); } } for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& section(**i); if (section.isBootloader) { section.Address = runningAddress; unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); if (section.Reserve != 0) { runningAddress = section.Address + section.Length; } } } for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& section(**i); /* Write to output file */ if (section.Name.compare("BootHeader") && !(section.isBootloader) && section.Name.compare(acBootloader)) { if (section.Address < runningAddress) { section.Address = runningAddress; } unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); if (section.Reserve != 0) { runningAddress = section.Address + section.Reserve; } } } TotalSize = runningAddress; } xilinx-bootgen-2024.2/binary-versal.h000077500000000000000000000040531475706442400175220ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _VERSAL_BINARY_H_ #define _VERSAL_BINARY_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include "binary.h" class Section; class Options; class Binary; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define WORD_SIZE_IN_BYTES 4 #define VERSAL_AC_SIZE 0xE60 typedef std::list SectionList; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalBinary : public Binary { public: VersalBinary() {}; ~VersalBinary(); void StackAndAlign(Options& options); }; #endif xilinx-bootgen-2024.2/binary.cpp000077500000000000000000000155661475706442400165760ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "binary.h" #include "bootgenexception.h" #include "options.h" #include "stringutils.h" #include "bifoptions.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ Binary::~Binary() { for(SectionList::iterator i=Sections.begin(); i!=Sections.end(); i++) { delete *i; } Sections.clear(); } /******************************************************************************/ void Binary::StackAndAlign(Options& options) { std::string logmsg; Binary::Address_t runningAddress = options.GetBaseAddress(); Binary::Address_t reservedAddress = 0; for (SectionList::iterator i = Sections.begin(); i != Sections.end(); i++) { Section& sec(**i); if (!sec.continuation) { if (runningAddress < reservedAddress) { runningAddress = reservedAddress; } } if (sec.isBootloader) { options.totalHeadersSize = runningAddress; options.allHeaderSize = options.totalHeadersSize - options.bootheaderSize; options.bootloaderSize = runningAddress; } if (sec.Length == 0) { LOG_WARNING("Section %s length is zero"); } if (sec.Address != 0) { if (runningAddress > sec.Address) { LOG_DUMP_IMAGE(*this); LOG_ERROR("Section %s offset of 0x%X overlaps with prior section end address of 0x%X", sec.Name.c_str(), sec.Address, runningAddress); } } else { if (sec.Alignment) { runningAddress = (runningAddress + sec.Alignment - 1) & ~(sec.Alignment - 1); } sec.Address = runningAddress; } if (sec.Reserve != 0) { reservedAddress = sec.Address + sec.Reserve; } runningAddress = sec.Address + sec.Length; runningAddress = (runningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); // align if necessary if (!sec.Name.compare("BootHeader")) { options.bootheaderSize = runningAddress; } if ((!StringUtils::GetExtension(sec.Name).compare(".sha384") || !StringUtils::GetExtension(sec.Name).compare(".sha256")) && sec.Name.find(StringUtils::BaseName(options.GetFsblFilename())) != std::string::npos) { options.bootloaderSize += sec.Length; } if (sec.isBootloader) { options.bootloaderSize = runningAddress - options.bootloaderSize; } } TotalSize = runningAddress; } /******************************************************************************/ Section::Section(const std::string& name, Binary::Length_t length) : Name(name) , Address(0) , Length(length) , Alignment(0) , Reserve(0) , continuation(false) , isPartitionData(false) , isCertificate(false) , isBitStream(false) , isBootloader(false) , isPmcdata(false) , isFirstElfSection(false) , index(0) , firstChunkSize(0) , partitionNum(0xFF) { std::string logmsg; Data = new uint8_t[length]; if (Data == 0) { LOG_ERROR("Memory allocation error, size = %d" , length); } } /******************************************************************************/ Section::~Section() { if (Data != NULL) { delete[] Data; } } /******************************************************************************/ void Section::PadToWordAlignment(uint32_t headPad, uint32_t tailPad) { if (headPad == 0 && tailPad == 0) { return; } /* The aligned byte size will be anywhere from 0 to 6 bytes longer than the original section data. */ Binary::Length_t newLength = Length + headPad + tailPad; uint8_t* newData = new uint8_t[newLength]; /* Pad the head */ memset(newData, 0, headPad); /* Move the bulk */ memmove(newData + headPad, Data, Length ); /* Pad the tail */ memset(newData + Length + headPad, 0, tailPad); delete[] Data; Data = newData; Length = newLength; } /******************************************************************************/ void Section::IncreaseLengthAndPadTo(Binary::Length_t newLength, uint8_t padding) { if (newLength < Length) { LOG_DEBUG(DEBUG_STAMP, "Resize length is less than original length"); LOG_ERROR("Section resize issue for authentication"); } uint8_t* newDataPtr = new uint8_t[newLength]; memcpy(newDataPtr,Data,Length); memset(newDataPtr+Length,padding,newLength - Length); delete[] Data; Data = newDataPtr; Length = newLength; } /******************************************************************************/ void Section::Summarize(std::ostream& o) { o << Name << " : " << std::hex << Length; uint32_t checksum = 0; for(uint32_t i=0; i #include #include #include #include class Section; class Options; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define WORD_SIZE_IN_BYTES 4 typedef std::list SectionList; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Binary { public: Binary() : TotalSize(0) { } virtual ~Binary(); typedef uint64_t Address_t; typedef uint64_t Length_t; virtual void StackAndAlign(Options& options); //void Dump(std::ostream& s); static bool CheckAddress(uint64_t addr) { return addr < 0x100000000ULL; } SectionList Sections; Length_t TotalSize; }; /******************************************************************************/ class Section { public: Section(const std::string& name, Binary::Length_t length); ~Section(); std::string Name; Binary::Address_t Address; Binary::Length_t Length; uint32_t Alignment; Binary::Length_t Reserve; uint8_t* Data; uint64_t firstChunkSize; bool continuation; bool isPartitionData; bool isCertificate; bool isFirstElfSection; bool isBitStream; bool isBootloader; bool isPmcdata; uint32_t partitionNum; int index; Binary::Address_t WordAddress() { return Address / sizeof(uint32_t); } void PadToWordAlignment(uint32_t headPad, uint32_t tailPad); void IncreaseLengthAndPadTo(Binary::Length_t length, uint8_t padding); void Summarize(std::ostream& out); void IncreaseLengthAndPadSHA3(Binary::Length_t newLength); }; #endif xilinx-bootgen-2024.2/binfile.cpp000077500000000000000000000152501475706442400167100ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "outputfile.h" #include "systemutils.h" #include /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void BinFile::Open() { std::string fName1 = filename.c_str(); std::string fName2 = filename.c_str(); if ((qspiDualMode == QspiMode::PARALLEL_LQSPI) || (qspiDualMode == QspiMode::PARALLEL_GQSPI) || ((qspiDualMode == QspiMode::STACKED) && (totalImageSize > qspiSizeInBytes))) { fName1 = fName1.substr(0, fName1.find_last_of(".")); //remove extension fName1.append("_1.bin"); fName2 = fName2.substr(0, fName2.find_last_of(".")); //remove extension fName2.append("_2.bin"); ofs1.open(fName2.c_str(), std::ios::binary); if (!ofs1) { LOG_ERROR("Cannot write output file : %s", fName2.c_str()); } } ofs.open(fName1.c_str(), std::ios::binary); if (!ofs) { LOG_ERROR("Cannot write output file : %s", filename.c_str()); } } /******************************************************************************/ void BinFile::Append() { ofs.open(filename.c_str(), std::ios::binary | std::ios::app); } /******************************************************************************/ void BinFile::WritePreamble() { // do nothing } /******************************************************************************/ void BinFile::WritePostscript() { // do nothing } /******************************************************************************/ void BinFile::Close() { ofs.close(); } /******************************************************************************/ void BinFile::Fill(Binary::Address_t start, Binary::Address_t end, bool doFill, uint8_t fillByte) { /* ignore "doFill". Always fill! */ size_t length = end - start; if (qspiDualMode == QspiMode::PARALLEL_GQSPI || qspiDualMode == QspiMode::PARALLEL_LQSPI) { for (size_t i = 0; i < length/2; i++) { ofs.put((char)fillByte); ofs1.put((char)fillByte); } } else if (qspiDualMode == QspiMode::STACKED) { Binary::Length_t write_size_1 = 0; Binary::Length_t write_size_2 = 0; if ((start + length) <= qspiSizeInBytes) { for (size_t i = 0; i < length; i++) { ofs.put((char)fillByte); } } else { if (start <= qspiSizeInBytes) { write_size_1 = qspiSizeInBytes - start; for (size_t i = 0; i < write_size_1; i++) { ofs.put((char)fillByte); } } write_size_2 = length - write_size_1; for (size_t i = 0; i < write_size_2; i++) { ofs1.put((char)fillByte); } } } else { for (size_t i = 0; i < length; i++) { ofs.put((char)fillByte); } } totalByteOutputCount += length; } /******************************************************************************/ void BinFile::Write(Binary::Address_t start, Binary::Length_t length, const uint8_t *buffer) { uint8_t* writedata = new uint8_t[length]; memcpy(writedata, buffer, length); if (qspiDualMode == QspiMode::PARALLEL_GQSPI) { uint8_t* buffer1 = new uint8_t[length / 2]; uint8_t* buffer2 = new uint8_t[length / 2]; for (uint64_t i = 0, j = 0; i < length; i += 2, j++) { buffer1[j] = (writedata[i]); buffer2[j] = (writedata[i + 1]); } ofs.write((const char*)buffer1, length / 2); ofs1.write((const char*)buffer2, length / 2); } else if (qspiDualMode == QspiMode::PARALLEL_LQSPI) { uint8_t* buffer1 = new uint8_t[length / 2]; uint8_t* buffer2 = new uint8_t[length / 2]; int k = 0; for (uint64_t i = 0; i < length; i += 2, k++) { uint8_t lsb = 0, lsbNxt = 0; uint8_t msb = 0, msbNxt = 0; uint8_t tempData = writedata[i]; uint8_t tempDataNxt = writedata[i + 1]; for (int j = 0; j < 4; j++) { lsb = lsb | ((tempData & 0x1) << j); msb = msb | (((tempData & 0x2) >> 1) << j); tempData = tempData >> 2; lsbNxt = lsbNxt | ((tempDataNxt & 0x1) << j); msbNxt = msbNxt | (((tempDataNxt & 0x2) >> 1) << j); tempDataNxt = tempDataNxt >> 2; } buffer1[k] = (lsb << 4) | lsbNxt; buffer2[k] = (msb << 4) | msbNxt; } ofs.write((const char*)buffer1, length / 2); ofs1.write((const char*)buffer2, length / 2); } else if (qspiDualMode == QspiMode::STACKED) { Binary::Length_t write_size_1 = 0; Binary::Length_t write_size_2 = 0; if((start + length) <= qspiSizeInBytes) { ofs.write((const char*)writedata, length); } else { if (start <= qspiSizeInBytes) { write_size_1 = qspiSizeInBytes - start; ofs.write((const char*)writedata, write_size_1); } write_size_2 = length - write_size_1; ofs1.write((const char*)(writedata + write_size_1), write_size_2); } } else { ofs.write((const char*)writedata, length); } totalByteOutputCount += length; delete [] writedata; } xilinx-bootgen-2024.2/bitutils-versal.cpp000077500000000000000000000116411475706442400204310ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "bootgenexception.h" #include "bitutils-versal.h" #include #include #include #include "bootimage.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalBitFile::VersalBitFile(std::istream& stream0) : BitFile(stream0), temp(NULL), encryptType(Encryption::None) { } /******************************************************************************/ VersalBitFile::~VersalBitFile() { if (temp) { delete temp; } } /******************************************************************************/ void VersalBitFile::Copy(OutputStream* os) { os->swap_cfi_bytes = true; os->Alloc(header.dataByteLength + 32); if (header.dataByteLength % 4) { LOG_ERROR("Bitstream length %d - is not word aligned", header.dataByteLength); } uint32_t bytes = header.dataByteLength / sizeof(uint8_t); uint8_t cfiBytes[16] = { 0 }; uint32_t numCfiLines = bytes / 16; for (uint32_t i = 0; i < numCfiLines; i++) { is.ReadCfiLine(cfiBytes); os->WriteCfiLine(cfiBytes); } } /******************************************************************************/ void VersalBitFile::CopyNpi(OutputStream* os) { os->Alloc(header.dataByteLength + 32); if (header.dataByteLength % 4) { LOG_ERROR("NPI length %d - is not word aligned", header.dataByteLength); } uint32_t bytes = header.dataByteLength / sizeof(uint8_t); uint8_t npiBytes[4] = { 0 }; uint32_t numnpiLines = bytes / 4; bool change_endianness = false; /* Read ID value (XNLX/CDO) from CDO Header to identify endianness */ /* 8 characters (npi line) + one new line character = 9 characters */ //is.Skip(9); is.ReadNpiLine(npiBytes); is.ReadNpiLine(npiBytes); uint32_t npi_word = ReadBigEndian32(npiBytes); if ((npi_word != 0x584c4e58) && (npi_word != 0x584e4c58) && (npi_word != 0x004f4443) && (npi_word != 0x43444f00)) { LOG_ERROR("Invalid CDO format - incorrect identification word (XLNX/CDO) - 0x%x", npi_word); } if ((npi_word == 0x584c4e58) || (npi_word == 0x004f4443)) { /* Convert BE CDOs to LE */ change_endianness = true; LOG_WARNING("CDO is in Big Endian format. Big Endian CDOs are deprecated. Please use little endian CDOs."); } /* HACK - Need correction */ /* Few CDO files have 0x prepended to each word So setting the stream to start and reading the banner again to reach the actual CDO word */ is.Start(); ReadRbtHeader(); for (uint32_t i = 0; i < numnpiLines; i++) { is.ReadNpiLine(npiBytes); if (change_endianness) { npi_word = ReadBigEndian32(npiBytes); } else { npi_word = ReadLittleEndian32(npiBytes); } os->WriteLong(npi_word); } } /******************************************************************************/ OutputStream* VersalBitFile::GetOutputStreamType(void) { return new OutputStream_LE(); } /******************************************************************************/ bool VersalBitFile::GetBitStripFlag(void) { return false; } /******************************************************************************/ bool VersalBitFile::GetBitPadFlag(bool) { return false; } /******************************************************************************/ bool VersalBitFile::GetPreserveHeaderFlag(void) { return false; } /******************************************************************************/ void VersalBitFile::ComparePartsDataBase(const std::string&) { /* TO-DO */ return; } xilinx-bootgen-2024.2/bitutils-versal.h000077500000000000000000000040721475706442400200760ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BITUTILS_VERSAL_H_ #define _BITUTILS_VERSAL_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bitutils.h" /* Forward Class Reference */ class OutputStream_LE; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /****************************************************************************** VersalBitFile ******************************************************************************/ class VersalBitFile : public BitFile { public: VersalBitFile(std::istream& stream); ~VersalBitFile(); OutputStream* GetOutputStreamType(void); bool GetBitStripFlag(void); bool GetBitPadFlag(bool); bool GetPreserveHeaderFlag(void); void DummyRead(void) { }; void ComparePartsDataBase(const std::string&); void Copy(OutputStream* os); void CopyNpi(OutputStream* os); protected: Encryption::Type encryptType; OutputStream_BE* temp; }; #endif xilinx-bootgen-2024.2/bitutils.cpp000077500000000000000000000273721475706442400171470ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "bootgenexception.h" #include "bitutils.h" #include #include #include #include "bootimage.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define NO_IO_ERROR 0 #define DATA_SYNC_WORD 0xAA995566 #define TIMER_CMD_WORD 0x30022001 /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ BitFile::BitFile(std::istream& stream0) : is(stream0), temp(NULL), encryptType(Encryption::None) { } /******************************************************************************/ BitFile::~BitFile() { if (temp) { delete temp; } } /******************************************************************************/ void BitFile::ParseBit(BootImage& bi) { switch (is.Peek()) { case 0x00: ReadBITHeader_x4k(); break; case 0x19: ReadBITHeader_NeoCAD(); break; case 'X': case 'x': ReadRbtHeader(); break; default: LOG_DEBUG(DEBUG_STAMP, "First Byte in Bitstream - 0x%X", is.Peek()); LOG_ERROR("Bitstream parsing error !!! Unsupported BIT file"); } inputPackageName = bi.options.GetDevicePackageName(); if(bi.partitionOutput->Type() != PartitionArch::FPGA) { ValidateDeviceName(header.devicePackageName); } } /******************************************************************************/ void BitFile::ReadBITHeader_x4k( ) { header.unknownString = is.ReadPascalString( ); header.unknownValue = is.ReadShort( ); header.fieldSeparatorA = is.ReadByte( ); header.designName = is.ReadPascalString(); header.fieldSeparatorB = is.ReadByte( ); header.devicePackageName= is.ReadPascalString(); header.fieldSeparatorC = is.ReadByte( ); header.designDate = is.ReadPascalString(); header.fieldSeparatorD = is.ReadByte( ); header.designTime = is.ReadPascalString(); if( ( header.fieldSeparatorA != 'a' ) || ( header.fieldSeparatorB != 'b' ) || ( header.fieldSeparatorC != 'c' ) || ( header.fieldSeparatorD != 'd' ) || ( header.designName.size() == 0 ) || ( header.devicePackageName.size() == 0 ) || ( header.designDate.size() == 0 ) || ( header.designTime.size() == 0 ) || ( header.unknownString != "\x0F\xF0\x0F\xF0\x0F\xF0\x0F\xF0" ) ) { LOG_ERROR("Bitstream parsing error !!! Invalid/Corrupted Bitstream Header"); } header.designDateAndTime = header.designDate + " " + header.designTime; header.fieldSeparatorE = is.ReadByte(); header.dataByteLength = is.ReadLong(); } /******************************************************************************/ void BitFile::ReadBITHeader_NeoCAD() { header.headerType = is.ReadByte(); header.designName = is.ReadCString(); header.deviceFamily = is.ReadCString(); header.devicePackageName = is.ReadCString(); header.designDateAndTime = is.ReadCString(); /* Skip unknown data */ is.Skip(sizeof(header.unknownData)); header.dataByteLength = is.ReadLong() / BITS_IN_BYTE; } /******************************************************************************/ void BitFile::Copy(OutputStream* os) { os->Alloc(header.dataByteLength + 32); if (header.dataByteLength % 4) { LOG_ERROR("Bitstream length %d - is not word aligned", header.dataByteLength); } int words = header.dataByteLength / sizeof(uint32_t); for(int i=0;iWriteLong(x); } } /******************************************************************************/ void BitFile::Strip(OutputStream* os) { os->Alloc(header.dataByteLength + 32); uint32_t cmdWord; /* In case of Zynq bitstreams, skip synchronization words, until we get the magic AA995566 */ do { cmdWord = is.ReadLong(); } while (cmdWord != DATA_SYNC_WORD); /* Dummy Read is necessary to move to next location where the actual bitstream starts FPGA encryption bitstream does not include this NOP data Zynq & ZynqMP encrypted bitstreams contain this NOP data */ DummyRead(); /* Now copy all command words, until we get a DESYNCH or REBOOT command */ BitCommand cmd; do { cmd.ReadWrite(is,os); } while (! (cmd.reg == BitCommand::CMD_reg && (cmd.value == BitCommand::DESYNCH_cmd || cmd.value == BitCommand::REBOOT_cmd))); /* Don't copy the DESYNCH or REBOOT command. */ os->Rewind(2*sizeof(uint32_t)); } /******************************************************************************/ void BitFile::ReadRbtHeader() { std::string line = is.ReadLine(); if ((line != "Xilinx ASCII Bitstream") && (line != "Xilinx ASCII CFI Deviceimage") && (line != "Xilinx ASCII NPI Deviceimage") && (line != "Xilinx ASCII PSAXIMM Deviceimage")) { LOG_DEBUG(DEBUG_STAMP, "Wrong Line - %s", line.c_str()); LOG_ERROR("Bitstream parsing error !!! First line of RBT has incorrect starting line"); } if (line == "Xilinx ASCII Bitstream") { is.SetRbt(); } while (true) { line = is.ReadLine(); if (line == "") { break; } size_t colon = line.find(':'); if (colon != std::string::npos) { std::string field = line.substr(0, colon); size_t valuePtr = line.find_first_not_of(" \t", colon + 1); if (valuePtr != std::string::npos) { if (field == "Design name") { header.designName = line.substr(valuePtr); } else if (field == "Part") { header.devicePackageName = line.substr(valuePtr); } else if (field == "Date") { header.designDateAndTime = line.substr(valuePtr); } else if (field == "Bits") { header.dataByteLengthString = line.substr(valuePtr); uint32_t y; std::stringstream x(header.dataByteLengthString); x >> y; header.dataByteLength = y / BITS_IN_BYTE; break; } } } } ValidateDeviceName(header.devicePackageName); } /******************************************************************************/ void BitFile::ValidateDeviceName(const std::string& packageName) { if (inputPackageName != "") { if (packageName.compare(0, inputPackageName.length(), inputPackageName) == 0) { return; } } else { ComparePartsDataBase(packageName); } } /******************************************************************************/ void BitFile::SetEncryptionType(Encryption::Type type) { encryptType = type; } /******************************************************************************/ OutputStream* ZynqBitFile::GetOutputStreamType(void) { return new OutputStream_LE(); } /******************************************************************************/ bool ZynqBitFile::GetBitStripFlag(void) { if (encryptType == Encryption::AES) { return true; } else { return false; } } /******************************************************************************/ bool ZynqBitFile::GetBitPadFlag(bool legacyFlag) { if (legacyFlag && (encryptType == Encryption::None)) { /* Don't pad to 32 bytes */ return false; } else { return true; } } /******************************************************************************/ void ZynqBitFile::ComparePartsDataBase(const std::string& packageName) { const char* parts[] = { "xc7z", "7z", "xa7z", "a7z", "xq7z", "q7z", NULL }; for (int i = 0; parts[i]; i++) { if (packageName.compare(0, strlen(parts[i]), parts[i]) == 0) { return; } } LOG_DEBUG(DEBUG_STAMP, "BIT file package name - %s", packageName.c_str()); LOG_ERROR("Partname %s in Bit file is incompatible with Zynq (Zynq 7000) parts", packageName.c_str()); } /******************************************************************************/ OutputStream* ZynqMpBitFile::GetOutputStreamType(void) { if(encryptType == Encryption::AES) { return new OutputStream_BE(); } else { return new OutputStream_LE(); } } /******************************************************************************/ bool ZynqMpBitFile::GetBitStripFlag(void) { return false; } /******************************************************************************/ bool ZynqMpBitFile::GetBitPadFlag(bool legacyFlag) { return false; } /******************************************************************************/ void ZynqMpBitFile::ComparePartsDataBase(const std::string& packageName) { const char* parts[] = { "xqzu", "xczu", "xazu", "xck", NULL }; for(int i=0; parts[i]; i++) { if (packageName.compare(0,strlen(parts[i]),parts[i]) == 0) { return; } } LOG_DEBUG(DEBUG_STAMP, "BIT file package name - %s", packageName.c_str()); LOG_ERROR("Partname %s in Bit file is incompatible with Zynq MP parts", packageName.c_str()); } /******************************************************************************/ void BitCommand::ReadWrite(InputStream_BE& is, OutputStream* os) { instruction = is.ReadLong(); os->WriteLong(instruction); word_type = Config_Word_Get_Type(); reg = Config_Word_Get_Register(); if (Config_Word_Get_Op() == kConfig_NOP_cmd) { count = 0; } else { if (word_type == cmd_word) { count = Config_Word_Get_Word_Count(); } else if (word_type == extension_word) { count = Config_Word_Get_Extension_Count(); } else { LOG_DEBUG(DEBUG_STAMP, "Bad command word in BIT stream: 0x%X", instruction); } } for (uint32_t i = 0;iWriteLong(x); if (i == 0) { value = x; } } } xilinx-bootgen-2024.2/bitutils.h000077500000000000000000000356521475706442400166140ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BITUTILS_H_ #define _BITUTILS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include "logger.h" #include "bootimage.h" /* Forward class references */ class OutputStream_LE; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define BITS_IN_BYTE 8 #define BITSTREAM_NOP 0x20000000 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class InputStream_BE { public: InputStream_BE(std::istream& stream0) : rbt(false),stream(stream0) {} void Read(uint8_t* dataBuffer, uint32_t dataByteLength) { stream.read((char*)dataBuffer,dataByteLength); } void Skip(int count) { stream.seekg(count,std::ios_base::cur); } void Back(int count) { count *= -1; stream.seekg(count, std::ios_base::cur); } uint8_t ReadByte() { uint8_t x; stream.read((char*)&x,1); return x; } int Peek() { return stream.peek(); } /* Read 2 bytes (16 bits) from the stream (big endian) */ uint16_t ReadShort() { uint16_t x; x = ((uint16_t)ReadByte()) << 8; x |= ReadByte(); return x; } /* Read 4 bytes (32 bits) from the stream (big endian) */ uint32_t ReadLong() { uint32_t x = 0; if (rbt) { std::string token = ReadLine(); if (token != "") { x = DecodeBinary(token); } } else { x = ((uint32_t)ReadByte()) << 24; x |= ((uint32_t)ReadByte()) << 16; x |= ((uint32_t)ReadByte()) << 8; x |= ReadByte(); } return x; } /* Read & Decode the binary data */ uint32_t DecodeBinary(const std::string &sBin) { /* Check for a bad string */ if (sBin.npos != sBin.find_first_not_of("01")) { LOG_DEBUG(DEBUG_STAMP,"Badly formed input string"); LOG_ERROR("Failed to read Bitstream !!!"); } /* Check for overflow */ if (sBin.length() > std::numeric_limits::digits) { LOG_DEBUG(DEBUG_STAMP, "The binary number is too big to convert to an unsigned int"); LOG_ERROR("Failed to read Bitstream !!!"); } /* For each binary digit, starting from the least significant digit, set the appropriate bit if the digit is not '0' */ unsigned nVal = 0; unsigned nBit = 0; std::string::const_reverse_iterator itr; for(itr=sBin.rbegin(); itr!=sBin.rend(); ++itr) { if (*itr == '1') { nVal |= (1<> (BITS_IN_BYTE * 0)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 1)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 2)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 3)) & 0xFF; assert(Size() <= maxsize); } }; /******************************************************************************/ class OutputStream_BE : public OutputStream { public: OutputStream_BE() { }; OutputStream_BE(size_t maxsize0) : OutputStream(maxsize0) {} ~OutputStream_BE() {} void WriteLong(uint32_t word) { *ptr++ = (word >> (BITS_IN_BYTE * 3)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 2)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 1)) & 0xFF; *ptr++ = (word >> (BITS_IN_BYTE * 0)) & 0xFF; assert(Size() <= maxsize); } }; /******************************************************************************/ class BitFileHeaderType { public: uint8_t headerType; std::string unknownString; uint32_t unknownValue; char fieldSeparatorA; std::string designName; char fieldSeparatorB; std::string devicePackageName; char fieldSeparatorC; std::string designDate; char fieldSeparatorD; std::string designTime; char fieldSeparatorE; uint32_t dataByteLength; std::string dataByteLengthString; uint8_t * bitStreamBuffer; std::string deviceFamily; std::string designDateAndTime; char unknownData[8]; BitFileHeaderType() : headerType(0) , dataByteLength(0) , unknownValue(0) , bitStreamBuffer(NULL) , unknownString() , fieldSeparatorA() , fieldSeparatorB() , fieldSeparatorC() , fieldSeparatorD() , fieldSeparatorE() { } } ; /******************************************************************************/ class BitFile { public: BitFile(std::istream& stream0); ~BitFile(); void ParseBitFpga(); virtual void ParseBit(BootImage& bi); virtual void SetEncryptionType(Encryption::Type); /* For Zynq/FPGA encrypted files only */ virtual void Strip(OutputStream* os); /* For ZynqMp files and Zynq/FPGA un-encrypted files */ virtual void Copy(OutputStream* os); virtual OutputStream* GetOutputStreamType(void) = 0; virtual bool GetBitStripFlag(void) = 0; virtual bool GetBitPadFlag(bool) = 0; virtual void DummyRead(void) = 0; virtual void ComparePartsDataBase(const std::string&) = 0; virtual void CopyNpi(OutputStream* os) {}; std::string inputPackageName; BitFileHeaderType header; protected: virtual void ReadBITHeader_x4k(); virtual void ReadBITHeader_NeoCAD(); virtual void ReadRbtHeader(); virtual void ValidateDeviceName(const std::string& packageName); Encryption::Type encryptType; InputStream_BE is; OutputStream_BE* temp; }; /******************************************************************************/ class ZynqMpBitFile : public BitFile { public: ZynqMpBitFile(std::istream& stream) : BitFile(stream) { }; OutputStream* GetOutputStreamType(void); bool GetBitStripFlag(void); bool GetBitPadFlag(bool); void DummyRead(void) { }; void ComparePartsDataBase(const std::string&); }; /******************************************************************************/ class ZynqBitFile : public BitFile { public: ZynqBitFile(std::istream& stream) : BitFile(stream) { }; OutputStream* GetOutputStreamType(void); bool GetBitStripFlag(void); bool GetBitPadFlag(bool); void DummyRead(void) { }; void ComparePartsDataBase(const std::string&); }; /******************************************************************************/ class BitCommand { public: void ReadWrite(InputStream_BE& is, OutputStream* os); uint32_t instruction; uint32_t count; uint32_t value; typedef enum Config_command_type { Reserve0_cmd = 0x00, WCFG_cmd = 0x01, MFWR_cmd = 0x02, LFRM_cmd = 0x03, RCFG_cmd = 0x04, START_cmd = 0x05, RCAP_cmd = 0x06, RCRC_cmd = 0x07, AGHIGH_cmd = 0x08, SWITCH_cmd = 0x09, GRESTORE_cmd = 0x0A, SHUTDOWN_cmd = 0x0B, GCAPTURE_cmd = 0x0C, DESYNCH_cmd = 0x0D, REBOOT_cmd = 0x0E, Reserve15_cmd = 0x0F } Config_command_type; typedef enum Config_register_type { CRC_reg = 0x00, FAR_reg = 0x01, FDRI_reg = 0x02, FDRO_reg = 0x03, CMD_reg = 0x04, CTL_reg = 0x05, MASK_reg = 0x06, STAT_reg = 0x07, LOUT_reg = 0x08, COR_reg = 0x09, MFWR_reg = 0x0A, CBC_reg = 0x0B, IDCODE_reg = 0x0C, AXSS_reg = 0x0D, COR1_reg = 0x0E, WBSTAR_reg = 0x10, TIMER_reg = 0x11, BOOTSTS_reg = 0x16, CTL1_reg = 0x18, BSPI_reg = 0x1F, } Config_register_type; Config_register_type reg; typedef enum { cmd_word = 0x01, extension_word = 0x02 } Config_word_type; Config_word_type word_type; typedef enum { kConfig_NOP_cmd = 0x00, kConfig_read_cmd = 0x01, kConfig_write_cmd = 0x02, kConfig_decrypt_cmd = 0x03 } Config_command_RW_type; uint32_t Config_Word_Get_Word_Count() { /* [10:0] */ return ((instruction >> 0) & 0x7FF); } Config_register_type Config_Word_Get_Register() { /* [18:13] */ return (Config_register_type)((instruction >> 13) & 0x1F); } Config_command_RW_type Config_Word_Get_Op() { /* [28:27] */ return (Config_command_RW_type)((instruction >> 27) & 0x3); } Config_word_type Config_Word_Get_Type() { /* [31:29] */ return (Config_word_type)((instruction >> 29) & 0x7); } inline uint32_t Config_Word_Get_Extension_Count() { return (instruction & 0x07FFFFFF); } }; #endif xilinx-bootgen-2024.2/bootgenenum.h000077500000000000000000000156251475706442400172750ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTGENENUM_H_ #define _BOOTGENENUM_H_ /* Encryption Key Source */ struct KeySource { typedef enum { None, BbramRedKey, EfuseRedKey, EfuseBlkKey, BhBlkKey, EfuseGryKey, BhGryKey, BhKupKey, BbramBlkKey, BbramGryKey, UserKey0, UserKey1, UserKey2, UserKey3, UserKey4, UserKey5, UserKey6, UserKey7, EfuseUserKey0, EfuseUserBlkKey0, EfuseUserGryKey0, EfuseUserKey1, EfuseUserBlkKey1, EfuseUserGryKey1, } Type; }; /* Elf endianness */ struct Endianness { typedef enum { NotEndian, LittleEndian, BigEndian, NumEndian, } Type; }; /* Authentication Selection */ struct Authentication { typedef enum { None, RSA, ECDSA, ECDSAp521, } Type; }; /* Checksum Selection */ struct Checksum { typedef enum { None, MD5, SHA2, SHA3, } Type; }; /* Encryption Selection */ struct Encryption { typedef enum { None, AES } Type; }; /* Output File types */ struct File { typedef enum { Unknown, MCS, MEM, BIN, HEX, BIT, RBT, } Type; }; /* Partition Owner */ struct PartitionOwner { typedef enum { FSBL, UBOOT, Reserved1, Reserved2, } Type; }; /* Qspi Mode for generating output files */ struct QspiMode { typedef enum { Unknown, PARALLEL_LQSPI, PARALLEL_GQSPI, STACKED, } Type; }; /* Secondary boot device */ struct BootDevice { typedef enum { DEFAULT, QSPI32, QSPI24, NAND, SD0, SD1, SDLS, MMC, USB, ETHERNET, PCIE, SATA, OSPI, SMAP, SBI, SD0RAW, SD1RAW, SDLSRAW, MMCRAW, MMC0, MMC0RAW, IMAGESTORE } Type; }; /* Domain PS or PL */ struct Domain { typedef enum { PS, PL } Type; }; /* ELF class 32 vs 64 bit */ struct ElfClass { typedef enum { ELFCLASSNONE, ELFCLASS32, ELFCLASS64 } Type; }; /* Processor Core */ struct Core { typedef enum { R5Single, A53Singlex32, A53Singlex64, R5Dual, } Type; }; /* Boot Header authentication */ struct BhRsa { typedef enum { BhRsaDisable = 0, BhRsaEnable = 3, }Type; }; /* DPA Counter measure */ struct DpaCM { typedef enum { DpaCMDisable = 0, DpaCMEnable = 3, } Type; }; /* DICE */ struct DICE { typedef enum { DiceDisable = 0, DiceEnable = 3, } Type; }; /* LockStep */ struct Lockstep { typedef enum { LockstepDisable = 0, LockstepEnable = 3, } Type; }; /* TCM Boot */ struct TcmBoot { typedef enum { TcmBootDisable = 0, TcmBootEnable = 3, } Type; }; /* Authentication Hash Selection */ struct AuthHash { typedef enum { Sha3 = 0, Sha2 = 3, }Type; }; /* PUF Helper Data location - efuse vs BH */ struct PufHdLoc { typedef enum { PUFinEFuse = 0, PUFinBH = 3, }Type; }; /* PUF Mode - 12K vs 4K */ struct PufMode { typedef enum { PUF12K = 0, PUF4K = 3, }Type; }; /* Optional Key */ struct OptKey { typedef enum { None = 0, OptKeyinSecHdr = 3, }Type; }; /* Authentication only */ struct AuthOnly { typedef enum { None = 0, Enabled = 3, }Type; }; /* Generate Authentication Keys */ struct GenAuthKeys { typedef enum { None, PEM, RSA, ECDSA, ECDSAP521, }Type; }; /* Exception Level for ARMv8 cores */ struct ExceptionLevel { typedef enum { EL0, EL1, EL2, EL3 }Type; }; /* Trustzone for ARMv8 cores */ struct TrustZone { typedef enum { NonSecure, Secure }Type; }; /* Destination Device */ struct DestinationDevice { typedef enum { DEST_DEV_NONE, DEST_DEV_PS, DEST_DEV_PL, DEST_DEV_PMU, DEST_DEV_XIP, } Type; }; /* A53 execution state 64bit vs 32bit */ struct A53ExecState { typedef enum { AARCH64 = 0, AARCH32, } Type; }; /* Destination Processor Cores */ struct DestinationCPU { typedef enum { NONE = 0, A53_0, A53_1, A53_2, A53_3, R5_0, R5_1, R5_lockstep, PMU, AIE } Type; }; /* Architecture */ struct PartitionArch { typedef enum { FPGA, NON_FPGA, VERSAL, } Type; }; /* Split Mode for generating multiple output files */ struct SplitMode { typedef enum { None, Normal, SlaveMode } Type; }; /* SPK select */ struct SpkSelect { typedef enum { SPK_eFUSE = 1, USER_eFUSE = 2, } Type; }; /* Output Mode for generating output files */ struct OutputMode { typedef enum { OUT_NORMAL, OUT_SPLIT_NORMAL, OUT_SPLIT_SLAVEBOOT, OUT_BITSTREAM, } Type; }; /* Partition Type */ struct PartitionType { typedef enum { RESERVED, ELF, CONFIG_DATA_OBJ, CFI, RAW, RAW_ELF, CFI_GSC, CFI_GSC_UNMASK, CDO, PMC_CDO, NPI, REG_INIT, BOOTLOADER, SLR_BOOT, SLR_CONFIG, SLR_SLAVE, SLR_SLAVE_BOOT, SLR_SLAVE_CONFIG, IMAGE_STORE_PDI } Type; }; /* Read image options */ struct ReadImageOption { typedef enum { NONE, ALL, BH, IHT, IH, PHT, AC, } Type; }; /* Dump options */ struct DumpOption { typedef enum { NONE, BH, PLM, PMC_CDO, BOOT_FILES, PARTITIONS, SLAVE_PDIS, } Type; }; #endif xilinx-bootgen-2024.2/bootgenexception.h000077500000000000000000000052141475706442400203200ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _BOOTGENEXCEPTION_H_ #define _BOOTGENEXCEPTION_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "stringutils.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define BootGenException(a) BootGenExceptionClass(__FILE__,__LINE__,a) #define BootGenException1(a,b) BootGenExceptionClass(__FILE__,__LINE__,a,b) #define BootGenException2(a,b,c) BootGenExceptionClass(__FILE__,__LINE__,a,b,c) /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class BootGenExceptionClass : public std::exception { public: BootGenExceptionClass(const char* filename0, int line0, const std::string& msg0 ) : msg(msg0) , filename(filename0) , line(line0) { } BootGenExceptionClass(const char* filename0, int line0, const char* format, ...) : filename(filename0) , line(line0) { va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); } ~BootGenExceptionClass() throw() { } const char* what() const throw() { return msg.c_str(); } private: std::string msg; std::string filename; int line; }; #endif xilinx-bootgen-2024.2/bootheader-versal.cpp000077500000000000000000000651551475706442400207170ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader-versal.h" #include "authentication-versal.h" #define PLM_MAX_SIZE 0x60000 //384KB #define PMCDATA_MAX_SIZE_VERSAL 0x14000 //80KB #define PMCDATA_MAX_SIZE_VERSALNET 0x10000 //64KB /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalBootHeader::VersalBootHeader(void) { pufData = new uint8_t[PUF_DATA_LENGTH]; bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; ivData = new uint8_t[IV_LENGTH * 4]; kekIvMust = false; memset(pufData, 0, PUF_DATA_LENGTH); memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); memset(ivData, 0, IV_LENGTH * 4); section = new Section("BootHeader", sizeof(VersalBootHeaderStructure)); bHTable = (VersalBootHeaderStructure*)section->Data; smapTable = (VersalSmapWidthTable*)bHTable->smapWords; } /******************************************************************************/ VersalBootHeader::VersalBootHeader(std::ifstream& src) { prebuilt = true; pufData = new uint8_t[PUF_DATA_LENGTH]; bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; ivData = new uint8_t[IV_LENGTH * 4]; memset(pufData, 0, PUF_DATA_LENGTH); memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); memset(ivData, 0, IV_LENGTH * 4); kekIvMust = false; /* Import the Boot Header from a boot image file */ section = new Section("BootHeader", sizeof(VersalBootHeaderStructure)); if (!src.read((char*)section->Data, section->Length).good()) { LOG_ERROR("Failed to read bootheader from imported image"); } bHTable = (VersalBootHeaderStructure*)section->Data; smapTable = (VersalSmapWidthTable*)bHTable->smapWords; } /******************************************************************************/ VersalBootHeader::~VersalBootHeader() { if (pufData != NULL) { delete[] pufData; } if (bhKeyData != NULL) { delete[] bhKeyData; } if (ivData != NULL) { delete[] ivData; } if (section != NULL) { delete section; } } /******************************************************************************/ void VersalBootHeader::Build(BootImage& bi, Binary& cache) { SetSmapBusWidthWords(bi.bifOptions->GetSmapWidth()); if (bi.IsBootloaderFound() == false) { if (bi.bifOptions->GetSmapWidth() != 0) { section = new Section("SmapHeader", sizeof(VersalSmapWidthTable)); smapTable = (VersalSmapWidthTable*)section->Data; memcpy(smapTable, bHTable, SMAP_BUS_WIDTH * sizeof(uint32_t)); cache.Sections.push_back(section); } return; } if (section != NULL) { cache.Sections.push_back(section); } /* If the boot header is imported from a bootimage file, no need to build */ if (prebuilt) { if (bi.bifOptions->GetRegInitFileName() != "") { BuildRegInitTable(bi.options); } return; } SetWidthDetectionWord(); SetIdentificationWord(); SetEncryptionKeySource(bi.options.GetEncryptedKeySource(), bi.bifOptions); SetPmcCdoLoadAddress(bi.bifOptions->GetPmcCdoLoadAddress()); SetShutterValue(bi.bifOptions->GetShutterValue()); SetPufRingOscilltorSwapConfigValue(bi.bifOptions->GetPufRingOscilltorSwapConfigValue()); SetGreyOrBlackKey(bi.bifOptions->GetBhKeyFile()); if (bi.options.IsVersalNetSeries() && bi.bifOptions->GetBHKekIVFile() != "") { kekIvFile = bi.bifOptions->GetBHKekIVFile(); } SetGreyOrBlackIv(kekIvFile); SetPlmSecureHdrIv(bi.options.secHdrIv); SetPmcDataSecureHdrIv(bi.options.secHdrIvPmcData); if (bi.options.IsVersalNetSeries()) { SetRevokeId(bi.imageList.front()->GetPartitionRevocationId()); } else { SetRevokeId(0x00000000); } SetRomReserved(); SetPmcFwReserved(); BuildRegInitTable(bi.options); SetPufData(bi); SetSHA3Padding(); } /******************************************************************************/ void VersalBootHeader::Link(BootImage& bi) { if (bi.IsBootloaderFound() == false) { return; } // If a bootimage is passed to the BIF if (prebuilt) { LinkPrebuiltBH(bi); return; } ImageHeaderTable* iHT = bi.imageHeaderTable; ImageHeader* fsbl = NULL; if (bi.createSubSystemPdis == true) { if (bi.subSysImageList.front()->imgList.front()->IsBootloader()) { fsbl = bi.subSysImageList.front()->imgList.front(); } } else { fsbl = iHT->GetFSBLImageHeader(); } slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; SetBHAttributes(bi); if (fsbl == NULL) { SetBHForPartialBootImage(); } else { PartitionHeader& bootloaderHdr(*(fsbl->GetPartitionHeaderList().front())); BootloaderAddressAndSizeCheck(bootloaderHdr); if (bootloaderHdr.imageHeader->GetChecksumContext()->Type() != Checksum::None && bi.options.IsVersalNetSeries()) { SetSourceOffset((uint32_t)bootloaderHdr.partition->section->Address + SHA3_LENGTH_BYTES); } else { SetSourceOffset((uint32_t)bootloaderHdr.partition->section->Address); } SetPlmLength((uint32_t)bootloaderHdr.GetPartitionSize()); SetBHForXIP(bi); SetPlmLength(bi.bifOptions->GetPmcFwSize()); SetPmcCdoLength(bi.bifOptions->GetPmcFwSize()); SetTotalPlmLength(bi.bifOptions->GetTotalPmcFwSize()); SetTotalPmcCdoLength(bi.bifOptions->GetTotalPmcFwSize()); SetPlmSecureHdrIv(bi.options.secHdrIv); if (bi.bifOptions->GetPmcFwSize() != 0) { SetPmcDataSecureHdrIv(bi.options.secHdrIvPmcData); } if (fsbl->IsStaticFlagSet() || bi.bifOptions->GetXipMode()) { SetTotalPlmLength(0); } else { SetPlmLength(bi.GetFsblFwSize()); SetTotalPlmLength(bi.GetTotalFsblFwSize()); } } if (iHT->section != NULL) { if (!Binary::CheckAddress(iHT->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Image Header Offset is %llX", iHT->section->Address); } SetImageHeaderByteOffset((uint32_t)iHT->section->Address); } SetHeaderChecksum(); if (bHTable->totalPlmLength > PLM_MAX_SIZE && !bi.options.IsVersalNetSeries()) { LOG_ERROR("Total PLM size : %dKB > maximum allowable size (384KB)", bHTable->totalPlmLength / 1024); } if (bHTable->totalPmcCdoLength > PMCDATA_MAX_SIZE_VERSAL && !bi.options.IsVersalNetSeries()) { LOG_ERROR("Total PMC DATA size : %dKB > maximum allowable size (80KB)", bHTable->totalPlmLength / 1024); } if (bHTable->totalPmcCdoLength > PMCDATA_MAX_SIZE_VERSALNET && bi.options.IsVersalNetSeries()) { LOG_ERROR("Total PMC DATA size : %dKB > maximum allowable size (64KB)", bHTable->totalPlmLength / 1024); } } /******************************************************************************/ void VersalBootHeader::LinkPrebuiltBH(BootImage& bi) { Authentication::Type authTypeLocal = Authentication::None; bool presignedLocal = false; if (bi.createSubSystemPdis == true) { authTypeLocal = bi.subSysImageList.front()->imgList.front()->GetAuthenticationType(); presignedLocal = bi.subSysImageList.front()->imgList.front()->GetAuthContext()->preSigned; } else { authTypeLocal = bi.imageList.front()->GetAuthenticationType(); presignedLocal = bi.imageList.front()->GetAuthContext()->preSigned; } if (authTypeLocal != Authentication::None) { if (!(presignedLocal)) { uint32_t acSize = sizeof(AuthCertificate4096Sha3PaddingStructure); bHTable->sourceOffset += acSize; if (bi.options.IsVersalNetSeries()) { SetTotalPlmLength(bi.GetTotalFsblFwSize()); SetTotalPmcCdoLength(bi.bifOptions->GetTotalPmcFwSize()); } else { bHTable->totalPlmLength += acSize; Binary::Length_t shaPadOnLength = bHTable->totalPlmLength + bHTable->totalPmcCdoLength - SIGN_LENGTH_VERSAL; uint8_t shaPadLength = SHA3_PAD_LENGTH - (shaPadOnLength % SHA3_PAD_LENGTH); if (bHTable->totalPmcCdoLength == 0) { bHTable->totalPlmLength += shaPadLength; } else { bHTable->totalPmcCdoLength += shaPadLength; } } SetHeaderChecksum(); } bi.SetTotalFsblFwSize(bHTable->totalPlmLength); bi.bifOptions->SetTotalpmcdataSize(bHTable->totalPmcCdoLength); } SetPlmLength(bi.GetFsblFwSize()); SetTotalPlmLength(bi.GetTotalFsblFwSize()); SetPmcCdoLength(bi.bifOptions->GetPmcFwSize()); SetTotalPmcCdoLength(bi.bifOptions->GetTotalPmcFwSize()); if (bi.bifOptions->GetPmcdataFile() != "") { SetPmcCdoLoadAddress(bi.bifOptions->GetPmcCdoLoadAddress()); } /* This is useful for importing the bootimage and appending new partitions. Total metaheader length depends on no. of partitions */ ImageHeaderTable* iHT = bi.imageHeaderTable; if (iHT->section != NULL) { if (!Binary::CheckAddress(iHT->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Image Header Offset is %llX", iHT->section->Address); } SetImageHeaderByteOffset((uint32_t)iHT->section->Address); } if (bi.partitionHeaderTable->firstSection != NULL) { if (!Binary::CheckAddress(bi.partitionHeaderTable->firstSection->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Partition Header Offset is %llX", bi.partitionHeaderList.front()->section->Address); } SetPartitionHeaderByteOffset((uint32_t)bi.partitionHeaderTable->firstSection->Address); } /* Update checksum as metaheader length is updated */ SetHeaderChecksum(); } /******************************************************************************/ void VersalBootHeader::SetBHForPartialBootImage() { SetSourceOffset(0); SetPlmLength(0); SetTotalPlmLength(0); SetPmcCdoLoadAddress(0); SetPmcCdoLength(0); SetTotalPmcCdoLength(0); } /******************************************************************************/ void VersalBootHeader::SetBHForXIP(BootImage& bi) { if (bi.bifOptions->GetXipMode()) { SetTotalPlmLength(0); /* TO-DO: Add XIP execution address checks */ } } /******************************************************************************/ void VersalBootHeader::SetSmapBusWidthWords(uint32_t width) { LOG_INFO("SMAP bus width is - %d bits", width); switch (width) { case 8: bHTable->smapWords[0] = 0xDD000000; bHTable->smapWords[1] = 0x44332211; bHTable->smapWords[2] = 0x88776655; bHTable->smapWords[3] = 0xCCBBAA99; break; case 16: bHTable->smapWords[0] = 0x00DD0000; bHTable->smapWords[1] = 0x33441122; bHTable->smapWords[2] = 0x77885566; bHTable->smapWords[3] = 0xBBCC99AA; break; case 32: default: bHTable->smapWords[0] = 0x000000DD; bHTable->smapWords[1] = 0x11223344; bHTable->smapWords[2] = 0x55667788; bHTable->smapWords[3] = 0x99aabbcc; break; } } /******************************************************************************/ void VersalBootHeader::SetWidthDetectionWord(void) { bHTable->widthDetectionWord = WIDTH_DETECTION; } /******************************************************************************/ void VersalBootHeader::SetIdentificationWord(void) { bHTable->identificationWord = HEADER_ID_WORD; } /******************************************************************************/ void VersalBootHeader::SetEncryptionKeySource(KeySource::Type keyType, BifOptions* bifOptions) { kekIvMust = false; switch (keyType) { case KeySource::EfuseRedKey: bHTable->encryptionKeySource = EFUSE_RED_KEY; break; case KeySource::BbramRedKey: bHTable->encryptionKeySource = BBRAM_RED_KEY; break; case KeySource::EfuseBlkKey: bHTable->encryptionKeySource = EFUSE_BLK_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_blk_key'"); } kekIvMust = true; break; case KeySource::BbramBlkKey: bHTable->encryptionKeySource = BBRAM_BLK_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_blk_key'"); } kekIvMust = true; break; case KeySource::BhBlkKey: bHTable->encryptionKeySource = BH_BLACK_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_blk_key'"); } kekIvMust = true; break; case KeySource::EfuseGryKey: bHTable->encryptionKeySource = EFUSE_GRY_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_gry_key'"); } kekIvMust = true; break; case KeySource::BbramGryKey: bHTable->encryptionKeySource = BBRAM_GRY_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_gry_key'"); } kekIvMust = true; break; case KeySource::BhGryKey: bHTable->encryptionKeySource = BH_GRY_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_gry_key'"); } kekIvMust = true; break; case KeySource::None: default: bHTable->encryptionKeySource = 0; break; } } /******************************************************************************/ void VersalBootHeader::SetPmcCdoLoadAddress(uint32_t address) { bHTable->pmcCdoLoadAddress = address; } /******************************************************************************/ void VersalBootHeader::SetSourceOffset(uint32_t offset) { bHTable->sourceOffset = offset; } /******************************************************************************/ void VersalBootHeader::SetPmcCdoLength(uint32_t size) { bHTable->pmcCdoLength = size; } /******************************************************************************/ void VersalBootHeader::SetTotalPmcCdoLength(uint32_t size) { bHTable->totalPmcCdoLength = size; } /******************************************************************************/ void VersalBootHeader::SetPlmLength(uint32_t size) { bHTable->plmLength = size; } /******************************************************************************/ void VersalBootHeader::SetTotalPlmLength(uint32_t size) { bHTable->totalPlmLength = size; } /******************************************************************************/ void VersalBootHeader::SetBHAttributes(BootImage& bi) { if (bi.imageList.size() != 0) { uint8_t cksumType = 0; cksumType = bi.partitionHeaderList.front()->imageHeader->GetChecksumContext()->Type(); bHTable->bhAttributes = bi.partitionHeaderList.front()->imageHeader->GetPufHdLocation() << PUF_HD_BIT_SHIFT; bHTable->bhAttributes |= cksumType << BI_HASH_BIT_SHIFT; bHTable->bhAttributes |= bi.partitionHeaderList.front()->imageHeader->GetDpacm() << DPA_CM_BIT_SHIFT; bHTable->bhAttributes |= bi.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; bHTable->bhAttributes |= bi.bifOptions->GetPufMode() << BH_PUF_MODE_BIT_SHIFT; if (bi.options.IsVersalNetSeries()) { if (bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) { bHTable->bhAttributes |= BH_RSA_SINGED_BIT_MASK << BH_RSA_SINGED_BIT_SHIFT; } bHTable->bhAttributes |= bi.bifOptions->GetDice() << BH_DICE_BIT_SHIFT; } } } /******************************************************************************/ void VersalBootHeader::SetBHAttributes(uint32_t attributes) { bHTable->bhAttributes = attributes; } /******************************************************************************/ void VersalBootHeader::SetHeaderChecksum(void) { /* Set the simple header checksum value by adding up all of the 32 bit values from the Width Detection Word (0x10) to the PUF (0xF1F) (968 words, 3872 bytes) */ bHTable->headerChecksum = ComputeWordChecksum(&bHTable->widthDetectionWord, 3872); } /******************************************************************************/ void VersalBootHeader::SetGreyOrBlackKey(std::string keyFile) { uint8_t* bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); if (keyFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(keyFile, bhKeyData, BLK_GRY_KEY_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Grey/Black key in BootHeader.\n Expected length for Grey/Black key is 32 bytes"); } } memcpy(&bHTable->greyOrBlackKey, bhKeyData, BLK_GRY_KEY_LENGTH * 4); delete[] bhKeyData; } /******************************************************************************/ void VersalBootHeader::SetShutterValue(uint32_t value) { bHTable->shutterValue = value; } /******************************************************************************/ void VersalBootHeader::SetRevokeId(uint32_t id) { bHTable->revokeId = id; } /******************************************************************************/ void VersalBootHeader::SetPufRingOscilltorSwapConfigValue(uint32_t value) { bHTable->pufRoSwapConfigVal = value; } /******************************************************************************/ void VersalBootHeader::SetImageHeaderByteOffset(uint32_t address) { bHTable->imageHeaderByteOffset = address; } /******************************************************************************/ void VersalBootHeader::SetPlmSecureHdrIv(uint8_t* iv) { if (iv == NULL) { memset(bHTable->plmSecureHdrIv, 0, IV_LENGTH * WORD_SIZE_IN_BYTES); } else { memcpy(bHTable->plmSecureHdrIv, iv, IV_LENGTH * WORD_SIZE_IN_BYTES); } } /******************************************************************************/ void VersalBootHeader::SetPmcDataSecureHdrIv(uint8_t* iv) { if (iv == NULL) { memset(bHTable->pmcCdoSecureHdrIv, 0, IV_LENGTH * WORD_SIZE_IN_BYTES); } else { memcpy(bHTable->pmcCdoSecureHdrIv, iv, IV_LENGTH * WORD_SIZE_IN_BYTES); } } /******************************************************************************/ void VersalBootHeader::SetGreyOrBlackIv(std::string ivFile) { uint8_t* ivData = new uint8_t[IV_LENGTH * 4]; memset(ivData, 0, IV_LENGTH * 4); if (ivFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(ivFile, ivData, IV_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Black/Grey Key IV.\n Expected length for Grey/Black IV is 12 bytes"); } } else { if (kekIvMust) { LOG_ERROR("Black/Grey IV is mandatory in case of Black/Grey key sources\n Please use 'bh_kek_iv' to specify the IV in BIF file"); } } memcpy(&bHTable->greyOrBlackIV, ivData, IV_LENGTH * 4); delete[] ivData; } /******************************************************************************/ void VersalBootHeader::SetPufData(BootImage &bi) { uint8_t* pufData = new uint8_t[PUF_DATA_LENGTH]; memset(pufData, 0, PUF_DATA_LENGTH); if (bi.bifOptions->GetPufHdLoc() == PufHdLoc::PUFinBH || bi.bifOptions->GetPufHdinBHFlag()) { if (bi.bifOptions->GetPufHelperFile() != "") { FileImport fileReader; if (!fileReader.LoadHexData(bi.bifOptions->GetPufHelperFile(), pufData, PUF_DATA_LENGTH)) { LOG_ERROR("Invalid no. of data bytes for PUF Helper Data.\n Expected length for PUF Helper Data is 1544 bytes"); } } } uint32_t pufLoc = GetBootHeaderSize() - sizeof(uint32_t) - (SHA3_PAD_SIZE_VERSAL * 4) - PUF_DATA_LENGTH; memcpy((uint8_t*)bHTable + pufLoc, pufData, PUF_DATA_LENGTH); delete[] pufData; } /******************************************************************************/ void VersalBootHeader::SetRomReserved() { for (int i = 0; iromReserved[i] = DEFAULT_RESERVED_VERSAL; } } /******************************************************************************/ void VersalBootHeader::SetPmcFwReserved() { for (int i = 0; iplmReserved[i] = DEFAULT_RESERVED_VERSAL; } } /******************************************************************************/ uint32_t* VersalBootHeader::GetChecksumStartPtr(void) { return &bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t VersalBootHeader::GetBootHeaderSize(void) { return sizeof(VersalBootHeaderStructure); } /******************************************************************************/ uint32_t VersalBootHeader::GetWidthDetectionWord(void) { return bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t VersalBootHeader::GetIdentificationWord(void) { return bHTable->identificationWord; } /******************************************************************************/ uint32_t VersalBootHeader::GetSourceOffset(void) { return bHTable->sourceOffset; } /******************************************************************************/ uint32_t VersalBootHeader::GetHeaderChecksum(void) { return bHTable->headerChecksum; } /******************************************************************************/ uint32_t VersalBootHeader::GetPmcFwLength(void) { return bHTable->plmLength; } /******************************************************************************/ uint32_t VersalBootHeader::GetTotalPmcFwLength(void) { return bHTable->totalPlmLength; } /******************************************************************************/ uint32_t VersalBootHeader::GetPmcCdoLoadAddress(void) { return bHTable->pmcCdoLoadAddress; } /******************************************************************************/ KeySource::Type VersalBootHeader::GetEncryptionKeySource(void) { switch (bHTable->encryptionKeySource) { case BBRAM_RED_KEY: return KeySource::BbramRedKey; break; case EFUSE_RED_KEY: return KeySource::EfuseRedKey; break; case BBRAM_BLK_KEY: return KeySource::BbramBlkKey; break; case EFUSE_BLK_KEY: return KeySource::EfuseBlkKey; break; case BH_BLACK_KEY: return KeySource::BhBlkKey; break; case EFUSE_GRY_KEY: return KeySource::EfuseGryKey; break; case BH_GRY_KEY: return KeySource::BhGryKey; break; case BBRAM_GRY_KEY: return KeySource::BbramGryKey; break; default: return KeySource::None; break; } } /******************************************************************************/ uint32_t VersalBootHeader::GetPmcCdoLength(void) { return bHTable->pmcCdoLength; } /******************************************************************************/ uint32_t VersalBootHeader::GetTotalPmcCdoLength(void) { return bHTable->totalPmcCdoLength; } /******************************************************************************/ uint32_t VersalBootHeader::GetBHAttributes(void) { return bHTable->bhAttributes; } /******************************************************************************/ uint32_t VersalBootHeader::GetImageHeaderByteOffset(void) { return bHTable->imageHeaderByteOffset; } /******************************************************************************/ uint32_t VersalBootHeader::CalcHeaderChecksum(void* addr, size_t len) { return ComputeWordChecksum(addr, len); } /******************************************************************************/ void VersalBootHeader::BuildRegInitTable(Options& options) { uint32_t regTableLoc = GetBootHeaderSize() - sizeof(uint32_t) - (SHA3_PAD_SIZE_VERSAL * 4) - PUF_DATA_LENGTH - (MAX_REGISTER_INITS * 4 * 2); regTable.Build(options, (RegisterInitTable*)(section->Data + regTableLoc)); } /******************************************************************************/ void VersalBootHeader::SetSHA3Padding() { for (int i = 0; isha3Padding[i] = DEFAULT_RESERVED_VERSAL; } bHTable->sha3Padding[0] = 0x6; bHTable->sha3Padding[SHA3_PAD_SIZE_VERSAL - 1] = 0x80000000; } /******************************************************************************/ uint32_t VersalBootHeader::GetXipBaseAddr(void) { return LQSPI_BASE_ADDR_VERSAL; } xilinx-bootgen-2024.2/bootheader-versal.h000077500000000000000000000152761475706442400203630ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTHEADER_VERSAL_H_ #define _BOOTHEADER_VERSAL_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader.h" #include "bootimage.h" #include "bifoptions.h" #include "fileutils.h" #include "imageheadertable-versal.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ /* Keys Source */ #define BBRAM_GRY_KEY 0x3A5C3C57 #define BBRAM_BLK_KEY 0x3A5C3C59 #define DEFAULT_RESERVED_VERSAL 0 #define SMAP_BUS_WIDTH 4 #define ROM_BH_RESERVED 15 #define PLM_BH_RESERVED 24 #define SHA3_PAD_SIZE_VERSAL 19 #define MAX_REG_INIT_VERSAL 512 #define DPA_CM_BIT_SHIFT 10 #define DPA_CM_BIT_MASK 3 //VersalNet #define BH_RSA_SINGED_BIT_SHIFT 18 #define BH_RSA_SINGED_BIT_MASK 3 #define BH_DICE_BIT_SHIFT 20 #define BH_DICE_BIT_MASK 3 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t smapWords[SMAP_BUS_WIDTH]; // (0x00) } VersalSmapWidthTable; typedef struct { uint32_t smapWords[SMAP_BUS_WIDTH]; // (0x00) uint32_t widthDetectionWord; // (0x10) uint32_t identificationWord; // (0x14) uint32_t encryptionKeySource; // (0x18) uint32_t sourceOffset; // (0x1C) uint32_t pmcCdoLoadAddress; // (0x20) uint32_t pmcCdoLength; // (0x24) uint32_t totalPmcCdoLength; // (0x28) uint32_t plmLength; // (0x2C) uint32_t totalPlmLength; // (0x30) uint32_t bhAttributes; // (0x34) uint32_t greyOrBlackKey[BLK_GRY_KEY_LENGTH]; // (0x38) uint32_t greyOrBlackIV[IV_LENGTH]; // (0x58) uint32_t plmSecureHdrIv[IV_LENGTH]; // (0x64) uint32_t shutterValue; // (0x70) uint32_t pmcCdoSecureHdrIv[IV_LENGTH]; // (0x74) uint32_t pufRoSwapConfigVal; // (0x80) - Valid only for VersalNet uint32_t revokeId; // (0x84) uint32_t romReserved[ROM_BH_RESERVED]; // (0x88) uint32_t imageHeaderByteOffset; // (0xC4) uint32_t plmReserved[PLM_BH_RESERVED]; // (0xC8) uint32_t reginit[MAX_REG_INIT_VERSAL]; // (0x128) uint32_t puf[PUF_DATA_LENGTH / 4]; // (0x928) uint32_t headerChecksum; // (0xF30) uint32_t sha3Padding[SHA3_PAD_SIZE_VERSAL]; // (0xF34) } VersalBootHeaderStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalBootHeader : public BootHeader { public: VersalBootHeader(); VersalBootHeader(std::ifstream& src); ~VersalBootHeader(); void Build(BootImage & bi, Binary & cache); void Link(BootImage& bi); void SetBHForPartialBootImage(); void SetBHForXIP(BootImage & bi); void BuildRegInitTable(Options& options); uint32_t CalcHeaderChecksum(void* addr, size_t len); void LinkPrebuiltBH(BootImage& bi); void AddAcSizeToTotalFSBLSize(uint32_t size) {}; void SetPartitionHeaderByteOffset(uint32_t address) {}; void SetWidthDetectionWord(void); void SetIdentificationWord(void); void SetSourceOffset(uint32_t offset); void SetHeaderChecksum(void); void SetShutterValue(uint32_t value); void SetPufRingOscilltorSwapConfigValue(uint32_t value); void SetImageHeaderByteOffset(uint32_t address); void SetEncryptionKeySource(KeySource::Type keyType, BifOptions* bifOptions); void SetGreyOrBlackKey(std::string keyFile); void SetGreyOrBlackIv(std::string ivFile); void SetPlmSecureHdrIv(uint8_t* iv); void SetPmcDataSecureHdrIv(uint8_t* iv); void SetPufData(BootImage &bi); void SetSmapBusWidthWords(uint32_t width); void SetPlmLength(uint32_t size); void SetTotalPlmLength(uint32_t size); void SetPmcCdoLength(uint32_t size); void SetPmcCdoLoadAddress(uint32_t address); void SetTotalPmcCdoLength(uint32_t size); void SetBHAttributes(BootImage& bi); void SetBHAttributes(uint32_t attributes); void SetRevokeId(uint32_t id); void SetRomReserved(); void SetPmcFwReserved(); void SetSHA3Padding(); uint32_t GetBootHeaderSize(void); uint32_t GetWidthDetectionWord(void); uint32_t GetIdentificationWord(void); uint32_t GetSourceOffset(void); uint32_t GetHeaderChecksum(void); uint32_t GetPmcFwLength(void); uint32_t GetTotalPmcFwLength(void); uint32_t GetPmcCdoLoadAddress(void); uint32_t GetImageHeaderByteOffset(void); uint32_t GetPmcCdoLength(void); uint32_t GetTotalPmcCdoLength(void); uint32_t GetBHAttributes(void); uint32_t GetXipBaseAddr(void); uint32_t* GetChecksumStartPtr(void); KeySource::Type GetEncryptionKeySource(void); /*To suppress the vesion check warning in parse boot image for zynqmp*/ uint32_t GetHeaderVersion(void) { return 0xFFFFFFFF; } private: VersalBootHeaderStructure *bHTable; VersalSmapWidthTable *smapTable; bool kekIvMust; std::string kekIvFile; uint8_t* pufData; uint8_t* bhKeyData; uint8_t* ivData; }; #endif xilinx-bootgen-2024.2/bootheader-zynq.cpp000077500000000000000000000323301475706442400204110ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader-zynq.h" #include "bootimage.h" #include "bifoptions.h" class BootImage; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqBootHeader::ZynqBootHeader(void) { section = new Section("BootHeader", sizeof(ZynqBootHeaderStructure) + sizeof(RegisterInitTable)); bHTable = (ZynqBootHeaderStructure*)section->Data; } /******************************************************************************/ ZynqBootHeader::ZynqBootHeader(std::ifstream& src) { prebuilt = true; section = new Section("BootHeader", sizeof(ZynqBootHeaderStructure) + sizeof(RegisterInitTable)); /* Import the Boot Header from a boot image file */ if (!src.read((char*)section->Data, section->Length).good()) { LOG_ERROR("Failed to read bootheader from imported image"); } bHTable = (ZynqBootHeaderStructure*)section->Data; } /******************************************************************************/ ZynqBootHeader::~ZynqBootHeader(void) { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqBootHeader::Build(BootImage& bi, Binary& cache) { if (section != NULL) { cache.Sections.push_back(section); } /* If the boot header is imported from a bootimage file, no need to build */ if (prebuilt) { if (bi.bifOptions->GetRegInitFileName() != "") { BuildRegInitTable(bi.options); } return; } SetWidthDetectionWord(); SetIdentificationWord(); SetEncryptionKeySource(bi.options.GetEncryptedKeySource()); SetHeaderVersion(); SetQspiConfigWord(); SetUdf(bi.options.bifOptions->GetUdfBhFile()); BuildRegInitTable(bi.options); } /******************************************************************************/ void ZynqBootHeader::Link(BootImage& bi) { if (prebuilt) { return; } ImageHeaderTable* iHT = bi.imageHeaderTable; ImageHeader* fsbl = iHT->GetFSBLImageHeader(); slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; SetBootVectors(bi); if (fsbl == NULL) { SetBHForSinglePartitionImage(); } else { PartitionHeader& bootloaderHdr(*(fsbl->GetPartitionHeaderList().front())); BootloaderAddressAndSizeCheck(bootloaderHdr); SetSourceOffset((uint32_t)bootloaderHdr.partition->section->Address); SetFsblLength((uint32_t)bootloaderHdr.GetPartitionSize()); SetFsblLoadAddress((uint32_t)bootloaderHdr.GetLoadAddress()); SetFsblExecAddress((uint32_t)bootloaderHdr.GetExecAddress()); SetBHForXIP(bi); if (fsbl->IsStaticFlagSet() || bi.bifOptions->GetXipMode()) { SetFsblLength(0); SetTotalFsblLength(0); } else { SetFsblLength(bi.GetFsblFwSize()); SetTotalFsblLength(bi.GetTotalFsblFwSize()); } } if (iHT->section != NULL) { if (!Binary::CheckAddress(iHT->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Image Header Offset is %llX", iHT->section->Address); } SetImageHeaderByteOffset((uint32_t)iHT->section->Address); } if (bi.partitionHeaderTable->firstSection != NULL) { if (!Binary::CheckAddress(bi.partitionHeaderTable->firstSection->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Partition Header Offset is %llX", bi.partitionHeaderList.front()->section->Address); } SetPartitionHeaderByteOffset((uint32_t)bi.partitionHeaderTable->firstSection->Address); } SetHeaderChecksum(); } /******************************************************************************/ void ZynqBootHeader::SetBHForSinglePartitionImage() { SetSourceOffset(0); SetFsblLoadAddress(0); SetFsblExecAddress(0); SetFsblLength(0); SetTotalFsblLength(0); } /******************************************************************************/ void ZynqBootHeader::SetBHForXIP(BootImage & bi) { if (bi.XipMode) { SetFsblLength(0); SetTotalFsblLength(0); SetFsblLoadAddress(0); if (GetFsblExecAddress() < GetXipBaseAddr() + bi.options.totalHeadersSize + bi.GetTotalPmuFwSize()) { LOG_ERROR("XIP Execution address is overlapping the Boot Header and/or other regions of the image", GetFsblExecAddress()); } if (GetTotalFsblLength() == 0) { SetSourceOffset(GetSourceOffset()); } } } /******************************************************************************/ void ZynqBootHeader::SetBootVectors(BootImage &bi) { for (int i=0; ibootVectors[i] = ARM_JUMP_TO_SELF_INSTRUCION; } } /******************************************************************************/ void ZynqBootHeader::SetWidthDetectionWord(void) { bHTable->widthDetectionWord = WIDTH_DETECTION; } /******************************************************************************/ void ZynqBootHeader::SetIdentificationWord(void) { bHTable->identificationWord = HEADER_ID_WORD; } /******************************************************************************/ void ZynqBootHeader::SetEncryptionKeySource(KeySource::Type keyType) { switch (keyType) { case KeySource::BbramRedKey: bHTable->encryptionKeySource = BBRAM_RED_KEY; break; case KeySource::EfuseRedKey: bHTable->encryptionKeySource = EFUSE_RED_KEY; break; case KeySource::None: default: bHTable->encryptionKeySource = 0; break; } } /******************************************************************************/ void ZynqBootHeader::SetHeaderVersion(void) { bHTable->headerVersion = BOOTHEADER_VERSION; } /******************************************************************************/ void ZynqBootHeader::SetSourceOffset(uint32_t offset) { bHTable->sourceOffset = offset; } /******************************************************************************/ void ZynqBootHeader::SetFsblLength(uint32_t size) { bHTable->fsblLength = size; } /******************************************************************************/ void ZynqBootHeader::SetFsblLoadAddress(uint32_t address) { bHTable->fsblLoadAddress = address; } /******************************************************************************/ void ZynqBootHeader::SetFsblExecAddress(uint32_t address) { bHTable->fsblExecAddress = address; } /******************************************************************************/ void ZynqBootHeader::SetTotalFsblLength(uint32_t size) { bHTable->totalFsblLength = size; } /******************************************************************************/ void ZynqBootHeader::SetQspiConfigWord(void) { bHTable->qspiConfigWord = QSPI_CONFIG_WORD; } /******************************************************************************/ void ZynqBootHeader::SetHeaderChecksum(void) { /* Set the simple header checksum value by adding up all of the 32 bit values from the Width Detection Word (0x20) to the QUAD-SPI Config Word (0x44) (10 words, 40 bytes) */ bHTable->headerChecksum = ComputeWordChecksum(&bHTable->widthDetectionWord, 40); } /******************************************************************************/ void ZynqBootHeader::SetUdf(std::string udfFile) { uint8_t bhUdfData[UDF_BH_SIZE_ZYNQ * sizeof(uint32_t)]; memset(bhUdfData, 0, UDF_BH_SIZE_ZYNQ * 4); if (udfFile != "") { LoadUdfData(udfFile, bhUdfData, UDF_BH_SIZE_ZYNQ); } memcpy((uint8_t*)bHTable->udf, bhUdfData, UDF_BH_SIZE_ZYNQ * sizeof(uint32_t)); } /******************************************************************************/ void ZynqBootHeader::SetImageHeaderByteOffset(uint32_t address) { bHTable->imageHeaderByteOffset = address; } /******************************************************************************/ void ZynqBootHeader::SetPartitionHeaderByteOffset(uint32_t address) { bHTable->partitionHeaderByteOffset = address; } /******************************************************************************/ uint32_t* ZynqBootHeader::GetChecksumStartPtr(void) { return &bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t ZynqBootHeader::GetBootHeaderSize(void) { return sizeof(ZynqBootHeaderStructure); } /******************************************************************************/ uint32_t ZynqBootHeader::GetWidthDetectionWord(void) { return bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t ZynqBootHeader::GetIdentificationWord(void) { return bHTable->identificationWord; } /******************************************************************************/ uint32_t ZynqBootHeader::GetSourceOffset(void) { return bHTable->sourceOffset; } /******************************************************************************/ uint32_t ZynqBootHeader::GetHeaderChecksum(void) { return bHTable->headerChecksum; } /******************************************************************************/ uint32_t ZynqBootHeader::GetFsblLength(void) { return bHTable->fsblLength; } /******************************************************************************/ uint32_t ZynqBootHeader::GetTotalFsblLength(void) { return bHTable->totalFsblLength; } /******************************************************************************/ uint32_t ZynqBootHeader::GetFsblExecAddress(void) { return bHTable->fsblExecAddress; } /******************************************************************************/ uint32_t ZynqBootHeader::GetImageHeaderByteOffset(void) { return bHTable->imageHeaderByteOffset; } /******************************************************************************/ uint32_t ZynqBootHeader::GetPartitionHeaderByteOffset(void) { return bHTable->partitionHeaderByteOffset; } /******************************************************************************/ KeySource::Type ZynqBootHeader::GetEncryptionKeySource(void) { switch (bHTable->encryptionKeySource) { case BBRAM_RED_KEY: return KeySource::BbramRedKey; break; case EFUSE_RED_KEY: return KeySource::EfuseRedKey; break; default: return KeySource::None; break; } } /******************************************************************************/ uint32_t ZynqBootHeader::GetHeaderVersion(void) { return bHTable->headerVersion; } /******************************************************************************/ uint32_t ZynqBootHeader::GetQspiConfigWord(void) { return bHTable->qspiConfigWord; } /******************************************************************************/ uint32_t ZynqBootHeader::GetFsblLoadAddress(void) { return bHTable->fsblLoadAddress; } /******************************************************************************/ uint32_t ZynqBootHeader::CalcHeaderChecksum(void* addr, size_t len) { return ComputeWordChecksum(addr, len); } /******************************************************************************/ void ZynqBootHeader::BuildRegInitTable(Options& options) { regTable.Build(options, registerInitTable()); } /******************************************************************************/ uint32_t ZynqBootHeader::GetXipBaseAddr(void) { /* LQSPI XIP */ if ((GetFsblExecAddress() >= LQSPI_BASE_ADDR_ZYNQ) && (GetFsblExecAddress() < LQSPI_BASE_ADDR_ZYNQ + LQSPI_SIZE_ZYNQ)) { return LQSPI_BASE_ADDR_ZYNQ; } /* NOR XIP */ if ((GetFsblExecAddress() >= NOR_BASE_ADDR_ZYNQ) && (GetFsblExecAddress() < NOR_BASE_ADDR_ZYNQ + NOR_SIZE_ZYNQ)) { return NOR_BASE_ADDR_ZYNQ; } return 0; } xilinx-bootgen-2024.2/bootheader-zynq.h000077500000000000000000000111551475706442400200600ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTHEADER_ZYNQ_H_ #define _BOOTHEADER_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader.h" #include "imageheadertable-zynq.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define UDF_BH_SIZE_ZYNQ 19 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t bootVectors [MAX_BOOT_VECTORS]; // (0x00) uint32_t widthDetectionWord; // (0x20) uint32_t identificationWord; // (0x24) uint32_t encryptionKeySource; // (0x28) uint32_t headerVersion; // (0x2C) uint32_t sourceOffset; // (0x30) uint32_t fsblLength; // (0x34) uint32_t fsblLoadAddress; // (0x38) uint32_t fsblExecAddress; // (0x3C) uint32_t totalFsblLength; // (0x40) uint32_t qspiConfigWord; // (0x44) uint32_t headerChecksum; // (0x48) uint32_t udf [UDF_BH_SIZE_ZYNQ]; // (0x4C) uint32_t imageHeaderByteOffset; // (0x98) uint32_t partitionHeaderByteOffset; // (0x9C) } ZynqBootHeaderStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqBootHeader : public BootHeader { public: ZynqBootHeader(); ZynqBootHeader(std::ifstream& src); ~ZynqBootHeader(); void Build(BootImage& bi, Binary& cache); void Link(BootImage& bi); void SetBHForSinglePartitionImage(); void SetBHForXIP(BootImage & bi); void BuildRegInitTable (Options& options); uint32_t CalcHeaderChecksum(void* addr, size_t len); void SetBootVectors(BootImage &bi); void SetWidthDetectionWord(void); void SetIdentificationWord(void); void SetSourceOffset(uint32_t offset); void SetHeaderChecksum(void); void SetFsblLength(uint32_t size); void SetTotalFsblLength(uint32_t size); void SetFsblExecAddress(uint32_t address); void SetUdf(std::string udfFile); void SetImageHeaderByteOffset(uint32_t address); void SetPartitionHeaderByteOffset(uint32_t address); void SetEncryptionKeySource(KeySource::Type keyType); void SetHeaderVersion(void); void SetFsblLoadAddress(uint32_t address); void SetQspiConfigWord(void); uint32_t GetBootHeaderSize(void); uint32_t GetWidthDetectionWord(void); uint32_t GetIdentificationWord(void); uint32_t GetSourceOffset(void); uint32_t GetHeaderChecksum(void); uint32_t GetFsblLength(void); uint32_t GetTotalFsblLength(void); uint32_t GetFsblExecAddress(void); uint32_t GetImageHeaderByteOffset(void); uint32_t GetPartitionHeaderByteOffset(void); uint32_t GetHeaderVersion(void); uint32_t GetFsblLoadAddress(void); uint32_t GetQspiConfigWord(void); uint32_t GetXipBaseAddr(void); uint32_t* GetChecksumStartPtr(void); KeySource::Type GetEncryptionKeySource(void); private: ZynqBootHeaderStructure *bHTable; }; #endif xilinx-bootgen-2024.2/bootheader-zynqmp.cpp000077500000000000000000000562721475706442400207610ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader-zynqmp.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqMpBootHeader::ZynqMpBootHeader(void) { pufData = new uint8_t[PUF_DATA_LENGTH]; bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; ivData = new uint8_t[IV_LENGTH * 4]; keyIvMust = false; memset(pufData, 0, PUF_DATA_LENGTH); memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); memset(ivData, 0, IV_LENGTH * 4); section = new Section("BootHeader", sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable)); bHTable = (ZynqMpBootHeaderStructure*)section->Data; } /******************************************************************************/ ZynqMpBootHeader::ZynqMpBootHeader(std::ifstream& src) { prebuilt = true; pufData = new uint8_t[PUF_DATA_LENGTH]; bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; ivData = new uint8_t[IV_LENGTH * 4]; memset(pufData, 0, PUF_DATA_LENGTH); memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); memset(ivData, 0, IV_LENGTH * 4); keyIvMust = false; /* Import the Boot Header from a boot image file */ section = new Section("BootHeader", sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable)); if (!src.read((char*)section->Data, section->Length).good()) { LOG_ERROR("Failed to read bootheader from imported image"); } bHTable = (ZynqMpBootHeaderStructure*)section->Data; /* If PUF is present in BH, increase the BH size */ if (((bHTable->fsblAttributes >> PUF_HD_BIT_SHIFT) & PUF_HD_BIT_MASK) == 0x3) { uint32_t newBhSize = sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable) + PUF_DATA_LENGTH; uint8_t* newDataPtr = new uint8_t[newBhSize]; memcpy(newDataPtr, section->Data, section->Length); if (!src.read((char*)newDataPtr + section->Length, newBhSize - section->Length).good()) { LOG_ERROR("Failed to read bootheader from imported image"); } delete[] section->Data; section->Data = newDataPtr; section->Length = newBhSize; bHTable = (ZynqMpBootHeaderStructure*)section->Data; } } /******************************************************************************/ ZynqMpBootHeader::~ZynqMpBootHeader(void) { if (pufData != NULL) { delete[] pufData; } if (bhKeyData != NULL) { delete[] bhKeyData; } if (ivData != NULL) { delete[] ivData; } if (section != NULL) { delete[] section; } } /******************************************************************************/ void ZynqMpBootHeader::Build(BootImage& bi, Binary& cache) { ResizeSection(bi); if (section != NULL) { cache.Sections.push_back(section); } /* If the boot header is imported from a bootimage file, no need to build */ if (prebuilt) { if (bi.bifOptions->GetRegInitFileName() != "") { BuildRegInitTable(bi.options); } return; } SetWidthDetectionWord(); SetIdentificationWord(); SetEncryptionKeySource(bi.options.GetEncryptedKeySource()); SetShutterValue(bi.bifOptions->GetShutterValue()); SetUdf(bi.options.bifOptions->GetUdfBhFile()); SetGreyOrBlackKey(bi.bifOptions->GetBhKeyFile()); SetGreyOrBlackKekIV(bi.bifOptions->GetBHKekIVFile()); SetSecureHdrIv(bi.options.secHdrIv); BuildRegInitTable(bi.options); SetPufData(bi); } /******************************************************************************/ void ZynqMpBootHeader::Link(BootImage& bi) { if (prebuilt) { AddAcSizeToTotalFsblSize(bi); ImageHeader* fsbl = bi.imageHeaderTable->GetFSBLImageHeader(); if (fsbl != NULL) { PartitionHeader& bootloaderHdr(*(fsbl->GetPartitionHeaderList().front())); BootloaderAddressAndSizeCheck(bootloaderHdr); SetSourceOffset((uint32_t)bootloaderHdr.partition->section->Address); if (bi.imageHeaderTable->section != NULL) { if (!Binary::CheckAddress(bi.imageHeaderTable->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Image Header Offset is %llX", bi.imageHeaderTable->section->Address); } SetImageHeaderByteOffset((uint32_t)bi.imageHeaderTable->section->Address); } if (bi.partitionHeaderTable->firstSection != NULL) { if (!Binary::CheckAddress(bi.partitionHeaderTable->firstSection->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Partition Header Offset is %llX", bi.partitionHeaderList.front()->section->Address); } SetPartitionHeaderByteOffset((uint32_t)bi.partitionHeaderTable->firstSection->Address); } SetHeaderChecksum(); } return; } ImageHeaderTable* iHT = bi.imageHeaderTable; ImageHeader* fsbl = iHT->GetFSBLImageHeader(); slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; SetFsblAttributes(bi); SetBootVectors(bi); if (fsbl == NULL) { SetBHForSinglePartitionImage(bi); } else { PartitionHeader& bootloaderHdr(*(fsbl->GetPartitionHeaderList().front())); BootloaderAddressAndSizeCheck(bootloaderHdr); SetSourceOffset((uint32_t)bootloaderHdr.partition->section->Address); SetFsblLength((uint32_t)bootloaderHdr.GetPartitionSize()); SetFsblExecAddress((uint32_t)bootloaderHdr.GetExecAddress()); SetBHForXIP(bi); SetPmuFwLength(bi.GetPmuFwSize()); SetTotalPmuFwLength(bi.GetTotalPmuFwSize()); SetSecureHdrIv(bi.options.secHdrIv); if (fsbl->IsStaticFlagSet() || bi.bifOptions->GetXipMode()) { SetFsblLength(0); SetTotalFsblLength(0); } else { SetFsblLength(bi.GetFsblFwSize()); SetTotalFsblLength(bi.GetTotalFsblFwSize()); } } if (iHT->section != NULL) { if (!Binary::CheckAddress(iHT->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Image Header Offset is %llX", iHT->section->Address); } SetImageHeaderByteOffset((uint32_t)iHT->section->Address); } if (bi.partitionHeaderTable->firstSection != NULL) { if (!Binary::CheckAddress(bi.partitionHeaderTable->firstSection->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Partition Header Offset is %llX", bi.partitionHeaderList.front()->section->Address); } SetPartitionHeaderByteOffset((uint32_t)bi.partitionHeaderTable->firstSection->Address); } SetHeaderChecksum(); } /******************************************************************************/ void ZynqMpBootHeader::ResizeSection(BootImage &bi) { /* If PUF is present in BH, increase the BH size */ if (bi.bifOptions->GetPufHdLoc() == PufHdLoc::PUFinBH) { uint32_t newBhSize = sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable) + PUF_DATA_LENGTH; section->IncreaseLengthAndPadTo(newBhSize, 0); } bHTable = (ZynqMpBootHeaderStructure*)section->Data; } /******************************************************************************/ void ZynqMpBootHeader::SetBootVectors(BootImage &bi) { std::vector bootvectors = bi.bifOptions->GetBootVectorArray(); uint32_t core = bi.GetCore(); if (bootvectors.size() == 0) { for (int i = 0; i < MAX_BOOT_VECTORS; i++) { bHTable->bootVectors[i] = ((core == Core::A53Singlex64) ? ARM_JUMP_TO_SELF_INSTRUCION_A53_64 : ARM_JUMP_TO_SELF_INSTRUCION); } } else { for (uint32_t i = 0; i < MAX_BOOT_VECTORS; i++) { bHTable->bootVectors[i] = ((i < bootvectors.size()) ? bootvectors[i] : (((core == Core::A53Singlex64) ? ARM_JUMP_TO_SELF_INSTRUCION_A53_64 : ARM_JUMP_TO_SELF_INSTRUCION))); } } } /******************************************************************************/ void ZynqMpBootHeader::SetWidthDetectionWord(void) { bHTable->widthDetectionWord = WIDTH_DETECTION; } /******************************************************************************/ void ZynqMpBootHeader::SetIdentificationWord(void) { bHTable->identificationWord = HEADER_ID_WORD; } /******************************************************************************/ void ZynqMpBootHeader::SetEncryptionKeySource(KeySource::Type keyType) { keyIvMust = false; switch (keyType) { case KeySource::EfuseRedKey: bHTable->encryptionKeySource = EFUSE_RED_KEY; break; case KeySource::BbramRedKey: bHTable->encryptionKeySource = BBRAM_RED_KEY; break; case KeySource::EfuseBlkKey: bHTable->encryptionKeySource = EFUSE_BLK_KEY; keyIvMust = true; break; case KeySource::BhBlkKey: bHTable->encryptionKeySource = BH_BLACK_KEY; keyIvMust = true; break; case KeySource::EfuseGryKey: bHTable->encryptionKeySource = EFUSE_GRY_KEY; keyIvMust = true; break; case KeySource::BhGryKey: bHTable->encryptionKeySource = BH_GRY_KEY; keyIvMust = true; break; case KeySource::BhKupKey: bHTable->encryptionKeySource = BH_KUP_KEY; break; case KeySource::None: default: bHTable->encryptionKeySource = 0; break; } } /******************************************************************************/ void ZynqMpBootHeader::SetFsblExecAddress(uint32_t address) { bHTable->fsblExecAddress = address; } /******************************************************************************/ void ZynqMpBootHeader::SetSourceOffset(uint32_t offset) { bHTable->sourceOffset = offset; if (slaveBootSplitMode) { bHTable->sourceOffset -= allHdrSize; } } /******************************************************************************/ void ZynqMpBootHeader::SetPmuFwLength(uint32_t size) { bHTable->pmuFwLength = size; } /******************************************************************************/ void ZynqMpBootHeader::SetTotalPmuFwLength(uint32_t size) { if (size > PMU_MAX_SIZE) { LOG_ERROR("Total PMU Firmware size %dKB > maximum allowable size (128KB)", size / 1024); } bHTable->totalPmuFwLength = size; } /******************************************************************************/ void ZynqMpBootHeader::SetFsblLength(uint32_t size) { bHTable->fsblLength = size; } /******************************************************************************/ void ZynqMpBootHeader::SetTotalFsblLength(uint32_t size) { bHTable->totalFsblLength = size; } /******************************************************************************/ void ZynqMpBootHeader::AddAcSizeToTotalFsblSize(BootImage & bi) { /* If authentication is enabled, and the image is not already authenticated, i.e if plain/encrypted image is provided through release mode flow, then add AC size to FSBL size */ if ((bi.imageList.front()->GetAuthenticationType() != Authentication::None) && (bi.imageList.front()->IsBootloader())) { if (!(bi.imageList.front()->GetAuthContext()->preSigned)) { /* The AC should be appended to a 64-byte aligned FSBL + PMU partition So find the pad length required for alignment and then add AC size */ uint32_t padLength = ((64 - ((bHTable->totalFsblLength + bHTable->totalPmuFwLength) & 63)) & 63); bHTable->totalFsblLength += (bi.headerAC->section->Length + padLength); SetHeaderChecksum(); } } } /******************************************************************************/ void ZynqMpBootHeader::SetBHForSinglePartitionImage(BootImage& bi) { SetSourceOffset(0); SetFsblExecAddress(0); SetPmuFwLength(0); SetTotalPmuFwLength(0); SetFsblLength(0); SetSecureHdrIv(bi.options.secHdrIv); SetTotalFsblLength(0); } /******************************************************************************/ void ZynqMpBootHeader::SetBHForXIP(BootImage& bi) { if (bi.bifOptions->GetXipMode()) { SetFsblLength(0); SetTotalFsblLength(0); if (GetFsblExecAddress() < GetXipBaseAddr() + bi.options.totalHeadersSize + bi.GetTotalPmuFwSize()) { LOG_ERROR("XIP Execution address is overlapping the Boot Header and/or other regions of the image", GetFsblExecAddress()); } if (GetTotalFsblLength() == 0) { SetSourceOffset(GetSourceOffset()); } } } /******************************************************************************/ void ZynqMpBootHeader::SetFsblAttributes(BootImage& bi) { if (bi.imageList.size() != 0) { uint8_t cksumType = 0; cksumType = bi.partitionHeaderList.front()->imageHeader->GetChecksumContext()->Type(); bHTable->fsblAttributes = bi.bifOptions->GetOptKey() << OPT_KEY_BIT_SHIFT; bHTable->fsblAttributes |= bi.bifOptions->GetAuthOnly() << AUTH_ONLY_BIT_SHIFT; bHTable->fsblAttributes |= bi.bifOptions->GetPufHdLoc() << PUF_HD_BIT_SHIFT; bHTable->fsblAttributes |= cksumType << BI_HASH_BIT_SHIFT; bHTable->fsblAttributes |= bi.GetCore() << CORE_BIT_SHIFT; bHTable->fsblAttributes |= bi.GetAuthHashAlgo() << AUTH_HASH_BIT_SHIFT; bHTable->fsblAttributes |= bi.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; bHTable->fsblAttributes |= bi.bifOptions->GetPufMode() << BH_PUF_MODE_BIT_SHIFT; } } /******************************************************************************/ void ZynqMpBootHeader::SetFsblAttributes(uint32_t fsblattributes) { bHTable->fsblAttributes = fsblattributes; } /******************************************************************************/ void ZynqMpBootHeader::SetHeaderChecksum(void) { /* Set the simple header checksum value by adding up all of the 32 bit values from the Width Detection Word (0x20) to the fsbl attributes (0x44) (10 words, 40 bytes) */ bHTable->headerChecksum = ComputeWordChecksum(&bHTable->widthDetectionWord, 40); } /******************************************************************************/ void ZynqMpBootHeader::SetGreyOrBlackKey(std::string keyFile) { uint8_t* bhKeyData = new uint8_t[BLK_GRY_KEY_LENGTH * 4]; memset(bhKeyData, 0, BLK_GRY_KEY_LENGTH * 4); if (keyFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(keyFile, bhKeyData, BLK_GRY_KEY_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Grey/Black key in BootHeader.\n Expected length for Grey/Black key is 32 bytes"); } } memcpy(&bHTable->greyOrBlackKey, bhKeyData, BLK_GRY_KEY_LENGTH * 4); delete[] bhKeyData; } /******************************************************************************/ void ZynqMpBootHeader::SetShutterValue(uint32_t value) { bHTable->shutterValue = value; } /******************************************************************************/ void ZynqMpBootHeader::SetUdf(std::string udfFile) { uint8_t bhUdfData[UDF_BH_SIZE_ZYNQMP * sizeof(uint32_t)]; memset(bhUdfData, 0, UDF_BH_SIZE_ZYNQMP * 4); if (udfFile != "") { LoadUdfData(udfFile, bhUdfData, UDF_BH_SIZE_ZYNQMP); } memcpy((uint8_t*)bHTable->udf, bhUdfData, UDF_BH_SIZE_ZYNQMP * sizeof(uint32_t)); } /******************************************************************************/ void ZynqMpBootHeader::SetImageHeaderByteOffset(uint32_t address) { bHTable->imageHeaderByteOffset = address; if (slaveBootSplitMode) { bHTable->imageHeaderByteOffset = 0; } } /******************************************************************************/ void ZynqMpBootHeader::SetPartitionHeaderByteOffset(uint32_t address) { bHTable->partitionHeaderByteOffset = address; if (slaveBootSplitMode) { bHTable->partitionHeaderByteOffset = 0; } } /******************************************************************************/ void ZynqMpBootHeader::SetSecureHdrIv(uint8_t* iv) { if (iv == NULL) { memset(bHTable->secureHdrIv, 0, IV_LENGTH * WORD_SIZE_IN_BYTES); } else { memcpy(bHTable->secureHdrIv, iv, IV_LENGTH * WORD_SIZE_IN_BYTES); } } /******************************************************************************/ void ZynqMpBootHeader::SetGreyOrBlackKekIV(std::string ivFile) { uint8_t* ivData = new uint8_t[IV_LENGTH * 4]; memset(ivData, 0, IV_LENGTH * 4); if (ivFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(ivFile, ivData, IV_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Black/Grey Key IV.\n Expected length for Grey/Black IV is 12 bytes"); } } else { if (keyIvMust) { LOG_ERROR("Black/Grey IV is mandatory in case of Black/Grey key sources\n Please use [bh_key_iv] to specify the IV in BIF file"); } } memcpy(&bHTable->greyOrBlackIV, ivData, IV_LENGTH * 4); delete[] ivData; } /******************************************************************************/ void ZynqMpBootHeader::SetPufData(BootImage &bi) { if (bi.bifOptions->GetPufHdLoc() == PufHdLoc::PUFinBH) { uint8_t* pufData = new uint8_t[PUF_DATA_LENGTH]; memset(pufData, 0, PUF_DATA_LENGTH); if (bi.bifOptions->GetPufHelperFile() != "") { FileImport fileReader; if (!fileReader.LoadHexData(bi.bifOptions->GetPufHelperFile(), pufData, PUF_DATA_LENGTH)) { LOG_ERROR("Invalid no. of data bytes for PUF Helper Data.\n Expected length for PUF Helper Data is 1544 bytes"); } } memcpy((uint8_t*)bHTable + GetBootHeaderSize() + GetRegInitTableSize(), pufData, PUF_DATA_LENGTH); delete[] pufData; } } /******************************************************************************/ uint32_t* ZynqMpBootHeader::GetChecksumStartPtr(void) { return &bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetBootHeaderSize(void) { return sizeof(ZynqMpBootHeaderStructure); } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetWidthDetectionWord(void) { return bHTable->widthDetectionWord; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetIdentificationWord(void) { return bHTable->identificationWord; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetSourceOffset(void) { return bHTable->sourceOffset; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetHeaderChecksum(void) { return bHTable->headerChecksum; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetFsblLength(void) { return bHTable->fsblLength; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetTotalFsblLength(void) { return bHTable->totalFsblLength; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetFsblExecAddress(void) { return bHTable->fsblExecAddress; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetImageHeaderByteOffset(void) { return bHTable->imageHeaderByteOffset; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetPartitionHeaderByteOffset(void) { return bHTable->partitionHeaderByteOffset; } /******************************************************************************/ KeySource::Type ZynqMpBootHeader::GetEncryptionKeySource(void) { switch (bHTable->encryptionKeySource) { case BBRAM_RED_KEY: return KeySource::BbramRedKey; break; case EFUSE_RED_KEY: return KeySource::EfuseRedKey; break; case EFUSE_BLK_KEY: return KeySource::EfuseBlkKey; break; case BH_BLACK_KEY: return KeySource::BhBlkKey; break; case EFUSE_GRY_KEY: return KeySource::EfuseGryKey; break; case BH_GRY_KEY: return KeySource::BhGryKey; break; case BH_KUP_KEY: return KeySource::BhKupKey; break; default: return KeySource::None; break; } } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetPmuFwLength(void) { return bHTable->pmuFwLength; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetTotalPmuFwLength(void) { return bHTable->totalPmuFwLength; } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetFsblAttributes(void) { return bHTable->fsblAttributes; } /******************************************************************************/ uint32_t ZynqMpBootHeader::CalcHeaderChecksum(void* addr, size_t len) { return ComputeWordChecksum(addr, len); } /******************************************************************************/ void ZynqMpBootHeader::BuildRegInitTable(Options& options) { regTable.Build(options, registerInitTable()); } /******************************************************************************/ uint32_t ZynqMpBootHeader::GetXipBaseAddr(void) { return LQSPI_BASE_ADDR_ZYNQMP; } xilinx-bootgen-2024.2/bootheader-zynqmp.h000077500000000000000000000136561475706442400204250ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTHEADER_ZYNQMP_H_ #define _BOOTHEADER_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader.h" #include "bootimage.h" #include "bifoptions.h" #include "fileutils.h" #include "imageheadertable-zynqmp.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define UDF_BH_SIZE_ZYNQMP 10 #define PMU_MAX_SIZE 0x20000 //128KB #define FSBL_MAX_SIZE 0x3E800 //250KB /* Masks values for BH attributes */ #define OPT_KEY_BIT_MASK 3 #define AUTH_ONLY_BIT_MASK 3 #define PUF_HD_BIT_MASK 3 #define BI_HASH_BIT_MASK 3 #define BH_RSA_BIT_MASK 3 #define CORE_BIT_MASK 3 #define BH_PUF_MODE_BIT_MASK 3 #define AUTH_HASH_BIT_MASK 3 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t bootVectors [MAX_BOOT_VECTORS]; // (0x00) uint32_t widthDetectionWord; // (0x20) uint32_t identificationWord; // (0x24) uint32_t encryptionKeySource; // (0x28) uint32_t fsblExecAddress; // (0x2C) uint32_t sourceOffset; // (0x30) uint32_t pmuFwLength; // (0x34) uint32_t totalPmuFwLength; // (0x38) uint32_t fsblLength; // (0x3C) uint32_t totalFsblLength; // (0x40) uint32_t fsblAttributes; // (0x44) uint32_t headerChecksum; // (0x48) uint32_t greyOrBlackKey [BLK_GRY_KEY_LENGTH]; // (0x4C-0x68) uint32_t shutterValue; // (0x6c) uint32_t udf [UDF_BH_SIZE_ZYNQMP]; // (0x70-0x94) uint32_t imageHeaderByteOffset; // (0x98) uint32_t partitionHeaderByteOffset; // (0x9C) uint32_t secureHdrIv [IV_LENGTH]; // (0xA0-0xA8) uint32_t greyOrBlackIV [IV_LENGTH]; // (0xAC-0xB4) } ZynqMpBootHeaderStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpBootHeader : public BootHeader { public: ZynqMpBootHeader(); ZynqMpBootHeader(std::ifstream& src); ~ZynqMpBootHeader(); void Build(BootImage& bi, Binary& cache); void Link(BootImage& bi); void ResizeSection(BootImage &bi); void AddAcSizeToTotalFsblSize(BootImage& bi); void SetBHForSinglePartitionImage(BootImage& bi); void SetBHForXIP(BootImage & bi); void BuildRegInitTable(Options& options); uint32_t CalcHeaderChecksum(void* addr, size_t len); void SetBootVectors(BootImage &bi); void SetWidthDetectionWord(void); void SetIdentificationWord(void); void SetSourceOffset(uint32_t offset); void SetHeaderChecksum(void); void SetFsblLength(uint32_t size); void SetTotalFsblLength(uint32_t size); void SetFsblExecAddress(uint32_t address); void SetShutterValue(uint32_t value); void SetUdf(std::string udfFile); void SetImageHeaderByteOffset(uint32_t address); void SetPartitionHeaderByteOffset(uint32_t address); void SetEncryptionKeySource(KeySource::Type keyType); void SetPmuFwLength(uint32_t size); void SetTotalPmuFwLength(uint32_t size); void SetFsblAttributes(BootImage& bi); void SetFsblAttributes(uint32_t fsblattributes); void SetGreyOrBlackKey(std::string keyFile); void SetGreyOrBlackKekIV(std::string ivFile); void SetSecureHdrIv(uint8_t* iv); void SetPufData(BootImage &bi); uint32_t GetBootHeaderSize(void); uint32_t GetWidthDetectionWord(void); uint32_t GetIdentificationWord(void); uint32_t GetSourceOffset(void); uint32_t GetHeaderChecksum(void); uint32_t GetFsblLength(void); uint32_t GetTotalFsblLength(void); uint32_t GetFsblExecAddress(void); uint32_t GetImageHeaderByteOffset(void); uint32_t GetPartitionHeaderByteOffset(void); uint32_t GetPmuFwLength(void); uint32_t GetTotalPmuFwLength(void); uint32_t GetFsblAttributes(void); uint32_t GetXipBaseAddr(void); uint32_t* GetChecksumStartPtr(void); KeySource::Type GetEncryptionKeySource(void); /* MP - Revisit - To suppress the vesion check warning in parse boot image for zynqmp */ uint32_t GetHeaderVersion(void) { return 0xFFFFFFFF; } private: ZynqMpBootHeaderStructure *bHTable; bool keyIvMust; uint8_t* pufData; uint8_t* bhKeyData; uint8_t* ivData; }; #endif xilinx-bootgen-2024.2/bootheader.cpp000077500000000000000000000113271475706442400174150ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include #include "options.h" #include "fileutils.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ BootHeader::BootHeader() : prebuilt(false) , bhSize(0) , fullBhSize(0) , allHdrSize(0) , slaveBootSplitMode(false) { } /******************************************************************************/ void BootHeader::BootloaderAddressAndSizeCheck(PartitionHeader & hdr) { if (!Binary::CheckAddress(hdr.partition->section->Address)) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Bootloader is placed at %llX", hdr.partition->section->Address); } if (!Binary::CheckAddress(hdr.GetPartitionSize())) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Bootloader size is %llX", hdr.GetPartitionSize()); } if (!Binary::CheckAddress(hdr.GetLoadAddress())) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Bootloader load address is %llX", hdr.GetLoadAddress()); } if (!Binary::CheckAddress(hdr.GetExecAddress())) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Bootloader exec address is %llX", hdr.GetExecAddress()); } if (!Binary::CheckAddress(hdr.GetTransferSize())) { LOG_ERROR("Bootgen does not support addresses larger than 32 bits. Bootloader transfer size is %llX", hdr.GetTransferSize()); } } /******************************************************************************/ void BootHeader::Copy(BootHeader* otherHeader) { if (prebuilt) { LOG_ERROR("Cannot copy bootheader, since it has already been imported"); } /* The BH Section Length can vary due to PUF Helper Data */ if (section->Length < otherHeader->section->Length) { uint32_t newBhSize = otherHeader->section->Length; uint8_t* newDataPtr = new uint8_t[newBhSize]; delete[] section->Data; section->Data = newDataPtr; section->Length = newBhSize; } memcpy(section->Data, otherHeader->section->Data,section->Length); prebuilt = true; } /******************************************************************************/ void BootHeader::LoadUdfData(const std::string& udfFilename, uint8_t* udfData, uint32_t size) { FILE* fPtr; int datum, ret; uint32_t nbytes = 0; std::string filename(udfFilename); std::string baseFile = StringUtils::BaseName(filename); fPtr = fopen(filename.c_str(),"r"); if (fPtr) { while ((ret = fscanf(fPtr, "%2X", &datum)) != EOF) { if (ret == 1) { if (datum < 0 || datum > 255) { LOG_ERROR("Bad hex conversion in %s", baseFile.c_str()); } if (nbytes == size*4) { LOG_ERROR("More than %d bytes in the Boot Header UDF Data file - %s is not allowed.", size*4, baseFile.c_str()); } udfData[nbytes++] = datum; } else { LOG_ERROR("Error reading hex characters from file - %s ", baseFile.c_str()); } } } else { LOG_ERROR("Failure to open boot header udf file - %s ", baseFile.c_str()); } fclose(fPtr); } /******************************************************************************/ bool BootHeader::GetPrebuiltFlag(void) { return prebuilt; } xilinx-bootgen-2024.2/bootheader.h000077500000000000000000000133231475706442400170600ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTHEADER_H_ #define _BOOTHEADER_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "logger.h" #include "imageheadertable.h" /* Forward class references */ class BaseThing; class Options; class BootImage; class Section; class ImageHeader; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define ARM_JUMP_TO_SELF_INSTRUCION 0xEAFFFFFE #define ARM_JUMP_TO_SELF_INSTRUCION_A53_64 0x14000000 #define WIDTH_DETECTION 0xAA995566 #define HEADER_ID_WORD 0x584C4E58 #define BOOTHEADER_VERSION 0x01010000 #define QSPI_CONFIG_WORD 0x1 #define MAX_BOOT_VECTORS 8 #define MAX_REGISTER_INITS 256 #define BLK_GRY_KEY_LENGTH 8 #define IV_LENGTH 3 #define PUF_DATA_LENGTH 1544 #define INVALID_REGISTER_ADDRESS 0xFFFFFFFF /* Keys Source */ #define EFUSE_RED_KEY 0xA5C3C5A3 #define BBRAM_RED_KEY 0x3A5C3C5A #define EFUSE_BLK_KEY 0xA5C3C5A5 #define BH_BLACK_KEY 0xA35C7C53 #define EFUSE_GRY_KEY 0xA5C3C5A7 #define BH_GRY_KEY 0xA35C7CA5 #define BH_KUP_KEY 0xA3A5C3C5 /* Bit shifts for FSBL config parameters */ #define OPT_KEY_BIT_SHIFT 2 #define AUTH_ONLY_BIT_SHIFT 4 #define PUF_HD_BIT_SHIFT 6 #define BI_HASH_BIT_SHIFT 8 #define CORE_BIT_SHIFT 10 #define AUTH_HASH_BIT_SHIFT 12 #define BH_RSA_BIT_SHIFT 14 #define BH_PUF_MODE_BIT_SHIFT 16 #define OPT_KEY_BIT_MASK 3 #define AUTH_ONLY_BIT_MASK 3 #define PUF_HD_BIT_MASK 3 #define BI_HASH_BIT_MASK 3 #define BH_RSA_BIT_MASK 3 #define BH_PUF_MODE_BIT_MASK 3 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t address; uint32_t value; } RegisterInitPair; typedef struct { RegisterInitPair registerInitialization [MAX_REGISTER_INITS]; } RegisterInitTable; typedef struct { uint64_t baseaddr; uint64_t size; } RegisterInitAddressRange; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class RegisterTable { public: RegisterTable() : regtab(NULL) , count(0) , fileParseEnd(false) { invalidAddr.clear(); } void Build (Options& option, RegisterInitTable* regTable0); void Add (Options& options, uint32_t address, uint32_t value); std::string filename; private: RegisterInitTable* regtab; uint32_t count; bool fileParseEnd; std::vector invalidAddr; }; /******************************************************************************/ class BootHeader : public BaseThing { public: BootHeader(); virtual ~BootHeader() {} virtual void Build(BootImage& bi, Binary& cache) { }; virtual void Link(BootImage& bi) { }; virtual void BuildRegInitTable (Options& options) { }; virtual void ResizeSection(BootImage &bi) {}; void BootloaderAddressAndSizeCheck(PartitionHeader& hdr); void Copy (BootHeader* otherHeader); void LoadUdfData (const std::string& udfBHFilename, uint8_t* udfData, uint32_t size); bool GetPrebuiltFlag (void); virtual uint32_t GetBootHeaderSize(void) { return 0; } uint32_t GetRegInitTableSize (void) { return sizeof(RegisterInitTable); } RegisterTable regTable; protected: bool prebuilt; uint32_t bhSize; bool slaveBootSplitMode; uint32_t fullBhSize; uint32_t allHdrSize; inline RegisterInitTable* registerInitTable() { if (section == NULL) { LOG_ERROR("Section was not allocated"); } return (RegisterInitTable*)(section->Data + GetBootHeaderSize()); } }; #endif xilinx-bootgen-2024.2/bootimage-versal.cpp000077500000000000000000002311401475706442400205360ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage-versal.h" #include "partitionheadertable-versal.h" #include "binary-versal.h" #include "checksum-versal.h" #include "authentication-versal.h" extern "C" { #include "cdo-command.h" #include "cdo-overlay.h" #include "cdo-binary.h" #include "cdo-load.h" }; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalBootImage::VersalBootImage(Options& options, uint8_t index) : BootImage(options, index) { partitionHeaderList.clear(); options.SetDefaultAlignment(16); bootHeader = new VersalBootHeader(); imageHeaderTable = new VersalImageHeaderTable(); partitionHeaderTable = new VersalPartitionHeaderTable(); currentEncryptCtx = new VersalEncryptionContext(); currentAuthCtx = new VersalAuthenticationContext(Authentication::RSA); SetLegacyEncryptionFlag(true); partitionOutput = new VersalPartitionOutput(); hash = new HashSha3(); cache = new VersalBinary(); checksumTable = new VersalChecksumTable(); currentAuthCtx->hashType = AuthHash::Sha3; currentAuthCtx->hash = hash; partitionHeaderTable->firstSection = NULL; convertAieElfToCdo = true; current_image_block = 0; createSubSystemPdis = true; } /******************************************************************************/ VersalBootImage::~VersalBootImage() { } /******************************************************************************/ void VersalBootImage::ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType) { /* Configure the encryption context */ bool aesKeyFileExists = false; switch (encryptType) { case Encryption::AES: if (image->IsBootloader()) { switch (image->GetEncryptionKeySrc()) { case KeySource::EfuseRedKey: case KeySource::BbramRedKey: case KeySource::EfuseBlkKey: case KeySource::BbramBlkKey: case KeySource::BhBlkKey: case KeySource::EfuseGryKey: case KeySource::BbramGryKey: case KeySource::BhGryKey: case KeySource::None: break; default: LOG_ERROR("BIF attribute error !!!\n\t\tInvalid 'keysrc' mentioned for Bootloader."); break; } bootloaderEncrypt = true; bootloaderKeySource = image->GetEncryptionKeySrc(); } if (bootloaderFound && !bootloaderEncrypt && !bootloaderAuthenticate) { LOG_ERROR("Bootloader must be encrypted or atleast authenticated to encrypt rest of the partitions"); } /* Remove if when [keysrc_encryption] id deprecated*/ if (image->IsBootloader()) { if (image->GetEncryptionKeySrc() == KeySource::None && bifOptions->GetEncryptionKeySource() == KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' must be specified when 'encryption' is enabled for partition : %s.", image->GetName().c_str()); } } else { if (image->GetEncryptionKeySrc() == KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' must be specified when 'encryption' is enabled for partition : %s.", image->GetName().c_str()); } } if (image->GetAesKeyFile() != "") { /* If no key file found in partition specific attributes - ERROR If specified key file non-existent - Set generateAesKeyFile flag */ std::ifstream keyFile(image->GetAesKeyFile()); aesKeyFileExists = keyFile.good(); if (!aesKeyFileExists) { image->SetAesKeyFileGeneration(true); } } options.bifOptions->SetHeaderEncryption(true); if (imageHeaderTable->GetEncryptContext() == NULL) { imageHeaderTable->SetEncryptContext(new VersalEncryptionContext(this->currentEncryptCtx)); } image->SetEncryptContext(new VersalEncryptionContext(this->currentEncryptCtx)); break; case Encryption::None: /* Remove if when [keysrc_encryption] id deprecated*/ if (image->IsBootloader()) { if (image->GetEncryptionKeySrc() != KeySource::None || bifOptions->GetEncryptionKeySource() != KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' can be specified only when 'encryption' is enabled for partition : %s.", image->GetName().c_str()); } } else { if (image->GetEncryptionKeySrc() != KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' can be specified only when 'encryption' is enabled for partition : %s.", image->GetName().c_str()); } } image->ValidateEncryptionAttributes(*this); if (options.bifOptions->metaHdrAttributes.encrypt != Encryption::None) { if (options.bifOptions->metaHdrAttributes.encrKeySource == KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' must be specified when 'encryption' is enabled for MetaHeader."); } options.bifOptions->SetHeaderEncryption(true); if (imageHeaderTable->GetEncryptContext() == NULL) { imageHeaderTable->SetEncryptContext(new VersalEncryptionContext()); } } else if(options.bifOptions->metaHdrAttributes.encrKeySource != KeySource::None) { LOG_ERROR("BIF attribute error !!!\n\t 'keysrc' can be specified only when 'encryption' is enabled for MetaHeader."); } image->SetEncryptContext(new NoneEncryptionContext()); break; default: image->SetEncryptContext(NULL); break; } } /******************************************************************************/ void VersalBootImage::ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions) { /* Configure the authentication context */ std::string spkSignFile = options.GetSpkSigFileName(); switch (authType) { case Authentication::RSA: case Authentication::ECDSA: case Authentication::ECDSAp521: { if (image->IsBootloader()) { bootloaderAuthenticate = true; } if (bootloaderFound && !bootloaderAuthenticate) { LOG_ERROR("Bootloader must be authenticated to authenticate rest of the partitions"); } image->SetAuthenticationType(authType); options.bifOptions->SetHeaderAC(true); authOnPartitionFound = true; currentAuthCtx->hashType = GetAuthHashAlgo(); currentAuthCtx->ppkFile = image->GetPpkFile(); currentAuthCtx->pskFile = image->GetPskFile(); currentAuthCtx->spkFile = image->GetSpkFile(); currentAuthCtx->sskFile = image->GetSskFile(); currentAuthCtx->spkSignFile = image->GetSpkSignFile(); currentAuthCtx->spkIdentification = image->GetPartitionRevocationId(); currentAuthCtx->SetSPKSignatureFile(image->GetSpkSignFile()); if (image->GetBhSignFile() != "") { currentAuthCtx->bhSignFile = image->GetBhSignFile(); } AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); if (authType == Authentication::ECDSA) { AuthenticationContext::SetAuthenticationKeyLength(EC_P384_KEY_LENGTH); } image->SetAuthContext(new VersalAuthenticationContext(currentAuthCtx, authType)); AuthenticationContext* authCtx = image->GetAuthContext(); authCtx->SetPresignFile(partitionbifoptions->presignFile); authCtx->SetUdfFile(partitionbifoptions->udfDataFile); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } } break; case Authentication::None: default: { if (options.bifOptions->metaHdrAttributes.authenticate != Authentication::None) { if (image->IsBootloader()) { //LOG_ERROR("Bootloader must be authenticated to authenticate the Meta Header"); } } image->SetAuthenticationType(Authentication::None); image->SetAuthContext(new NoneAuthenticationContext()); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } } break; } } /******************************************************************************/ void VersalBootImage::ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType) { /* Configure the checksum context */ switch (checksumType) { case Checksum::MD5: case Checksum::SHA2: LOG_ERROR("BIF attribute error !!!\n\t\t 'checksum=sha2/md5' is not supported in VERSAL architecture."); break; case Checksum::SHA3: image->SetChecksumContext(new VersalSHA3ChecksumContext()); break; case Checksum::None: default: image->SetChecksumContext(new NoneChecksumContext()); break; } } /******************************************************************************/ void VersalBootImage::ParseBootImage(PartitionBifOptions* it) { LOG_INFO("Importing BootImage..."); std::string baseFile = StringUtils::BaseName(it->filename); bool full_pdi = true; bool smap_exists = false; bool this_bootimage = false; if (StringUtils::GetExtension(baseFile) == ".mcs") { LOG_ERROR("Parsing mcs format file is not supported : %s", baseFile.c_str()); } FILE *binFile = fopen(it->filename.c_str(), "rb"); if (!binFile) { LOG_ERROR("Cannot read file %s", it->filename.c_str()); } VersalBootHeaderStructure* bH = new VersalBootHeaderStructure; fread(bH, 1, sizeof(VersalBootHeaderStructure), binFile); if (bH->widthDetectionWord != 0xAA995566) { full_pdi = false; } uint32_t firstWord = *bH->smapWords; if ((firstWord == 0xDD000000) || (firstWord == 0x00DD0000) || (firstWord == 0x0000DD00) || (firstWord == 0x0000000DD)) { smap_exists = true; } delete bH; bH = NULL; fclose(binFile); std::ifstream src(it->filename.c_str(), std::ios::binary); if (!src.good()) { LOG_ERROR("Failure in reading bootimage file for import - %s ", baseFile.c_str()); } VersalBootHeader* importedBh = NULL; if (!full_pdi) { LOG_WARNING("File %s is not a full PDI. It is missing the boot header", baseFile.c_str()); bootloaderFound = false; if (smap_exists) { src.seekg(sizeof(VersalSmapWidthTable)); } else { src.seekg(0); } } else { importedBh = new VersalBootHeader(src); if (importedBh->GetHeaderVersion() != 0xFFFFFFFF) { LOG_WARNING("This version of bootgen may not support the bootimage header in %s ", baseFile.c_str()); LOG_WARNING("The version of the imported header is 0x%X, and this version of bootgen only supports 0x%X", importedBh->GetHeaderVersion(), BOOTHEADER_VERSION); } /* Authentication attribues to be appended to the attributes from stage2-Encrypted Image */ uint32_t attributes = importedBh->GetBHAttributes(); if (options.bifOptions->GetBhRsa() != BhRsa::BhRsaDisable) { attributes |= options.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; } if (options.IsVersalNetSeries()) { if (it->delayAuth || (it->authType != Authentication::None)) { attributes |= BH_RSA_SINGED_BIT_MASK << BH_RSA_SINGED_BIT_SHIFT; } } if (authHash != AuthHash::Sha3) { attributes |= authHash << AUTH_HASH_BIT_SHIFT; } if (options.bifOptions->GetDpaCM() != DpaCM::DpaCMDisable) { attributes |= options.bifOptions->GetDpaCM() << DPA_CM_BIT_SHIFT; } if (options.bifOptions->GetDice() != DICE::DiceDisable) { attributes |= options.bifOptions->GetDice() << BH_DICE_BIT_SHIFT; } importedBh->SetBHAttributes(attributes); /* If imported header has a non-zero source offset, it must be a FSBL header, so it must be copied */ if (importedBh->GetSourceOffset() != 0) { LOG_INFO("Copying bootheader from %s ", baseFile.c_str()); SetAssumeEncryptionFlag(false); options.SetEncryptedKeySource(importedBh->GetEncryptionKeySource()); bootHeader->Copy(importedBh); } src.seekg(importedBh->GetImageHeaderByteOffset()); } CheckForIhtAttributes(baseFile); imageHeaderTable = new VersalImageHeaderTable(src); if (imageHeaderTable->iht_optional_data_length != 0) { src.seekg(importedBh->GetImageHeaderByteOffset() + sizeof(VersalImageHeaderTableStructure)); iht_optional_data_length = imageHeaderTable->iht_optional_data_length; iht_optional_data = (uint32_t*)malloc(iht_optional_data_length); src.read((char*)iht_optional_data, iht_optional_data_length); } uint32_t offset = imageHeaderTable->GetFirstImageHeaderOffset() * sizeof(uint32_t); uint32_t imageCount = imageHeaderTable->GetImageCount(); bool bootloader_found = false; do { imageCount--; bool IsBootloader = false; /* IsBootloader flag is important to rearrange the sections in the StackAndAlign stage This flag needs to be passed on while creating the image header, and from there it is populated in partition headers, sections etc. */ if (full_pdi) { if (bootloader_found == false) { IsBootloader = true; bootloader_found = true; } } if (createSubSystemPdis == true) { src.seekg(offset); SubSysImageHeader* subsys = new SubSysImageHeader(src); for (uint32_t i = 0; i < subsys->num_of_images; i++) { ImageHeader* image = new VersalImageHeader(src, (VersalImageHeaderStructure*)subsys->section->Data, IsBootloader, i); image->SetAlignment(it->alignment); image->SetOffset(it->offset); image->SetReserve(it->reserve, it->updateReserveInPh); image->SetLoad(it->load); image->SetStartup(it->startup); image->SetPartitionRevocationId(it->GetRevokeId()); /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetPpkFile(options.bifOptions->GetPPKFileName()); image->SetPskFile(options.bifOptions->GetPSKFileName()); if (it->ppkFile != "" || it->pskFile != "") { image->SetPpkFile(it->ppkFile); image->SetPskFile(it->pskFile); } image->SetSpkFile(options.bifOptions->GetSPKFileName()); image->SetSskFile(options.bifOptions->GetSSKFileName()); if (it->spkFile != "" || it->sskFile != "") { image->SetSpkFile(it->spkFile); image->SetSskFile(it->sskFile); } image->SetSpkSignFile(it->spkSignatureFile); image->SetBhSignFile(options.bifOptions->GetBHSignFileName()); /* Commenting this func for now, check while doing the HSM mode */ ConfigureProcessingStages(image, it); subsys->imgList.push_back(image); /* Image is just temporary, we need to get a pointer back to the copied object and relink */ subsys->imgList.back()->Relink(); ImageHeader* newImage = subsys->imgList.back(); /* For replacing pmcdata */ if (IsBootloader) { image->SetTotalFsblFwSizeIh(importedBh->GetTotalPmcFwLength()); image->SetFsblFwSizeIh(importedBh->GetPmcFwLength()); if (importedBh->GetTotalPmcCdoLength() != 0 && options.bifOptions->GetPmcdataFile() == "") { options.bifOptions->SetTotalpmcdataSize(importedBh->GetTotalPmcCdoLength()); options.bifOptions->pmcdataSize = importedBh->GetPmcCdoLength(); options.bifOptions->pmcDataBuffer = new uint8_t[options.bifOptions->GetTotalpmcdataSize()]; memcpy(options.bifOptions->pmcDataBuffer, newImage->GetPartitionHeaderList().front()->partition->section->Data + importedBh->GetTotalPmcFwLength(), options.bifOptions->totalpmcdataSize); image->SetPmcDataSizeIh(options.bifOptions->pmcdataSize); image->SetTotalPmcDataSizeIh(options.bifOptions->GetTotalpmcdataSize()); } } /* Determine if we need to load in previous RSAAuthentication Information */ for (std::list::iterator partHdr = newImage->GetPartitionHeaderList().begin(); partHdr != newImage->GetPartitionHeaderList().end(); partHdr++) { PartitionHeader* ph = (*partHdr); if (ph->GetAuthCertificateOffset() != 0) { authOnPartitionFound = true; LOG_INFO("Loading AC context for section %s ", ph->section->Name.c_str()); binFile = fopen(it->filename.c_str(), "rb"); if (!binFile) { LOG_ERROR("Cannot read file %s", it->filename.c_str()); } uint8_t* aC = new uint8_t[sizeof(AuthCertificate4096Sha3PaddingStructure)]; memset(aC, 0, sizeof(AuthCertificate4096Sha3PaddingStructure)); if (!(fseek(binFile, ph->GetAuthCertificateOffset(), SEEK_SET))) { size_t result = fread(aC, 1, sizeof(AuthCertificate4096Sha3PaddingStructure), binFile); if (result != sizeof(AuthCertificate4096Sha3PaddingStructure)) { LOG_ERROR("Error parsing Authentication Certificates from PDI file"); } } fclose(binFile); Authentication::Type authtype = Authentication::None; if (((*aC) & 0xF3) == 0x02) { authtype = Authentication::ECDSA; } else if (((*aC) & 0xF3) == 0x11) { authtype = Authentication::RSA; } else if (((*aC) & 0xF3) == 0x22) { authtype = Authentication::ECDSAp521; } VersalAuthenticationContext* auth = new VersalAuthenticationContext((AuthCertificate4096Sha3PaddingStructure*)aC, authtype); // load in previous certificate data AuthenticationCertificate* tempac; tempac = new VersalAuthenticationCertificate(auth); auth->preSigned = true; tempac->fsbl = true; ph->ac.push_back(tempac); newImage->SetAuthContext(auth); } } } offset += sizeof(VersalImageHeaderStructure); if ((getenv("BOOTGEN_MERGE_IMAGES_WITH_SAME_ID") == NULL)) { if ((prev_image_block != current_image_block) || (this_bootimage == true)) { subSysImageList.push_back(subsys); prev_image_block = current_image_block; } else { for (std::list::iterator subSysHdr = subSysImageList.begin(); subSysHdr != subSysImageList.end(); subSysHdr++) { if ((*subSysHdr)->GetSubSystemId() == subsys->GetSubSystemId()) { (*subSysHdr)->imgList.splice((*subSysHdr)->imgList.end(), (subsys->imgList)); } } } } else { subSysImageList.push_back(subsys); } } else { src.seekg(offset); ImageHeader* image = new VersalImageHeader(src, IsBootloader); image->SetAlignment(it->alignment); image->SetOffset(it->offset); image->SetReserve(it->reserve, it->updateReserveInPh); image->SetLoad(it->load); image->SetStartup(it->startup); image->SetPartitionRevocationId(it->GetRevokeId()); /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetPpkFile(options.bifOptions->GetPPKFileName()); image->SetPskFile(options.bifOptions->GetPSKFileName()); if (it->ppkFile != "" || it->pskFile != "") { image->SetPpkFile(it->ppkFile); image->SetPskFile(it->pskFile); } image->SetSpkFile(options.bifOptions->GetSPKFileName()); image->SetSskFile(options.bifOptions->GetSSKFileName()); if (it->spkFile != "" || it->sskFile != "") { image->SetSpkFile(it->spkFile); image->SetSskFile(it->sskFile); } image->SetSpkSignFile(it->spkSignatureFile); image->SetBhSignFile(options.bifOptions->GetBHSignFileName()); ConfigureProcessingStages(image, it); imageList.push_back(image); /* Image is just temporary, we need to get a pointer back to the copied object and relink */ imageList.back()->Relink(); ImageHeader* newImage = imageList.back(); /* For replacing pmcdata */ if (IsBootloader) { image->SetTotalFsblFwSizeIh(importedBh->GetTotalPmcFwLength()); image->SetFsblFwSizeIh(importedBh->GetPmcFwLength()); if (importedBh->GetTotalPmcCdoLength() != 0 && options.bifOptions->GetPmcdataFile() == "") { options.bifOptions->SetTotalpmcdataSize(importedBh->GetTotalPmcCdoLength()); options.bifOptions->pmcdataSize = importedBh->GetPmcCdoLength(); options.bifOptions->pmcDataBuffer = new uint8_t[options.bifOptions->GetTotalpmcdataSize()]; memcpy(options.bifOptions->pmcDataBuffer, newImage->GetPartitionHeaderList().front()->partition->section->Data + importedBh->GetTotalPmcFwLength(), options.bifOptions->totalpmcdataSize); image->SetPmcDataSizeIh(options.bifOptions->pmcdataSize); image->SetTotalPmcDataSizeIh(options.bifOptions->GetTotalpmcdataSize()); } } /* Determine if we need to load in previous RSAAuthentication Information */ for (std::list::iterator partHdr = newImage->GetPartitionHeaderList().begin(); partHdr != newImage->GetPartitionHeaderList().end(); partHdr++) { PartitionHeader* ph = (*partHdr); if(ph->GetAuthCertificateOffset() != 0) { LOG_INFO("Loading AC context for section %s ", ph->section->Name.c_str()); binFile = fopen(it->filename.c_str(), "rb"); if (!binFile) { LOG_ERROR("Cannot read file %s", it->filename.c_str()); } uint8_t* aC = new uint8_t[sizeof(AuthCertificate4096Sha3PaddingStructure)]; memset(aC, 0, sizeof(AuthCertificate4096Sha3PaddingStructure)); if (!(fseek(binFile, ph->GetAuthCertificateOffset(), SEEK_SET))) { size_t result = fread(aC, 1, sizeof(AuthCertificate4096Sha3PaddingStructure), binFile); if (result != sizeof(AuthCertificate4096Sha3PaddingStructure)) { LOG_ERROR("Error parsing Authentication Certificates from PDI file"); } } fclose(binFile); Authentication::Type authtype = Authentication::None; if (((*aC) & 0xF3) == 0x02) { authtype = Authentication::ECDSA; } else if (((*aC) & 0xF3) == 0x11) { authtype = Authentication::RSA; } else if (((*aC) & 0xF3) == 0x22) { authtype = Authentication::ECDSAp521; } VersalAuthenticationContext* auth = new VersalAuthenticationContext((AuthCertificate4096Sha3PaddingStructure*)aC, authtype); AuthenticationCertificate* tempac; tempac = new VersalAuthenticationCertificate(auth); auth->preSigned = true; tempac->fsbl = true; ph->ac.push_back(tempac); newImage->SetAuthContext(auth); } } offset += sizeof(VersalImageHeaderStructure); } this_bootimage = true; } while (imageCount != 0); } /******************************************************************************/ void VersalBootImage::CheckForIhtAttributes(std::string base_file) { if (options.bifOptions->GetPdiId() != 0) { LOG_WARNING("PDI id is taken from base PDI %s, ignoring PDI 'id' specified in the BIF", base_file.c_str()); } if (options.bifOptions->GetParentId()) { LOG_WARNING("Parent id is taken from base PDI %s, ignoring 'parent_id' specified in the BIF", base_file.c_str()); } if (options.bifOptions->GetIdCode()) { LOG_WARNING("ID code is taken from base PDI %s, ignoring 'id_code' specified in the BIF", base_file.c_str()); } if (options.bifOptions->GetExtendedIdCode()) { LOG_WARNING("Extended ID code is taken from base PDI %s, ignoring 'extended_id_code' specified in the BIF", base_file.c_str()); } if (options.bifOptions->GetBypassIdcodeFlag()) { //LOG_WARNING("ID code check is taken from base PDI %s, ignoring 'bypass_idcode_check' specified in the BIF", base_file.c_str()); } if (options.bifOptions->GetBootDevice() != BootDevice::DEFAULT) { LOG_WARNING("Boot Device is taken from base PDI %s, ignoring 'boot_device' specified in the BIF", base_file.c_str()); } } /******************************************************************************/ void VersalBootImage::ValidateSecureAttributes(ImageHeader * image, BifOptions * bifoptions, PartitionBifOptions * partitionBifOptions) { /* Error checks for diff modes */ switch (partitionBifOptions->encryptType) { case Encryption::AES: if (XipMode) { LOG_ERROR("Encryption not supported in XIP Mode"); } if (image->IsBootloader()) { if (bifoptions->GetAuthOnly() == AuthOnly::Enabled) { LOG_ERROR("Cannot encrypt bootloader, when 'auth_only' attribute is used"); } } break; default: break; } switch (partitionBifOptions->authType) { case Authentication::RSA: { if (XipMode) { LOG_ERROR("Authentication not supported in XIP Mode"); } } break; case Authentication::None: default: { if (partitionBifOptions->presignFile != "") { LOG_ERROR("Cannot specify 'presign' attribute when Authentication is not enabled"); } if ((image->IsBootloader()) && (bifoptions->GetAuthOnly() == AuthOnly::Enabled)) { LOG_ERROR("Bootloader must be authenticated if auth_only is used in {boot_config} attribute."); } } break; } if (!bootloaderAuthenticate && bootloaderEncrypt) { switch (bootloaderKeySource) { case KeySource::EfuseBlkKey: case KeySource::EfuseGryKey: case KeySource::EfuseRedKey: case KeySource::EfuseUserBlkKey0: case KeySource::EfuseUserBlkKey1: case KeySource::EfuseUserGryKey0: case KeySource::EfuseUserGryKey1: case KeySource::EfuseUserKey0: case KeySource::EfuseUserKey1: switch (partitionBifOptions->keySrc) { case KeySource::BbramBlkKey: case KeySource::BbramGryKey: case KeySource::BbramRedKey: LOG_ERROR("A Bbram key source cannot be used for other partitions when bootloader is not authenticated and uses a Efuse Key Source."); default: break; } break; case KeySource::BbramBlkKey: case KeySource::BbramGryKey: case KeySource::BbramRedKey: switch (partitionBifOptions->keySrc) { case KeySource::EfuseBlkKey: case KeySource::EfuseGryKey: case KeySource::EfuseRedKey: case KeySource::EfuseUserBlkKey0: case KeySource::EfuseUserBlkKey1: case KeySource::EfuseUserGryKey0: case KeySource::EfuseUserGryKey1: case KeySource::EfuseUserKey0: case KeySource::EfuseUserKey1: LOG_ERROR("An Efuse key source cannot be used for other partitions when bootloader is not authenticated and uses a Bbram Key Source."); default: break; } default: break; } } } /******************************************************************************/ ImageHeader* VersalBootImage::ParsePartitionDataToImage(BifOptions * bifoptions, PartitionBifOptions * partitionBifOptions, ImageBifOptions* imageBifOptions) { static int aie_elf_cnt = 0; static uint8_t slr_boot_cnt = 0; static std::list slrBootPdiInfo; imageBifOptions->slrConfigPartitionIndex++; ImageHeader *image = new VersalImageHeader(partitionBifOptions->filename); image->SetFileList(partitionBifOptions->filelist); image->SetBootloader(partitionBifOptions->bootloader); image->SetAlignment(partitionBifOptions->alignment); image->SetOffset(partitionBifOptions->offset); image->SetReserve(partitionBifOptions->reserve, partitionBifOptions->updateReserveInPh); image->SetLoad(partitionBifOptions->load); image->SetStartup(partitionBifOptions->startup); image->SetBootFlag(partitionBifOptions->boot); image->SetMultibootFlag(partitionBifOptions->multiboot); image->SetNoAutoStartFlag(partitionBifOptions->noautostart); image->SetProtectedFlag(partitionBifOptions->Protected); image->SetStaticFlag(partitionBifOptions->Static); image->SetUserFlag(partitionBifOptions->user); image->SetDestCpu(partitionBifOptions->destCPUType); image->SetExceptionLevel(partitionBifOptions->exceptionLevel); image->SetTrustZone(partitionBifOptions->trustzone); image->SetEarlyHandoff(partitionBifOptions->early_handoff); image->SetHivec(partitionBifOptions->hivec); image->SetPartitionType(partitionBifOptions->partitionType); image->SetPartitionUid(partitionBifOptions->partitionId); image->SetEncryptionKeySrc(partitionBifOptions->keySrc); image->SetPartitionRevocationId(partitionBifOptions->GetRevokeId()); image->SetDpacm(partitionBifOptions->dpaCM); image->SetPufHdLocation(partitionBifOptions->pufHdLoc); image->SetClusterNum(partitionBifOptions->clusterNum); image->SetLockStepFlag(partitionBifOptions->lockstep); image->SetDelayAuthFlag(partitionBifOptions->delayAuth); image->SetTcmBoot(partitionBifOptions->tcmBoot); if ((bifoptions->GetDpaCM() == DpaCM::DpaCMEnable) && (image->IsBootloader())) { image->SetDpacm(DpaCM::DpaCMEnable); } if ((bifoptions->GetPufHdLoc() == PufHdLoc::PUFinBH) && (image->IsBootloader())) { image->SetPufHdLocation(PufHdLoc::PUFinBH); } if (image->GetPufHdLocation() == PufHdLoc::PUFinBH) { bifOptions->SetPufHdinBHFlag(); } /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetPpkFile(bifoptions->GetPPKFileName()); if (partitionBifOptions->ppkFile != "") { image->SetPpkFile(partitionBifOptions->ppkFile); } image->SetPskFile(bifoptions->GetPSKFileName()); if (partitionBifOptions->pskFile != "") { image->SetPskFile(partitionBifOptions->pskFile); } image->SetSpkFile(bifoptions->GetSPKFileName()); if (partitionBifOptions->spkFile != "") { image->SetSpkFile(partitionBifOptions->spkFile); } image->SetSskFile(bifoptions->GetSSKFileName()); if (partitionBifOptions->sskFile != "") { image->SetSskFile(partitionBifOptions->sskFile); } image->SetSpkSignFile(bifoptions->GetSPKSignFileName()); if (partitionBifOptions->spkSignatureFile != "") { image->SetSpkSignFile(partitionBifOptions->spkSignatureFile); } /* Local AES key file is mandatory when the partition is encrypted */ if (partitionBifOptions->aesKeyFile != "") { image->SetAesKeyFile(partitionBifOptions->aesKeyFile); } else if ((options.GetEncryptionKeyFile() != "") && (image->IsBootloader())) { LOG_WARNING("This usage of 'aeskeyfile' is deprecated. \n Please refer 'bootgen -arch versal -bif_help aeskeyfile' for more info."); image->SetAesKeyFile(options.GetEncryptionKeyFile()); } /* If no key file found in partition specific attributes, generate aeskeyfile with partition_name.nky */ else { std::string name = StringUtils::RemoveExtension(image->GetName()) + ".nky"; image->SetAesKeyFile(name); } if (image->IsBootloader()) { if (partitionBifOptions->keySrc != KeySource::None) { options.SetEncryptedKeySource(partitionBifOptions->keySrc); } if (bootloaderFound == true) { LOG_ERROR("BIF attribute error !!!\n\t\tA bootimage cannot have more than one bootloader."); } bootloaderFound = true; fsblFilename = partitionBifOptions->filename; options.fsblFilename = partitionBifOptions->filename; if ((bifOptions->aHwrot == true) && (partitionBifOptions->authType == Authentication::None)) { LOG_ERROR("Bootloader must be authenticated when 'a_hwrot' is enabled"); } if ((bifOptions->sHwrot == true) && (partitionBifOptions->encryptType == Encryption::None)) { LOG_ERROR("Bootloader must be encrypted with 'keysrc=efuse_blk_key', when 's_hwrot' is enabled"); } if((bifOptions->sHwrot == true) && (partitionBifOptions->keySrc != KeySource::EfuseBlkKey)) { LOG_ERROR("Bootloader must be encrypted with 'keysrc=efuse_blk_key', when 's_hwrot' is enabled"); } if (partitionBifOptions->authType == Authentication::ECDSAp521) { LOG_ERROR("BIF attribute error !!!\n\t\t 'ecdsa-p521' not supported for bootloader partition"); } if (partitionBifOptions->hivec) { LOG_ERROR("BIF attribute error !!!\n\t\t'hivec' not supported for bootloader partition"); } } ConfigureEncryptionBlocks(image, partitionBifOptions); ConfigureProcessingStages(image, partitionBifOptions); ValidateSecureAttributes(image, bifoptions, partitionBifOptions); if ((partitionBifOptions->partitionType == PartitionType::SLR_BOOT) || (partitionBifOptions->partitionType == PartitionType::SLR_CONFIG)) { /* SSIT devices */ SlrPdiInfo* slrPdi = new SlrPdiInfo; slrPdi->file = partitionBifOptions->filename; std::ifstream s(slrPdi->file.c_str()); if (!s) { LOG_ERROR("Cannot read file - %s ", slrPdi->file.c_str()); } slrPdi->index = (SlrId::Type) partitionBifOptions->slrNum; if (partitionBifOptions->partitionType == PartitionType::SLR_BOOT) { slr_boot_cnt++; if (partitionBifOptions->slrNum == 0xFF) { slrPdi->index = (SlrId::Type) slr_boot_cnt; } slrPdi->type = SlrPdiType::BOOT; slrBootPdiInfo.push_back(slrPdi); if (slr_boot_cnt == bifoptions->slrBootCnt) { image->SetSlrBootPartitions(slrBootPdiInfo); image->SetName("SSIT Boot Partition"); image->SetSlrPartition(true); imageList.push_back(image); } } else { slrPdi->type = SlrPdiType::CONFIG; slrPdi->index = (SlrId::Type) partitionBifOptions->slrNum; if (partitionBifOptions->slrNum == 0xFF) { slrPdi->index = (SlrId::Type) imageBifOptions->slrConfigPartitionIndex; if (slrPdi->index == imageBifOptions->slrConfigCnt) { slrPdi->index = SlrId::MASTER; } } else { slrPdi->index = (partitionBifOptions->slrNum == 0x0) ? (SlrId::MASTER) : ((SlrId::Type) partitionBifOptions->slrNum); } imageBifOptions->slrConfigPdiInfo.push_back(slrPdi); if (imageBifOptions->slrConfigPartitionIndex == imageBifOptions->slrConfigCnt) { image->SetSlrConfigPartitions(imageBifOptions->slrConfigPdiInfo); image->SetName("SSIT Config Partition"); image->SetSlrPartition(true); imageList.push_back(image); } } } else if ((convertAieElfToCdo == true) && (partitionBifOptions->destCPUType == DestinationCPU::AIE)) { /* ELF to CDO flow - All ELFs are converted to one CDO Push all the AIE elfs to a list */ aie_elf_cnt++; bifoptions->aie_elfs.push_back(partitionBifOptions->filename); if (aie_elf_cnt == 1) { imageList.push_back(image); } else { return NULL; } } else if (partitionBifOptions->partitionType == PartitionType::IMAGE_STORE_PDI) { ImageStorePdiInfo* imageStorePdi = new ImageStorePdiInfo; imageStorePdi->file = partitionBifOptions->filename; std::ifstream s(imageStorePdi->file.c_str()); if (!s) { LOG_ERROR("Cannot read file - %s ", imageStorePdi->file.c_str()); } imageStorePdi->id = partitionBifOptions->imageStoreId; image->SetWriteImageStorePartitions(imageStorePdi); imageList.push_back(image); } else { imageList.push_back(image); } bool break_outer_loop = false; for (std::list::iterator subSysHdr = subSysImageList.begin(); subSysHdr != subSysImageList.end(); subSysHdr++) { for (std::list::iterator partName = (*subSysHdr)->partitionNameList.begin(); partName != (*subSysHdr)->partitionNameList.end(); partName++) { image->SetMemCopyAddress((*subSysHdr)->GetSubSysMemCopyAddress()); image->SetDelayLoadHandOffFlags((*subSysHdr)->GetDelayLoadMode(), (*subSysHdr)->GetDelayHandoffMode()); std::string part(*partName); if (!image->GetFilename().compare(part)) { (*subSysHdr)->imgList.push_back(image); break_outer_loop = true; break; } } if (break_outer_loop) { break; } } if (image->GetTcmBootFlag() == true && image->GetDestCpu() != DestinationCPU::R5_0 && image->GetDestCpu() != DestinationCPU::R5_1 && image->GetDestCpu() != DestinationCPU::R5_lockstep) { LOG_ERROR("BIF attribute error !!!\n\t 'tcmboot' is supported only with R5 cpu"); } return image; } /******************************************************************************/ void VersalBootImage::OutputOptionalSecureDebugImage() { std::string secureDebugImageFile = options.GetSecureDebugImageFile(); uint32_t authJtagImageSize = sizeof(AuthenticatedJtagImageStructure); uint8_t* writedata = new uint8_t[authJtagImageSize]; memset(writedata, 0, authJtagImageSize); if (options.GetSecureDebugAuthType() != Authentication::None) { VersalAuthenticationContext* authCtx = new VersalAuthenticationContext(this->currentAuthCtx, options.GetSecureDebugAuthType()); if (authCtx) { authCtx->hashType = authHash; authCtx->hash = hash; authCtx->CreateAuthJtagImage(writedata, bifOptions->authJtagInfo); } std::ofstream ofs; ofs.open(secureDebugImageFile.c_str(), std::ios::binary); if (!ofs) { LOG_ERROR("Cannot write output to file : %s", secureDebugImageFile.c_str()); } ofs.write((const char*)writedata, authJtagImageSize); ofs.close(); LOG_TRACE("Authenticated Jtag Image : '%s' generated.", secureDebugImageFile.c_str()); } delete[] writedata; } /******************************************************************************/ void VersalBootImage::ConfigureEncryptionBlocks(ImageHeader * image, PartitionBifOptions * partitionBifOptions) { if (partitionBifOptions->encryptType == Encryption::AES) { std::vector encrBlocks = partitionBifOptions->GetEncryptionBlocks(); uint32_t defaultEncrBlockSize = partitionBifOptions->GetDefaultEncryptionBlockSize(); image->SetDefaultEncrBlockSize(defaultEncrBlockSize); if (image->IsBootloader() && !(options.IsVersalNetSeries())) { for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { image->InsertEncrBlocksList(encrBlocks[itr]); } } else { Binary::Length_t encrBlocksSize = 0; Binary::Length_t encrOverhead = 0; Binary::Length_t secureChunkSize = GetSecureChunkSize(image->IsBootloader()); if (partitionBifOptions->authType == Authentication::None && !partitionBifOptions->delayAuth) { secureChunkSize += SHA3_LENGTH_BYTES; } /* Creating encryption blocks for 64KB from user specified blocks. Consider encryption overhead as well */ for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* Push all the user blocks till the sum of user specified blocks and overhead is less than 64KB. */ if ((encrBlocksSize + encrOverhead) < secureChunkSize) { image->InsertEncrBlocksList(encrBlocks[itr]); } /* When the sum of user specified blocks and overhead reaches 64KB, push that block and break. */ else if ((encrBlocksSize + encrOverhead) == secureChunkSize) { image->InsertEncrBlocksList(encrBlocks[itr]); break; } /* If the sum of user specified blocks and overhead exceeds 64KB, truncate that block, .push and break.*/ else { Binary::Length_t lastBlock = secureChunkSize - (encrBlocksSize - encrBlocks[itr] + encrOverhead); encrBlocksSize += (lastBlock - encrBlocks[itr]); image->InsertEncrBlocksList(lastBlock); LOG_WARNING("The last encryption block size is truncated to %d to fit into the secure chunk of 32KB.", lastBlock); break; } } /* If the user specified blocks, does not make a chunk of 64KB, then calculate the rest and push. */ if (encrBlocksSize + encrOverhead < secureChunkSize) { /* If a default size(using (*)) is mentioned, */ if (defaultEncrBlockSize != 0) { encrBlocksSize += defaultEncrBlockSize; encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* then push the default size untill the sum of encr blocks and overhead is < or = 64KB.*/ while (encrBlocksSize + encrOverhead < secureChunkSize) { image->InsertEncrBlocksList(defaultEncrBlockSize); encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); encrBlocksSize += defaultEncrBlockSize; } Binary::Length_t lastBlock = defaultEncrBlockSize; /* When the sum of encr blocks and overhead goes beyond 64KB, truncate the default size and push.*/ if ((encrBlocksSize + encrOverhead) > secureChunkSize) { if (secureChunkSize > (encrBlocksSize + encrOverhead - defaultEncrBlockSize)) { lastBlock = secureChunkSize - (encrBlocksSize + encrOverhead - defaultEncrBlockSize); encrBlocksSize += (lastBlock - defaultEncrBlockSize); LOG_WARNING("The last encryption block size is truncated to %d to fit into the secure chunk of 32KB.", lastBlock); } else { LOG_ERROR("The keyrolling block size '%d' cannot fit into the secure chunk of 32KB. Please choose another block size.\n For details, refer to the section 'Design Advisories for Bootgen' from UG1283.", defaultEncrBlockSize); } } image->InsertEncrBlocksList(lastBlock); } /* If a default size(using (*)) is not mentioned, then calculate the last block that makes sum of encr blocks and overhead = 64KB and push.*/ else { encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); image->InsertEncrBlocksList(secureChunkSize - (encrBlocksSize + encrOverhead)); } } } if (image->GetEncrBlocksList().size() != 0) { static bool warningGiven = false; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { if (encrBlocks[itr] > 1024 * 1024 * ENCR_BLOCK_IN_BYTES) { if (!warningGiven) { LOG_WARNING("partition - %s, block - %d", partitionBifOptions->filename.c_str(), encrBlocks[itr]); LOG_WARNING("The key rolling rate associated with the partition - %s exceeds 1M traces per key.\n\t If you are using a device with the AES masking DPA countermeasure enabled,\n\t you should confirm that the key rolling rate is sufficient.\n\t For more details on key rolling rates, please see the Versal Security Users Manual(UG1508).", partitionBifOptions->filename.c_str()); warningGiven = true; } } } } } } /******************************************************************************/ void VersalBootImage::SetPmcdataFile(const std::string& filename) { options.bifOptions->SetPmcdataFile(filename); } /******************************************************************************/ void VersalBootImage::ConfigureProcessingStages(ImageHeader* image, PartitionBifOptions* partitionbifoptions) { ConfigureEncryptionContext(image, partitionbifoptions->encryptType); ConfigureAuthenticationContext(image, partitionbifoptions->authType, partitionbifoptions); ConfigureChecksumContext(image, partitionbifoptions->checksumType); image->SetPartOwner(partitionbifoptions->ownerType); } /******************************************************************************/ void VersalBootImage::Add(BifOptions* bifoptions) { uint8_t slr_boot_cnt = 0; // Add 'LOG_WARNING("A bootimage cannot be generated on the go, with '-generate_keys'.\n However, the requested keys will be generated.");' if (bifoptions->GetAESKeyFileName() != "") { LOG_WARNING("This usage of 'aeskeyfile' is deprecated for VERSAL.. \n Please refer 'bootgen -arch versal -bif_help aeskeyfile' for more info."); currentEncryptCtx->SetAesFileName(bifoptions->GetAESKeyFileName()); options.SetEncryptionKeyFile(bifoptions->GetAESKeyFileName()); } if (bifOptions->GetBhRsa() == BhRsa::BhRsaEnable && bifOptions->aHwrot == true) { LOG_ERROR("BIF attribute error !!!\n\t\t 'bh_auth_enable' and 'a_hwrot' cannot be used together"); } currentEncryptCtx->SetMetalKeyFile(bifoptions->GetFamilyKeyFileName()); currentAuthCtx->SetSpkIdentification(bifoptions->GetSpkId()); currentAuthCtx->SetHeaderAuthentication(bifoptions->GetHeaderAC()); if (options.GetAuthKeyGeneration() == GenAuthKeys::None) { if (bifoptions->GetPPKFileName() != "") { currentAuthCtx->SetPPKeyFile(bifoptions->GetPPKFileName()); } if (bifoptions->GetPSKFileName() != "") { currentAuthCtx->SetPSKeyFile(bifoptions->GetPSKFileName()); } if (bifoptions->GetSPKFileName() != "") { currentAuthCtx->SetSPKeyFile(bifoptions->GetSPKFileName()); VersalAuthenticationContext* authCtx = NULL; if (currentAuthCtx) { std::string filename = bifoptions->GetSPKFileName(); FILE* f; f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } RSA* rsa = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); fclose(f); f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } EC_KEY *eckeyLocal = PEM_read_EC_PUBKEY(f, NULL, NULL, NULL); fclose(f); if (rsa != NULL) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::RSA); } else if(eckeyLocal != NULL) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::ECDSA); } } if (options.DoGenerateHashes()) { authCtx->hash = hash; authCtx->spkIdentification = bifOptions->GetRevokeId(); LOG_INFO("Generating SPK Hash File"); authCtx->GenerateSPKHashFile(bifoptions->GetSPKFileName(), hash); } if (authCtx != NULL) { delete authCtx; } } if (bifoptions->GetSSKFileName() != "") { currentAuthCtx->SetSSKeyFile(bifoptions->GetSSKFileName()); } } if (bifoptions->GetSPKSignFileName() != "") { LOG_TRACE("Parsing SPK Signature File"); currentAuthCtx->SetSPKSignatureFile(bifoptions->GetSPKSignFileName()); } if (bifoptions->GetBHSignFileName() != "") { LOG_TRACE("Parsing BH Signature File"); currentAuthCtx->SetBHSignatureFile(bifoptions->GetBHSignFileName()); } currentEncryptCtx->SetBHKekIVFile(bifoptions->GetBHKekIVFile()); currentEncryptCtx->SetBbramKekIVFile(bifoptions->GetBbramKekIVFile()); currentEncryptCtx->SetEfuseKekIVFile(bifoptions->GetEfuseKekIVFile()); currentEncryptCtx->SetEfuseUserKek0IVFile(bifoptions->GetEfuseUserKek0IVFile()); currentEncryptCtx->SetEfuseUserKek1IVFile(bifoptions->GetEfuseUserKek1IVFile()); XipMode = bifoptions->GetXipMode(); /* Overlay CDO */ { std::string overlayFile = options.GetOverlayCDOFileName(); if (overlayFile != "") { CdoSequence * seq = cdoseq_load_cdo((char *)(overlayFile.c_str())); if (seq == NULL) { LOG_ERROR("Error parsing overlay CDO file"); } overlayCDO = cdooverlay_open(seq); if (overlayCDO == NULL) { LOG_ERROR("Error parsing overlay CDO file"); } } } LOG_INFO("Parsing Partition Data to Image"); if (bifoptions->imageBifOptionList.size() == 0) { if (bifoptions->partitionBifOptionList.size() != 0) { LOG_ERROR("Legacy BIF format detected. Please update to Versal BIF format. Refer UG1283 for more details."); } for (std::list::iterator itr = bifoptions->partitionBifOptionList.begin(); itr != bifoptions->partitionBifOptionList.end(); itr++) { if ((*itr)->bootImage) { ParseBootImage((*itr)); } else if ((*itr)->pmcData) { SetPmcdataFile((*itr)->filename); if ((*itr)->load.Value() != 0) { bifoptions->pmcCdoLoadAddress = (*itr)->load.Value(); } if ((*itr)->aesKeyFile != "") { bifoptions->SetPmcDataAesFile((*itr)->aesKeyFile); } //If no key file found in partition specific attributes - Generate aeskeyfile with partition_name.nky else { bifoptions->SetPmcDataAesFile(StringUtils::RemoveExtension(StringUtils::BaseName((*itr)->filename)) + ".nky"); } } else { ParsePartitionDataToImage(bifOptions, *itr, NULL); } } } else { for (std::list::iterator imgitr = bifoptions->imageBifOptionList.begin(); imgitr != bifoptions->imageBifOptionList.end(); imgitr++) { uint8_t slr_cfg_cnt = 0; SubSysImageHeader *subSysImage = new SubSysImageHeader(*imgitr); bool bootimage_partition = false; current_image_block++; bool break_outer_loop = false; for (std::list::iterator partitr = (*imgitr)->partitionBifOptionsList.begin(); partitr != (*imgitr)->partitionBifOptionsList.end(); partitr++) { if ((*partitr)->bootImage) { ParseBootImage((*partitr)); bootimage_partition = true; } else if ((*partitr)->pmcData) { SetPmcdataFile((*partitr)->filename); if ((*partitr)->load.Value() != 0) { bifoptions->pmcCdoLoadAddress = (*partitr)->load.Value(); } if ((*partitr)->aesKeyFile != "") { bifoptions->SetPmcDataAesFile((*partitr)->aesKeyFile); } else { //If no key file found in partition specific attributes - Generate aeskeyfile with partition_name.nky bifoptions->SetPmcDataAesFile(StringUtils::RemoveExtension(StringUtils::BaseName((*partitr)->filename)) + ".nky"); } } else { ImageHeader* img = ParsePartitionDataToImage(bifOptions, *partitr, *imgitr); if (img != NULL) { img->SetName(subSysImage->GetSubSystemName()); /* PLM and PSM should not have 0x1c000000 as default IDs, otherwise they will get merged with default subsystem As they should be replaced in their respective subsystems, they should have some non-common id. */ if ((bootimage_partition == true) && (subSysImage->GetSubSystemId() == 0x1c000000) && (img->IsBootloader() || img->GetDestCpu() == DestinationCPU::PMU)) { subSysImage->SetSubSystemId(0x0); } if ((getenv("BOOTGEN_MERGE_IMAGES_WITH_SAME_ID") == NULL)) { if (bootimage_partition == true) { for (std::list::iterator ssitr = subSysImageList.begin(); ssitr != subSysImageList.end(); ssitr++) { if (((*ssitr)->GetSubSystemId() == subSysImage->GetSubSystemId()) && !(img->IsBootloader() || img->GetDestCpu() == DestinationCPU::PMU)) { (*ssitr)->imgList.push_back(img); break_outer_loop = true; } } } } if (subSysImage->GetDelayHandoffMode() || subSysImage->GetDelayLoadMode()) { if (img->IsBootloader()) { LOG_ERROR("BIF attributes 'delay_load'/'delay_handoff' not supported for PMC subsystem"); } if (img->GetDestCpu() == DestinationCPU::PMU) { //LOG_WARNING("delay_load/delay_handoff enabled for %s subsystem, this may cause some issues while using PS", subSysImage->GetSubSystemName().c_str()); } if ((StringUtils::EndsWith(img->GetFilename(), ".npi")) || (StringUtils::EndsWith(img->GetFilename(), ".rnpi"))) { //LOG_WARNING("delay_load/delay_handoff enabled for %s subsystem, this may cause some issues if not handled properly", subSysImage->GetSubSystemName().c_str()); } } if (((*partitr)->partitionType == PartitionType::SLR_BOOT) || ((*partitr)->partitionType == PartitionType::SLR_CONFIG)) { if ((*partitr)->partitionType == PartitionType::SLR_BOOT) { if (++slr_boot_cnt == bifoptions->slrBootCnt) { subSysImage->imgList.push_back(img); } } if ((*partitr)->partitionType == PartitionType::SLR_CONFIG) { if (++slr_cfg_cnt == (*imgitr)->slrConfigCnt) { subSysImage->imgList.push_back(img); } } } else { if (!break_outer_loop) subSysImage->imgList.push_back(img); } } } } /* Add to subsys list only if it the partition type is not bootimage. Because bootimage will have its own subsystems */ if ((!bootimage_partition) || (subSysImage->imgList.size() != 0)) { subSysImageList.push_back(subSysImage); } } } } /******************************************************************************/ void VersalBootImage::ReplaceImages(void) { std::list::iterator it1, it2, PrevImgloc; std::list::iterator subsysIt; bool replaceImages = false; bool replacePSMImages = false; ImageHeader* img1 = NULL; ImageHeader* PSMimg = NULL; uint32_t tempindx = 0; // Check for bootloader, if there are more bootloaders in the bif, other than the one in bootimage, replace it. uint8_t bootloaderCnt = 0; uint8_t PSMImageCnt = 0; for (std::list::iterator subsys = subSysImageList.begin(); subsys != subSysImageList.end(); subsys++) { for (std::list::iterator img = (*subsys)->imgList.begin(); img != (*subsys)->imgList.end(); img++) { if ((*img)->GetDestCpu() == DestinationCPU::PMU) { if (PSMImageCnt == 0) { it2 = img; } PSMImageCnt++; } if ((PSMImageCnt > 1) && (replacePSMImages == false)) { replacePSMImages = true; PSMimg = *img; subsysIt = subsys; } if ((*img)->IsBootloader()) { if (bootloaderCnt == 0) { it1 = img; } bootloaderCnt++; bootloaderFound = true; } if ((bootloaderCnt > 1) && (replaceImages == false)) { replaceImages = true; img1 = (*img); subsysIt = subsys; } } } if ((replacePSMImages == true) || (replaceImages == true)) { subSysImageList.erase(subsysIt); } bootloaderCnt = 0; if (replaceImages == true) { for (std::list::iterator subsys = subSysImageList.begin(); subsys != subSysImageList.end(); subsys++) { for (std::list::iterator img = (*subsys)->imgList.begin(); img != (*subsys)->imgList.end(); img++) { tempindx++; if ((*img)->IsBootloader()) { (*subsys)->imgList.erase(it1); (*subsys)->imgList.push_front((img1)); break; } } break; } } tempindx = 0; PSMImageCnt = 0; if (replacePSMImages == true) { for (std::list::iterator subsys = subSysImageList.begin(); subsys != subSysImageList.end(); subsys++) { for (std::list::iterator img = (*subsys)->imgList.begin(); img != (*subsys)->imgList.end(); img++) { tempindx++; if ((*img)->GetDestCpu() == DestinationCPU::PMU) { (*subsys)->imgList.erase(it2); (*subsys)->imgList.push_back(PSMimg); break; } } } } } /******************************************************************************/ void VersalBootImage::ReplaceImagesNoSubSys(void) { std::list oldList = imageList; std::list newList; std::list::iterator it1, it2, PrevImgloc; it1 = it2 = imageList.begin(); bool replaceImages = false; bool replacePSMImages = false; ImageHeader* tempBl = NULL; uint32_t tempindx = 0; ImageHeader* PSMimg = NULL; // Check for bootloader, if there are more bootloaders in the bif, other than the one in bootimage, replace it. uint8_t bootloaderCnt = 0; uint8_t PSMImageCnt = 0; for (std::list::iterator img = imageList.begin(); img != imageList.end(); img++) { if ((*img)->GetDestCpu() == DestinationCPU::PMU) { PSMImageCnt++; } if (PSMImageCnt > 1) { replacePSMImages = true; } if ((*img)->IsBootloader()) { bootloaderCnt++; bootloaderFound = true; } if (bootloaderCnt > 1) { replaceImages = true; } } bootloaderCnt = 0; if (replaceImages == true) { for (std::list::iterator img = imageList.begin(); img != imageList.end(); img++) { tempindx++; if ((*img)->IsBootloader()) { bootloaderCnt++; if (bootloaderCnt == 2) { tempBl = *img; imageList.remove(*img); break; } } } imageList.erase(it1); if(tempBl != NULL) { imageList.push_front(tempBl); } } tempindx = 0; PSMImageCnt = 0; if (replacePSMImages == true) { for (std::list::iterator img = imageList.begin(); img != imageList.end(); img++) { tempindx++; if ((*img)->GetDestCpu() == DestinationCPU::PMU) { PSMImageCnt++; if (PSMImageCnt == 2) { PSMimg = *img; imageList.remove(*img); break; } else { PrevImgloc = img; } } } imageList.insert(PrevImgloc, PSMimg); imageList.erase(PrevImgloc); } } /******************************************************************************/ void VersalBootImage::OutputOptionalEfuseHash() { std::string hashFile = options.GetEfuseHashFileName(); std::string primaryKeyFile; if (hashFile != "") { if (bifOptions->GetPPKFileName() != "") { if (currentAuthCtx) { primaryKeyFile = bifOptions->GetPPKFileName(); std::string filename = primaryKeyFile; FILE* f = NULL; f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } RSA* rsa = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); fclose(f); f = fopen(filename.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", filename.c_str()); } EC_KEY *eckeyLocal = PEM_read_EC_PUBKEY(f, NULL, NULL, NULL); fclose(f); VersalAuthenticationContext* authCtx = NULL; if (rsa != NULL) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::RSA); } else if (eckeyLocal != NULL) { FILE* f = NULL; f = fopen(primaryKeyFile.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", primaryKeyFile.c_str()); } EC_KEY *eckeyLocal = PEM_read_EC_PUBKEY(f, NULL, NULL, NULL); const EC_GROUP* ecgroup = EC_KEY_get0_group(eckeyLocal); int ecCurveNID = EC_GROUP_get_curve_name(ecgroup); fclose(f); if (ecCurveNID == NID_secp384r1) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::ECDSA); } else if (ecCurveNID == NID_secp521r1) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::ECDSAp521); } else { LOG_ERROR("Unsupported ECDSA curve read from key file : %s\n Supported ECDSA curves: P384, P521", primaryKeyFile.c_str()); } } else { LOG_ERROR("Cannot read the public key file : %s", filename.c_str()); } authCtx->hash = hash; authCtx->GeneratePPKHash(hashFile); } } else if (bifOptions->GetPSKFileName() != "") { if (currentAuthCtx) { primaryKeyFile = bifOptions->GetPSKFileName(); std::ifstream File(primaryKeyFile.c_str()); std::string word; File >> word; File >> word; VersalAuthenticationContext* authCtx = NULL; if (word == "EC") { FILE* f = NULL; f = fopen(primaryKeyFile.c_str(), "r"); if (f == NULL) { LOG_ERROR("Cannot open key %s", primaryKeyFile.c_str()); } EC_KEY *eckeyLocal = PEM_read_ECPrivateKey(f, NULL, NULL, NULL); const EC_GROUP* ecgroup = EC_KEY_get0_group(eckeyLocal); int ecCurveNID = EC_GROUP_get_curve_name(ecgroup); fclose(f); if (ecCurveNID == NID_secp384r1) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::ECDSA); } else if (ecCurveNID == NID_secp521r1) { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::ECDSAp521); } else { LOG_ERROR("Unsupported ECDSA curve read from key file : %s\n Supported ECDSA curves: P384, P521", primaryKeyFile.c_str()); } } else { authCtx = new VersalAuthenticationContext(currentAuthCtx, Authentication::RSA); } authCtx->hash = hash; authCtx->GeneratePPKHash(hashFile); } } else { LOG_ERROR("Cannot read PPK/PSK. PPK/PSK is mandatory to generate PPK hash bits, using '-efuseppkbits'."); } } } /******************************************************************************/ void VersalBootImage::AppendImagesInSubsystems(void) { std::list eraseSubSysImageList; for (std::list::iterator subsys1 = subSysImageList.begin(); subsys1 != subSysImageList.end(); subsys1++) { for (std::list::iterator subsys2 = subSysImageList.begin(); subsys2 != subSysImageList.end(); subsys2++) { if ((*subsys1) != (*subsys2)) { if (((*subsys2)->GetSubSystemId() == (*subsys1)->GetSubSystemId()) && (*subsys1)->GetSubSystemId() != 0 && (*subsys1)->GetSubSystemId() != 0x1c000001) { (*subsys1)->imgList.insert((*subsys1)->imgList.end(), (*subsys2)->imgList.begin(), (*subsys2)->imgList.end()); eraseSubSysImageList.push_back(*subsys2); } } } for (std::list::iterator erasesubsys = eraseSubSysImageList.begin(); erasesubsys != eraseSubSysImageList.end(); erasesubsys++) { subSysImageList.remove(*erasesubsys); } } } /******************************************************************************/ void VersalBootImage::BuildAndLink(Binary* cache) { if (imageList.size() == 0 && options.GetSecureDebugAuthType() == Authentication::None) { LOG_WARNING("No partition images given"); } if (subSysImageList.size() == 0) { if (createSubSystemPdis == false) { /* Create old style image headers - for local testing */ /* No need to do anything here */ //LOG_WARNING("BOOTGEN_SUBSYSTEM_PDI is not set, PDI has one image header for each input partition file"); } else { ImageBifOptions *imgOptions = new ImageBifOptions(); /* If Subsystems are not specified in BIF - create one image header for PLM and other image header for subsytem and add all partitions to it */ imgOptions->SetImageName("default_subsys"); SubSysImageHeader* sub_sys_image = new SubSysImageHeader(imgOptions); for (std::list::iterator image = imageList.begin(); image != imageList.end(); image++) { if ((*image)->IsBootloader()) { imgOptions->SetImageName("pmc_subsys"); SubSysImageHeader* plm_header = new SubSysImageHeader(imgOptions); plm_header->imgList.push_back((*image)); plm_header->SetSubSystemName("pmc_subsys"); plm_header->SetSubSystemId(0x1c000001); subSysImageList.push_back(plm_header); } else { sub_sys_image->imgList.push_back((*image)); } } if (sub_sys_image->imgList.size() != 0) { sub_sys_image->SetSubSystemName("default_subsys"); sub_sys_image->SetSubSystemId(0x1c000000); subSysImageList.push_back(sub_sys_image); LOG_INFO("BOOTGEN_SUBSYSTEM_PDI is set, but no subsystems are specified, all partitions are grouped into one default subsystem"); } } } DetermineEncryptionDefaults(); partitionHeaderList.clear(); if (createSubSystemPdis == true) { ReplaceImages(); } else { ReplaceImagesNoSubSys(); } /* Build stage */ /* all static fields within the header tables are populated here */ bootHeader->Build(*this, *cache); imageHeaderTable->Build(*this, *cache); partitionHeaderTable->Build(*this, *cache); checksumTable->Build(*this, *cache); partitionHeaderTable->BuildPartitions(*this, *cache); LOG_INFO("After build "); LOG_DUMP_IMAGE(*cache); /* Stack and alignment stage */ /* Once the header tables are created, stack all the tables and do the necessary alignment */ cache->StackAndAlign(options); LOG_INFO("After align "); LOG_DUMP_IMAGE(*cache); PrintPartitionInformation(); /* Link stage - fields which depend on partitions are populated here */ bootHeader->Link(*this); imageHeaderTable->Link(*this); if (options.IsAuthOptimizationEnabled()) { partitionHeaderTable->LinkPartitions(*this); partitionHeaderTable->Link(*this); } else { partitionHeaderTable->Link(*this); partitionHeaderTable->LinkPartitions(*this); } checksumTable->Link(*this); LOG_INFO("After Link "); LOG_DUMP_IMAGE(*cache); } /******************************************************************************/ uint64_t VersalBootImage::GetSecureChunkSize(bool isBootloader) { if (options.IsVersalNetSeries() && isBootloader == true) { return (SECURE_16K_CHUNK - SHA3_LENGTH_BYTES); } else { return (SECURE_32K_CHUNK - SHA3_LENGTH_BYTES); } } xilinx-bootgen-2024.2/bootimage-versal.h000077500000000000000000000061271475706442400202100ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTIMAGE_VERSAL_H_ #define _BOOTIMAGE_VERSAL_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "bootheader-versal.h" #include "encryption-versal.h" #include "binary-versal.h" #define ENCR_BLOCK_IN_BYTES 16 //= 128 bits /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalBootImage : public BootImage { public: VersalBootImage(Options& options, uint8_t index); ~VersalBootImage(); void BuildAndLink(Binary* cache); void Add(BifOptions* bifoptions); void ReplaceImages(void); void ReplaceImagesNoSubSys(void); void AppendImagesInSubsystems(void); void OutputOptionalEfuseHash(); void OutputPartitionFiles(Options& options, Binary& cache) {}; void GenerateAuthenticationKeys(void) {}; void ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType); void ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions); void ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType); void ConfigureProcessingStages(ImageHeader* image, PartitionBifOptions* partitionbifoptions); void CheckForIhtAttributes(std::string base_file); void ParseBootImage(PartitionBifOptions * it); void ValidateSecureAttributes(ImageHeader * image, BifOptions* bifoptions, PartitionBifOptions* partitionBifOptions); ImageHeader* ParsePartitionDataToImage(BifOptions* bifoptions, PartitionBifOptions* partitionIterator, ImageBifOptions* ssIterator); void OutputOptionalSecureDebugImage(); void ConfigureEncryptionBlocks(ImageHeader * image, PartitionBifOptions* partitionBifOptions); void SetPmcdataFile(const std::string & filename); uint64_t GetSecureChunkSize(bool isBootloader); uint32_t current_image_block; uint32_t prev_image_block; }; #endif xilinx-bootgen-2024.2/bootimage-zynq.cpp000077500000000000000000000546211475706442400202520ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage-zynq.h" #include "bifoptions.h" #include "encryption-zynq.h" #include "authentication-zynq.h" /* Forward Class Declaration */ class ZynqEncryptionContext; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqBootImage::ZynqBootImage(Options& options, uint8_t index) : BootImage(options, index) { options.SetPadHeaderTable(true); bootHeader = new ZynqBootHeader(); imageHeaderTable = new ZynqImageHeaderTable(); partitionHeaderTable = new PartitionHeaderTable(); currentEncryptCtx = new ZynqEncryptionContext(); currentAuthCtx = new ZynqAuthenticationContext(); SetLegacyEncryptionFlag(true); partitionOutput = new ZynqPartitionOutput(); hash = new HashSha2(); currentAuthCtx->hash = hash; partitionHeaderList.clear(); partitionHeaderTable->firstSection = NULL; importedBh = NULL; }; /******************************************************************************/ void ZynqBootImage::ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType) { switch (encryptType) { case Encryption::AES: if (image->GetAesKeyFile() != "") { std::ifstream keyFile(image->GetAesKeyFile()); if (!keyFile.good()) { image->SetAesKeyFileGeneration(true); } } image->SetEncryptContext(new ZynqEncryptionContext(this->currentEncryptCtx)); break; case Encryption::None: image->ValidateEncryptionAttributes(*this); image->SetEncryptContext(new NoneEncryptionContext()); break; default: image->SetEncryptContext(NULL); break; } } /******************************************************************************/ void ZynqBootImage::ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions) { std::string spkSignFile = options.GetSpkSigFileName(); switch (partitionbifoptions->authType) { case Authentication::RSA: { image->SetAuthenticationType(Authentication::RSA); options.bifOptions->SetHeaderAC(true); this->currentAuthCtx->hashType = GetAuthHashAlgo(); if (image->GetSpkFile() != "") { currentAuthCtx->spkFile = image->GetSpkFile(); } if (image->GetSskFile() != "") { currentAuthCtx->sskFile = image->GetSskFile(); } if (image->GetSpkSignFile() != "") { currentAuthCtx->spkSignFile = image->GetSpkSignFile(); } if (image->GetBhSignFile() != "") { currentAuthCtx->bhSignFile = image->GetBhSignFile(); } currentAuthCtx->spkIdentification = image->GetSpkId(); currentAuthCtx->ppkSelect = image->GetPpkSelect(); currentAuthCtx->spkSelect = image->GetSpkSelect(); image->SetAuthContext(new ZynqAuthenticationContext(this->currentAuthCtx)); AuthenticationContext* authCtx = image->GetAuthContext(); authCtx->SetPresignFile(partitionbifoptions->presignFile); authCtx->SetUdfFile(partitionbifoptions->udfDataFile); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } std::string copyName = image->section->Name; StringUtils::ToLower(copyName); if ((StringUtils::EndsWith(copyName, ".bit") || StringUtils::EndsWith(copyName, ".rbt"))) { image->SetAuthBlock(partitionbifoptions->authblockattr, options.GetNoAuthBlocksFlag()); } } break; case Authentication::None: default: { image->SetAuthenticationType(Authentication::None); image->SetAuthContext(new NoneAuthenticationContext()); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } } break; } } /******************************************************************************/ void ZynqBootImage::ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType) { switch (checksumType) { case Checksum::MD5: // For Zynq cases, Checksum is not supported for FSBL image->SetChecksumContext(new MD5ChecksumContext()); break; case Checksum::SHA2: image->SetChecksumContext(new SHA2ChecksumContext()); break; case Checksum::SHA3: image->SetChecksumContext(new SHA3ChecksumContext()); break; case Checksum::None: default: image->SetChecksumContext(new NoneChecksumContext()); break; } } /******************************************************************************/ void ZynqBootImage::ConfigureProcessingStages(ImageHeader* image, PartitionBifOptions* partitionbifoptions) { ConfigureEncryptionContext(image, partitionbifoptions->encryptType); ConfigureAuthenticationContext(image, partitionbifoptions->authType, partitionbifoptions); ConfigureChecksumContext(image, partitionbifoptions->checksumType); image->SetPartOwner(partitionbifoptions->ownerType); } /******************************************************************************/ void ZynqBootImage::DetermineEncryptionDefaults() { if (legacyEncryptionEnabled) { Encryption::Type defaultType = Encryption::None; if (assumeEncryption) { bool explicitlySet = false; /* Legacy behavior for BIF files that do not explicitly set [encryption=aes|none]. loop through all the images. If the encryption context is set (at least once), then this is the "new" functionality. If it is not set at all, this is legacy functionality. */ for (std::list::iterator image = imageList.begin(); image != imageList.end(); image++) { if ((*image)->GetEncryptContext() != NULL) { explicitlySet = true; break; } } if (explicitlySet) { defaultType = Encryption::None; } else { bool globalEncryptionRequested = ( options.GetEncryptedKeySource() != KeySource::None || options.GetHmac() != "" || options.GetKey0() != "" || options.GetStartCbc() != "" || options.GetEncryptionKeyFile() != ""); if (globalEncryptionRequested) { defaultType = Encryption::AES; } else { defaultType = Encryption::None; } } } /* Apply the default to all images that were not explicitly specified */ for (std::list::iterator image = imageList.begin(); image != imageList.end(); image++) { if ((*image)->GetEncryptContext() == NULL) { switch (defaultType) { case Encryption::AES: { ZynqEncryptionContext* aes = new ZynqEncryptionContext(); std::string keyFile = options.GetEncryptionKeyFile(); if (keyFile != "") aes->SetAesFileName(keyFile); else aes->SetAesFileName(keyFile); (*image)->SetEncryptContext(aes); } break; case Encryption::None: default: (*image)->SetEncryptContext(new NoneEncryptionContext()); break; } } /* Set or verify the bootrom key source/encryption ONLY for the FSBL */ if ((*image)->IsBootloader()) { if ((*image)->GetEncryptContext()->Type() == Encryption::None) { options.SetEncryptedKeySource(KeySource::None); } else { if (options.GetEncryptedKeySource() == KeySource::None) { LOG_ERROR("A key source must be specified in order to have an encrypted partition. Please specify -encrypt efuse|bbram at the command line."); } } } } } } /******************************************************************************/ void ZynqBootImage::ParseBootImage(PartitionBifOptions* it) { LOG_INFO("Importing BootImage..."); std::string baseFile = StringUtils::BaseName(it->filename); if (StringUtils::GetExtension(baseFile) == ".mcs") { LOG_ERROR("Parsing mcs format file is not supported : %s", baseFile.c_str()); } std::ifstream src(it->filename.c_str(), std::ios::binary); if (!src.good()) { LOG_ERROR("Failure in reading bootimage file for import - %s ", baseFile.c_str()); } importedBh = new ZynqBootHeader(src); if (importedBh->GetIdentificationWord() != HEADER_ID_WORD) { LOG_ERROR("File %s is not a bootimage. It is missing the header signature", baseFile.c_str()); } if (importedBh->GetHeaderVersion() == BOOTHEADER_VERSION) { uint32_t calcChecksum = importedBh->CalcHeaderChecksum(importedBh->GetChecksumStartPtr(), 40); if (calcChecksum != importedBh->GetHeaderChecksum()) { LOG_ERROR("File %s has a corrupted bootimage header. The checksum is incorrect", baseFile.c_str()); } } /* If imported header has a non-zero source offset, it must be a FSBL header, so it must be copied */ static bool bHImported = false; if (!bHImported) { LOG_INFO("Copying bootheader from %s ", baseFile.c_str()); SetAssumeEncryptionFlag(false); options.SetEncryptedKeySource(importedBh->GetEncryptionKeySource()); bootHeader->Copy(importedBh); bHImported = true; } src.seekg(importedBh->GetImageHeaderByteOffset()); ImageHeaderTable* imageHeaderTable = new ZynqImageHeaderTable(src); uint32_t offset = imageHeaderTable->GetFirstImageHeaderOffset() * sizeof(uint32_t); do { src.seekg(offset); ImageHeader* image = new ZynqImageHeader(src); if (image->GetPartitionHeaderList().size() > 0) { /* FsblLoadAddress not available in boot header for ZynqMp. ExecAddress available for both Zynq & ZynqMp */ bool checkLoadAddrInBhAndPht = (image->GetPartitionHeaderList().front()->GetExecAddress() == importedBh->GetFsblExecAddress()); bool isItBootloader = (checkLoadAddrInBhAndPht && (importedBh->GetSourceOffset() != 0)); image->SetBootloader(isItBootloader); if (image->IsBootloader()) { LOG_INFO("Found Bootloader in %s at offset 0x%x ", baseFile.c_str(), importedBh->GetSourceOffset()); } } image->SetAlignment(it->alignment); image->SetOffset(it->offset); image->SetReserve(it->reserve, it->updateReserveInPh); image->SetLoad(it->load); image->SetStartup(it->startup); /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetSpkFile(options.bifOptions->GetSPKFileName()); image->SetSskFile(options.bifOptions->GetSSKFileName()); image->SetSpkSignFile(options.bifOptions->GetSPKSignFileName()); // Local AES key file is mandatory when the partition is encrypted if (it->aesKeyFile != "") { LOG_ERROR("This usage of 'aeskeyfile' is not supported for ZYNQ. Please refer 'bootgen -bif_help aeskeyfile' for more info."); } else if ((options.GetEncryptionKeyFile() != "") && (image->IsBootloader())) { image->SetAesKeyFile(options.GetEncryptionKeyFile()); } else { /* If no key file found in partition specific attributes Generate aeskeyfile with partition_name.nky */ std::string name = StringUtils::RemoveExtension(image->GetName()) + ".nky"; image->SetAesKeyFile(name); } ConfigureProcessingStages(image, it); imageList.push_back(image); /* image is just temporary, we need to get a pointer back to the copied object and relink */ imageList.back()->Relink(); ImageHeader* newImage = imageList.back(); /* Determine if we need to load in previous RSAAuthentication information */ for (std::list::iterator partHdr = newImage->GetPartitionHeaderList().begin(); partHdr != newImage->GetPartitionHeaderList().end(); partHdr++) { PartitionHeader* ph = (*partHdr); uint32_t encrPartLen = ph->GetEncryptedPartitionLength(); size_t imageAuthBlock = image->GetAuthBlock(); int acSize = 1; if (imageAuthBlock != 0) { acSize = encrPartLen / (imageAuthBlock * 1024 * 1024); if (encrPartLen % imageAuthBlock != 0) { acSize++; } } if (ph->IsAuthCertPresent()) { LOG_INFO("Loading AC context for section %s ", ph->section->Name.c_str()); image->SetAuthenticationType(Authentication::RSA); options.bifOptions->SetHeaderAC(true); /* load in previous certificate data */ for (int i = 0; i < acSize; i++) { void *cert = (ph->partition->section->Data + ph->GetCertificateRelativeByteOffset()); AuthenticationContext::SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); AuthenticationContext* auth = new ZynqAuthenticationContext((AuthCertificate2048Structure*)cert); AuthenticationCertificate* tempac; tempac = new RSA2048AuthenticationCertificate(auth); auth->preSigned = true; tempac->fsbl = true; ph->ac.push_back(tempac); newImage->SetAuthContext(auth); } } } offset = image->GetNextImageHeaderOffset(); } while (offset != 0); } /******************************************************************************/ void ZynqBootImage::ValidateSecureAttributes(ImageHeader * image, BifOptions * bifoptions, PartitionBifOptions * partitionBifOptions) { switch (partitionBifOptions->encryptType) { case Encryption::AES: if (XipMode) { LOG_ERROR("Encryption not supported in XIP Mode"); } break; default: break; } switch (partitionBifOptions->authType) { case Authentication::RSA: { bifoptions->SetHeaderAC(true); if (XipMode) { LOG_ERROR("Authentication not supported in XIP Mode"); } std::string copyName = image->section->Name; StringUtils::ToLower(copyName); if ((StringUtils::EndsWith(copyName, ".bit") || StringUtils::EndsWith(copyName, ".rbt"))) { } else if (partitionBifOptions->authblockattr != 0) { LOG_ERROR("'-authblocks' option supported only for bit stream"); } } break; case Authentication::None: default: { if (partitionBifOptions->presignFile != "") { LOG_ERROR("Cannot specify 'presign' attribute when Authentication is not enabled"); } if (partitionBifOptions->udfDataFile != "") { LOG_ERROR("Cannot specify 'udf_data' attribute with Authentication is not enabled"); } if (partitionBifOptions->authblockattr != 0) { LOG_ERROR("Cannot specify '-authblocks' attribute with Authentication NOT enabled"); } } break; } switch (partitionBifOptions->checksumType) { case Checksum::MD5: if (partitionBifOptions->bootloader) { LOG_ERROR("Zynq FSBL does not support checksum attribute"); } break; default: break; } } /******************************************************************************/ void ZynqBootImage::ParsePartitionDataToImage(BifOptions * bifoptions, PartitionBifOptions * partitionBifOptions) { ImageHeader *image = new ZynqImageHeader(partitionBifOptions->filename); image->SetBootloader(partitionBifOptions->bootloader); image->SetAlignment(partitionBifOptions->alignment); image->SetOffset(partitionBifOptions->offset); image->SetReserve(partitionBifOptions->reserve, partitionBifOptions->updateReserveInPh); image->SetLoad(partitionBifOptions->load); image->SetStartup(partitionBifOptions->startup); image->SetBootFlag(partitionBifOptions->boot); image->SetMultibootFlag(partitionBifOptions->multiboot); image->SetNoAutoStartFlag(partitionBifOptions->noautostart); image->SetProtectedFlag(partitionBifOptions->Protected); image->SetStaticFlag(partitionBifOptions->Static); image->SetUserFlag(partitionBifOptions->user); image->SetSpkFile(bifoptions->GetSPKFileName()); image->SetSskFile(bifoptions->GetSSKFileName()); image->SetSpkSignFile(bifoptions->GetSPKSignFileName()); if (partitionBifOptions->aesKeyFile != "") { LOG_ERROR("This usage of 'aeskeyfile' is not supported for ZYNQ. Please refer 'bootgen -bif_help aeskeyfile' for more info."); } if (partitionBifOptions->aesKeyFile != "") { image->SetAesKeyFile(partitionBifOptions->aesKeyFile); } else if ((options.GetEncryptionKeyFile() != "") && (image->IsBootloader())) { image->SetAesKeyFile(options.GetEncryptionKeyFile()); } else { /* If no key file found in partition specific attributes - Generate aeskeyfile with partition_name.nky */ std::string name = StringUtils::RemoveExtension(image->GetName()) + ".nky"; image->SetAesKeyFile(name); } if (image->IsBootloader()) { if (bootloaderFound == true) { LOG_ERROR("BIF attribute error !!!\n\t\tA bootimage cannot have more than one bootloader."); } bootloaderFound = true; fsblFilename = partitionBifOptions->filename; options.fsblFilename = partitionBifOptions->filename; } ConfigureProcessingStages(image, partitionBifOptions); ValidateSecureAttributes(image, bifoptions, partitionBifOptions); imageList.push_back(image); } /******************************************************************************/ void ZynqBootImage::Add(BifOptions* bifoptions) { if (bifoptions->GetAESKeyFileName() != "") { currentEncryptCtx->SetAesFileName(bifoptions->GetAESKeyFileName()); options.SetEncryptionKeyFile(bifoptions->GetAESKeyFileName()); } if (options.GetAuthKeyGeneration() == GenAuthKeys::None) { if (bifoptions->GetPPKFileName() != "") { LOG_TRACE("Parsing PPK Key File"); currentAuthCtx->SetPPKeyFile(bifoptions->GetPPKFileName()); currentAuthCtx->ParsePPKeyFile(bifoptions->GetPPKFileName()); } if (bifoptions->GetPSKFileName() != "") { LOG_TRACE("Parsing PSK Key File"); currentAuthCtx->SetPSKeyFile(bifoptions->GetPSKFileName()); currentAuthCtx->ParsePSKeyFile(bifoptions->GetPSKFileName()); } if (bifoptions->GetSPKFileName() != "") { LOG_TRACE("Parsing SPK Key File"); currentAuthCtx->SetSPKeyFile(bifoptions->GetSPKFileName()); currentAuthCtx->ParseSPKeyFile(bifoptions->GetSPKFileName()); if (options.DoGenerateHashes()) { LOG_INFO("Generating SPK Hash File"); currentAuthCtx->GenerateSPKHashFile(bifoptions->GetSPKFileName(), hash); } } if (bifoptions->GetSSKFileName() != "") { LOG_TRACE("Parsing SSK Key File"); currentAuthCtx->SetSSKeyFile(bifoptions->GetSSKFileName()); currentAuthCtx->ParseSSKeyFile(bifoptions->GetSSKFileName()); } } if (bifoptions->GetSPKSignFileName() != "") { LOG_TRACE("Parsing SPK Signature File"); currentAuthCtx->SetSPKSignatureFile(bifoptions->GetSPKSignFileName()); } XipMode = bifoptions->GetXipMode(); if (options.GetAuthKeyGeneration() != GenAuthKeys::None) { LOG_WARNING("A bootimage cannot be generated on the go, with '-generate_keys'.\n However, the requested keys will be generated."); return; } LOG_INFO("Parsing Partition Data to Image"); for (std::list::iterator it = bifoptions->partitionBifOptionList.begin(); it != bifoptions->partitionBifOptionList.end(); it++) { if ((*it)->bootImage) { ParseBootImage((*it)); } else { ParsePartitionDataToImage(bifOptions, *it); } } } xilinx-bootgen-2024.2/bootimage-zynq.h000077500000000000000000000047551475706442400177220ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTIMAGE_ZYNQ_H_ #define _BOOTIMAGE_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "bootheader-zynq.h" #include "imageheadertable-zynq.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqBootImage : public BootImage { public: ZynqBootImage(Options& options, uint8_t index); ~ZynqBootImage() { if (importedBh != NULL) { delete importedBh; } }; void ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType); void ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions); void ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType); void ConfigureProcessingStages(ImageHeader * image, PartitionBifOptions * partitionbifoptions); void DetermineEncryptionDefaults(); void ParseBootImage(PartitionBifOptions * it); void ValidateSecureAttributes(ImageHeader * image, BifOptions* bifoptions, PartitionBifOptions* partitionBifOptions); void ParsePartitionDataToImage(BifOptions* bifoptions, PartitionBifOptions* it); void Add(BifOptions* bifoptions); protected: ZynqBootHeader* importedBh; }; #endif xilinx-bootgen-2024.2/bootimage-zynqmp.cpp000077500000000000000000000606731475706442400206130ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage-zynqmp.h" #include "bifoptions.h" #include "encryption-zynqmp.h" #include "authentication-zynqmp.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqMpBootImage::ZynqMpBootImage(Options& options, uint8_t index) : BootImage(options, index) { partitionHeaderList.clear(); bootHeader = new ZynqMpBootHeader(); imageHeaderTable = new ZynqMpImageHeaderTable(); partitionHeaderTable = new PartitionHeaderTable(); currentEncryptCtx = new ZynqMpEncryptionContext(); currentAuthCtx = new ZynqMpAuthenticationContext(); SetLegacyEncryptionFlag(true); partitionOutput = new ZynqMpPartitionOutput(); hash = new HashSha3(); currentAuthCtx->hash = hash; AuthenticationContext::SetZynpMpVerEs1Flag(options.GetZynqmpes1Flag()); partitionHeaderTable->firstSection = NULL; importedBh = NULL; } /******************************************************************************/ void ZynqMpBootImage::ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType) { switch (encryptType) { case Encryption::AES: if (image->GetAesKeyFile() != "") { std::ifstream keyFile(image->GetAesKeyFile()); if (!keyFile.good()) { image->SetAesKeyFileGeneration(true); } } image->SetEncryptContext(new ZynqMpEncryptionContext(this->currentEncryptCtx)); break; case Encryption::None: image->ValidateEncryptionAttributes(*this); image->SetEncryptContext(new NoneEncryptionContext()); break; default: image->SetEncryptContext(NULL); break; } } /******************************************************************************/ void ZynqMpBootImage::ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions) { std::string spkSignFile = options.GetSpkSigFileName(); switch (authType) { case Authentication::RSA: { image->SetAuthenticationType(Authentication::RSA); options.bifOptions->SetHeaderAC(true); this->currentAuthCtx->hashType = GetAuthHashAlgo(); if (image->GetSpkFile() != "") { currentAuthCtx->spkFile = image->GetSpkFile(); } if (image->GetSskFile() != "") { currentAuthCtx->sskFile = image->GetSskFile(); } if (image->GetSpkSignFile() != "") { currentAuthCtx->spkSignFile = image->GetSpkSignFile(); } if (image->GetBhSignFile() != "") { currentAuthCtx->bhSignFile = image->GetBhSignFile(); } currentAuthCtx->spkIdentification = image->GetSpkId(); currentAuthCtx->ppkSelect = image->GetPpkSelect(); currentAuthCtx->spkSelect = image->GetSpkSelect(); image->SetAuthContext(new ZynqMpAuthenticationContext(this->currentAuthCtx)); AuthenticationContext* authCtx = image->GetAuthContext(); authCtx->SetPresignFile(partitionbifoptions->presignFile); authCtx->SetACFile(partitionbifoptions->acFile); authCtx->SetUdfFile(partitionbifoptions->udfDataFile); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } std::string copyName = image->section->Name; StringUtils::ToLower(copyName); if ((StringUtils::EndsWith(copyName, ".bit") || StringUtils::EndsWith(copyName, ".rbt"))) { image->SetAuthBlock(partitionbifoptions->authblockattr, options.GetNoAuthBlocksFlag()); } else if (StringUtils::EndsWith(copyName, ".hashbit")) { image->SetAuthBlock(partitionbifoptions->authblockattr, true); } } break; case Authentication::None: default: { image->SetAuthenticationType(Authentication::None); image->SetAuthContext(new NoneAuthenticationContext()); if (spkSignFile != "") { currentAuthCtx->GenerateSPKSignature(spkSignFile); currentAuthCtx->spkSignRequested = spkSignFile; } } break; } } /******************************************************************************/ void ZynqMpBootImage::ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType) { switch (checksumType) { case Checksum::MD5: image->SetChecksumContext(new MD5ChecksumContext()); break; case Checksum::SHA2: image->SetChecksumContext(new SHA2ChecksumContext()); break; case Checksum::SHA3: image->SetChecksumContext(new SHA3ChecksumContext()); break; case Checksum::None: default: image->SetChecksumContext(new NoneChecksumContext()); break; } } /******************************************************************************/ void ZynqMpBootImage::ConfigureProcessingStages(ImageHeader* image, PartitionBifOptions* partitionbifoptions) { ConfigureEncryptionContext(image, partitionbifoptions->encryptType); ConfigureAuthenticationContext(image, partitionbifoptions->authType, partitionbifoptions); ConfigureChecksumContext(image, partitionbifoptions->checksumType); image->SetPartOwner(partitionbifoptions->ownerType); } /******************************************************************************/ void ZynqMpBootImage::ParseBootImage(PartitionBifOptions* it) { LOG_INFO("Importing BootImage..."); std::string baseFile = StringUtils::BaseName(it->filename); if (StringUtils::GetExtension(baseFile) == ".mcs") { LOG_ERROR("Parsing mcs format file is not supported : %s", baseFile.c_str()); } std::ifstream src(it->filename.c_str(), std::ios::binary); if (!src.good()) { LOG_ERROR("Failure in reading bootimage file for import - %s ", baseFile.c_str()); } importedBh = new ZynqMpBootHeader(src); if (importedBh->GetIdentificationWord() != HEADER_ID_WORD) { LOG_ERROR("File %s is not a bootimage. It is missing the header signature", baseFile.c_str()); } if (importedBh->GetHeaderVersion() != 0xFFFFFFFF) { LOG_WARNING("This version of bootgen may not support the bootimage header in %s ", baseFile.c_str()); LOG_WARNING("The version of the imported header is 0x%X, and this version of bootgen only supports 0x%X", importedBh->GetHeaderVersion(), BOOTHEADER_VERSION); } /* Authentication attribues to be appended to the attributes from stage2-Encrypted Image */ uint32_t fsblattributes = importedBh->GetFsblAttributes(); if (options.bifOptions->GetBhRsa() != BhRsa::BhRsaDisable) { fsblattributes |= options.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; } if (authHash != AuthHash::Sha3) { fsblattributes |= authHash << AUTH_HASH_BIT_SHIFT; } importedBh->SetFsblAttributes(fsblattributes); /* If imported header has a non-zero source offset, it must be a FSBL header, so it must be copied */ static bool bHImported = false; if (!bHImported) { LOG_INFO("Copying bootheader from %s ", baseFile.c_str()); SetAssumeEncryptionFlag(false); options.SetEncryptedKeySource(importedBh->GetEncryptionKeySource()); bootHeader->Copy(importedBh); bHImported = true; } src.seekg(importedBh->GetImageHeaderByteOffset()); ImageHeaderTable* imageHeaderTable = new ZynqMpImageHeaderTable(src); uint32_t offset = imageHeaderTable->GetFirstImageHeaderOffset() * sizeof(uint32_t); do { src.seekg(offset); ImageHeader* image = new ZynqMpImageHeader(src); if (image->GetPartitionHeaderList().size() > 0) { /* FsblLoadAddress not available in boot header for ZynqMp. ExecAddress available for both Zynq & ZynqMp */ bool checkLoadAddrInBhAndPht = (image->GetPartitionHeaderList().front()->GetExecAddress() == importedBh->GetFsblExecAddress()); bool isItBootloader = (checkLoadAddrInBhAndPht && (importedBh->GetSourceOffset() != 0)); image->SetBootloader(isItBootloader); if (image->IsBootloader()) { LOG_INFO("Found Bootloader in %s at offset 0x%x ", baseFile.c_str(), importedBh->GetSourceOffset()); } } image->SetAlignment(it->alignment); image->SetOffset(it->offset); image->SetReserve(it->reserve, it->updateReserveInPh); image->SetLoad(it->load); image->SetStartup(it->startup); image->SetUserPartitionNum(it->pid); image->SetPpkSelect(bifOptions->GetPpkSelection()); /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetSpkFile(options.bifOptions->GetSPKFileName()); if (it->spkFile != "") { image->SetSpkFile(it->spkFile); } image->SetSskFile(options.bifOptions->GetSSKFileName()); if (it->sskFile != "") { image->SetSskFile(it->sskFile); } image->SetSpkSignFile(options.bifOptions->GetSPKSignFileName()); if (it->spkSignatureFile != "") { image->SetSpkSignFile(it->spkSignatureFile); } image->SetSpkId(bifOptions->GetSpkId()); if (it->spkIdLocal) { image->SetSpkId(it->spkId); } image->SetSpkSelect(bifOptions->GetSpkSelection()); if (it->spkSelLocal) { image->SetSpkSelect(it->spkSelect); } image->SetBhSignFile(options.bifOptions->GetBHSignFileName()); /* Local AES key file is mandatory when the partition is encrypted */ char* aeskeyfileENV = getenv("AESKEYFILE"); if (it->aesKeyFile != "") { image->SetAesKeyFile(it->aesKeyFile); } else if ((aeskeyfileENV != NULL) && (options.GetEncryptionKeyFile() != "") && (image->IsBootloader())) { image->SetAesKeyFile(options.GetEncryptionKeyFile()); } else { /* If no key file found in partition specific attributes Generate aeskeyfile with partition_name.nky */ std::string name = StringUtils::RemoveExtension(image->GetName()) + ".nky"; image->SetAesKeyFile(name); } ConfigureProcessingStages(image, it); imageList.push_back(image); /* image is just temporary, we need to get a pointer back to the copied object and relink */ imageList.back()->Relink(); ImageHeader* newImage = imageList.back(); /* Determine if we need to load in previous RSAAuthentication information */ for (std::list::iterator partHdr = newImage->GetPartitionHeaderList().begin(); partHdr != newImage->GetPartitionHeaderList().end(); partHdr++) { PartitionHeader* ph = (*partHdr); uint32_t encrPartLen = ph->GetEncryptedPartitionLength(); size_t imageAuthBlock = image->GetAuthBlock(); int acSize = 1; if (imageAuthBlock != 0) { acSize = encrPartLen / (imageAuthBlock * 1024 * 1024); if (encrPartLen % (imageAuthBlock * 1024 * 1024) != 0) { acSize++; } } if (ph->IsAuthCertPresent()) { LOG_INFO("Loading AC context for section %s ", ph->section->Name.c_str()); image->SetAuthenticationType(Authentication::RSA); options.bifOptions->SetHeaderAC(true); /* load in previous certificate data */ for (int i = 0; i < acSize; i++) { void *cert = (ph->partition->section->Data + ph->GetCertificateRelativeByteOffset()); AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); AuthenticationContext* auth = new ZynqMpAuthenticationContext((AuthCertificate4096Structure*)cert); AuthenticationCertificate* tempac; tempac = new RSA4096AuthenticationCertificate(auth); auth->preSigned = true; tempac->fsbl = true; ph->ac.push_back(tempac); newImage->SetAuthContext(auth); } } } offset = image->GetNextImageHeaderOffset(); } while (offset != 0); } /******************************************************************************/ void ZynqMpBootImage::ValidateSecureAttributes(ImageHeader * image,BifOptions * bifoptions, PartitionBifOptions * partitionBifOptions) { switch (partitionBifOptions->encryptType) { case Encryption::AES: if (XipMode) { LOG_ERROR("Encryption not supported in XIP Mode"); } if (image->IsBootloader()) { if (bifoptions->GetAuthOnly() == AuthOnly::Enabled) { LOG_ERROR("Cannot encrypt bootloader, when 'auth_only' attribute is used"); } } break; default: if (image->IsBootloader() && bifoptions->GetOptKey() == OptKey::OptKeyinSecHdr) { LOG_ERROR("Optional key cannot be used, if bootloader is not encrypted\n Cannot use 'opt_key' in [fsbl_config] attribute when encryption is not used"); } break; } switch (partitionBifOptions->authType) { case Authentication::RSA: { if (XipMode) { LOG_ERROR("Authentication not supported in XIP Mode"); } if (currentAuthCtx->spkSelect == SpkSelect::USER_eFUSE) { if ((currentAuthCtx->spkIdentification == 0) || (currentAuthCtx->spkIdentification > 0x100)) { LOG_ERROR("spk_id can only take values from 0x1 to 0x100, if spk_select=user-efuse"); } } std::string copyName = image->section->Name; StringUtils::ToLower(copyName); if ((StringUtils::EndsWith(copyName, ".bit") || StringUtils::EndsWith(copyName, ".rbt"))) { } else if (partitionBifOptions->authblockattr != 0) { LOG_ERROR("'authblocks' option supported only for bit stream"); } } break; case Authentication::None: default: { if (partitionBifOptions->presignFile != "") { LOG_ERROR("Cannot specify 'presign' attribute when Authentication is not enabled"); } if (partitionBifOptions->acFile != "") { LOG_ERROR("Cannot specify 'ac' attribute when Authentication is not enabled"); } if (partitionBifOptions->udfDataFile != "") { LOG_ERROR("Cannot specify 'udf_data' attribute with Authentication is not enabled"); } if (partitionBifOptions->authblockattr != 0) { LOG_ERROR("Cannot specify 'authblocks' attribute with Authentication NOT enabled"); } if ((image->IsBootloader()) && (bifoptions->GetAuthOnly() == AuthOnly::Enabled)) { LOG_ERROR("Bootloader must be authenticated if auth_only is used in [fsbl_config] attribute."); } } break; } } /******************************************************************************/ void ZynqMpBootImage::ParsePartitionDataToImage(BifOptions* bifoptions, PartitionBifOptions* partitionBifOptions) { ImageHeader *image = new ZynqMpImageHeader(partitionBifOptions->filename); image->SetBootloader(partitionBifOptions->bootloader); image->SetAlignment(partitionBifOptions->alignment); image->SetOffset(partitionBifOptions->offset); image->SetReserve(partitionBifOptions->reserve, partitionBifOptions->updateReserveInPh); image->SetLoad(partitionBifOptions->load); image->SetStartup(partitionBifOptions->startup); image->SetUserPartitionNum(partitionBifOptions->pid); image->SetBootFlag(partitionBifOptions->boot); image->SetMultibootFlag(partitionBifOptions->multiboot); image->SetNoAutoStartFlag(partitionBifOptions->noautostart); image->SetProtectedFlag(partitionBifOptions->Protected); image->SetStaticFlag(partitionBifOptions->Static); image->SetUserFlag(partitionBifOptions->user); image->SetDestDevice(partitionBifOptions->destDeviceType); if (image->IsBootloader()) { SetDestCpuFromCore(bifOptions->GetCore(), partitionBifOptions->destCPUType); } image->SetDestCpu(partitionBifOptions->destCPUType); image->SetExceptionLevel(partitionBifOptions->exceptionLevel); image->SetTrustZone(partitionBifOptions->trustzone); image->SetEarlyHandoff(partitionBifOptions->early_handoff); image->SetHivec(partitionBifOptions->hivec); image->SetA32ExecMode(partitionBifOptions->a32Mode); image->SetBigEndian(partitionBifOptions->bigEndian); image->SetBhSignFile(bifoptions->GetBHSignFileName()); image->SetPpkSelect(bifOptions->GetPpkSelection()); /* Local key files/signatures within partition attributes have more priority than global key/signature files, if both specified */ image->SetSpkFile(bifoptions->GetSPKFileName()); if (partitionBifOptions->spkFile != "") { image->SetSpkFile(partitionBifOptions->spkFile); } image->SetSskFile(bifoptions->GetSSKFileName()); if (partitionBifOptions->sskFile != "") { image->SetSskFile(partitionBifOptions->sskFile); } image->SetSpkSignFile(bifoptions->GetSPKSignFileName()); if (partitionBifOptions->spkSignatureFile != "") { image->SetSpkSignFile(partitionBifOptions->spkSignatureFile); } image->SetSpkId(bifOptions->GetSpkId()); if (partitionBifOptions->spkIdLocal) { image->SetSpkId(partitionBifOptions->spkId); } image->SetSpkSelect(bifOptions->GetSpkSelection()); if (partitionBifOptions->spkSelLocal) { image->SetSpkSelect(partitionBifOptions->spkSelect); } /* Local AES key file is mandatory when the partition is encrypted */ if (partitionBifOptions->aesKeyFile != "") { image->SetAesKeyFile(partitionBifOptions->aesKeyFile); } else { /* If no key file found in partition specific attributes - Generate aeskeyfile with partition_name.nky */ std::string name = StringUtils::RemoveExtension(image->GetName()) + ".nky"; image->SetAesKeyFile(name); } if (image->IsBootloader()) { if (bootloaderFound == true) { LOG_ERROR("BIF attribute error !!!\n\t\tA bootimage cannot have more than one bootloader."); } bootloaderFound = true; fsblFilename = partitionBifOptions->filename; options.fsblFilename = partitionBifOptions->filename; if (partitionBifOptions->hivec) { LOG_ERROR("BIF attribute error !!!\n\t\t'hivec' not supported for bootloader partition"); } } if (partitionBifOptions->encryptType == Encryption::AES) { std::vector encrBlocks = partitionBifOptions->GetEncryptionBlocks(); for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { image->InsertEncrBlocksList(encrBlocks[itr]); } image->SetDefaultEncrBlockSize(partitionBifOptions->GetDefaultEncryptionBlockSize()); } if ((bifoptions->GetAuthOnly() == AuthOnly::Enabled) && (options.GetEncryptedKeySource() == KeySource::None)) { LOG_ERROR("Key Source is mandatory when 'auth_only' attribute is used."); } ConfigureProcessingStages(image, partitionBifOptions); ValidateSecureAttributes(image,bifoptions, partitionBifOptions); imageList.push_back(image); } /******************************************************************************/ void ZynqMpBootImage::Add(BifOptions* bifoptions) { //check-R filespec->Dump(); if (bifoptions->GetAESKeyFileName() != "") { if (options.GetGreyKeyGeneration() ) { currentEncryptCtx->SetAesFileName(bifoptions->GetAESKeyFileName()); options.SetEncryptionKeyFile(bifoptions->GetAESKeyFileName()); } else { LOG_ERROR("This usage of 'aeskeyfile' is not supported for ZYNQMP. \n Please refer 'bootgen -bif_help aeskeyfile' for more info. \n Use of the same .nky file across multiple partitions results in re-use of the key, which is not a good security practice."); } } currentEncryptCtx->SetMetalKeyFile(bifoptions->GetFamilyKeyFileName()); currentAuthCtx->SetPpkSelect(bifoptions->GetPpkSelection()); currentAuthCtx->SetSpkSelect(bifoptions->GetSpkSelection()); currentAuthCtx->SetSpkIdentification(bifoptions->GetSpkId()); currentAuthCtx->SetHeaderAuthentication(bifoptions->GetHeaderAC()); if (options.GetAuthKeyGeneration() == GenAuthKeys::None) { if (bifoptions->GetPPKFileName() != "") { LOG_TRACE("Parsing PPK Key File"); currentAuthCtx->SetPPKeyFile(bifoptions->GetPPKFileName()); currentAuthCtx->ParsePPKeyFile(bifoptions->GetPPKFileName()); } if (bifoptions->GetPSKFileName() != "") { LOG_TRACE("Parsing PSK Key File"); currentAuthCtx->SetPSKeyFile(bifoptions->GetPSKFileName()); currentAuthCtx->ParsePSKeyFile(bifoptions->GetPSKFileName()); } if (bifoptions->GetSPKFileName() != "") { LOG_TRACE("Parsing SPK Key File"); currentAuthCtx->SetSPKeyFile(bifoptions->GetSPKFileName()); if (options.DoGenerateHashes()) { LOG_INFO("Generating SPK Hash File"); currentAuthCtx->GenerateSPKHashFile(bifoptions->GetSPKFileName(), hash); } } if (bifoptions->GetSSKFileName() != "") { LOG_TRACE("Parsing SSK Key File"); currentAuthCtx->SetSSKeyFile(bifoptions->GetSSKFileName()); } } if (bifoptions->GetSPKSignFileName() != "") { LOG_TRACE("Parsing SPK Signature File"); currentAuthCtx->SetSPKSignatureFile(bifoptions->GetSPKSignFileName()); } if (bifoptions->GetBHSignFileName() != "") { LOG_TRACE("Parsing BH Signature File"); currentAuthCtx->SetBHSignatureFile(bifoptions->GetBHSignFileName()); } currentEncryptCtx->SetBHKekIVFile(bifoptions->GetBHKekIVFile()); XipMode = bifoptions->GetXipMode(); if (options.GetAuthKeyGeneration() != GenAuthKeys::None) { LOG_WARNING("A bootimage cannot be generated on the go, with '-generate_keys'.\n However, the requested keys will be generated."); return; } if (options.GetGreyKeyGeneration()) { LOG_WARNING("A bootimage cannot be generated on the go, with '-generate_keys'.\n However, the requested keys will be generated.\n Do note to use the same Key0/IV0 pair in AES key file while generating a bootimage."); return; } LOG_INFO("Parsing Partition Data to Image"); for (std::list::iterator itr = bifoptions->partitionBifOptionList.begin(); itr != bifoptions->partitionBifOptionList.end(); itr++) { if ((*itr)->bootImage) { ParseBootImage(*itr); } else { ParsePartitionDataToImage(bifOptions,*itr); } } } xilinx-bootgen-2024.2/bootimage-zynqmp.h000077500000000000000000000047231475706442400202520ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _BOOTIMAGE_ZYNQMP_H_ #define _BOOTIMAGE_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "bootheader-zynqmp.h" #include "imageheadertable-zynqmp.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpBootImage : public BootImage { public: ZynqMpBootImage(Options& options, uint8_t index); ~ZynqMpBootImage() { if (importedBh != NULL) { delete importedBh; } } void ConfigureEncryptionContext(ImageHeader * image, Encryption::Type encryptType); void ConfigureAuthenticationContext(ImageHeader * image, Authentication::Type authType, PartitionBifOptions * partitionbifoptions); void ConfigureChecksumContext(ImageHeader * image, Checksum::Type checksumType); void ConfigureProcessingStages(ImageHeader * image, PartitionBifOptions * partitionbifoptions); void ParseBootImage(PartitionBifOptions * it); void ValidateSecureAttributes(ImageHeader * image,BifOptions* bifoptions, PartitionBifOptions* partitionBifOptions); void ParsePartitionDataToImage(BifOptions* bifoptions, PartitionBifOptions* it); void Add(BifOptions* bifoptions); protected: ZynqMpBootHeader* importedBh; }; #endif xilinx-bootgen-2024.2/bootimage.cpp000077500000000000000000000734601475706442400172550ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "bootimage.h" #include "bootimage-zynq.h" #include "bootimage-zynqmp.h" #include "bootimage-versal.h" #include "bifscanner.h" #include "bootheader.h" #include "options.h" #include "bootgenexception.h" #include "outputfile.h" #include "binary.h" #include "stringutils.h" #include "checksum.h" #include "logger.h" #include "bitutils.h" /* ------------------------------------------------------------------------------ **************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------ */ std::vector BootImage::encryptionKeyFileVec; /******************************************************************************/ void BIF_File::Process(Options& options) { ParseBifFile(options); bifOptionList = options.bifOptionsList; /* Parse the include bif file */ if (options.includeBifOptionsList.size() > 1) { LOG_ERROR("Multiple include bif files is not supported."); } if (options.includeBifOptionsList.size() != 0) { options.bifOptionsList.clear(); biffilename = options.includeBifOptionsList.front(); ParseBifFile(options); includeBifOptionList = options.bifOptionsList; if (options.IsSsitBif()) { includeBifOptionList.back()->slrNum = 0x00; /* Back populate the slr number, based on the group name in master bif for SSIT use cases */ for (std::list::iterator itr = includeBifOptionList.back()->partitionBifOptionList.begin(); itr != includeBifOptionList.back()->partitionBifOptionList.end(); itr++) { if (((*itr)->slrNum != 0xFF) && ((strcmp((*itr)->bifSection.c_str(), "") != 0))) { for (std::size_t j = 0; j < includeBifOptionList.size(); j++) { if (strcmp(includeBifOptionList[j]->GetGroupName().c_str(), (*itr)->bifSection.c_str()) == 0) { includeBifOptionList[j]->slrNum = (*itr)->slrNum; break; } } } } } AppendAndReplaceFilesinBIF(); options.bifOptionsList = bifOptionList = includeBifOptionList; } BootImage* currentbi = NULL; uint8_t index = 0; size_t itr = 0; std::string lastPmcDataAesFile = bifOptionList.back()->GetPmcDataAesFile(); for (std::vector::iterator bifoptions = bifOptionList.begin(); bifoptions != bifOptionList.end(); bifoptions++, itr++) { if (((*bifoptions)->slrBootCnt == 0) && ((*bifoptions)->slrConfigCnt == 0) && options.IsSsitBif()) { (*bifoptions)->pdiType = PartitionType::SLR_SLAVE; if ((*bifoptions)->GetSmapWidth() != 0) { LOG_WARNING("smap_width for SSIT SLAVE PDIs is identified as %d. Setting it to the default value '0'.", (*bifoptions)->GetSmapWidth()); (*bifoptions)->SetSmapWidth(0); } } else if ((*bifoptions)->pdiType == PartitionType::SLR_SLAVE_CONFIG) { (*bifoptions)->SetSmapWidth(0); } if (options.archType == Arch::ZYNQMP) { currentbi = new ZynqMpBootImage(options, index); } else if (options.archType == Arch::VERSAL) { currentbi = new VersalBootImage(options, index); currentbi->pmcDataAesFile = (*bifoptions)->GetPmcDataAesFile(); if ((itr+1) == bifOptionList.size()) { currentbi->pmcDataAesFile = lastPmcDataAesFile; } } else { currentbi = new ZynqBootImage(options, index); } if (currentbi != NULL) { currentbi->Add(*bifoptions); if (((*bifoptions)->pdiType != PartitionType::SLR_SLAVE_BOOT) && ((*bifoptions)->pdiType != PartitionType::SLR_SLAVE_CONFIG)) { if ((*bifoptions)->pdiType == PartitionType::SLR_SLAVE) { if (currentbi->bootloaderFound) { (*bifoptions)->pdiType = PartitionType::SLR_SLAVE_BOOT; } else { (*bifoptions)->pdiType = PartitionType::SLR_SLAVE_CONFIG; } } } bootImages.push_back(currentbi); } Output(options, index); index++; } } /******************************************************************************/ void BIF_File::Output(Options& options, uint8_t index) { File::Type splitFileType = options.GetSplitType(); std::list outFilename = options.GetOutputFileNames(); std::string fName = ""; BootImage* bi = bootImages.at(index); { if (options.GetAuthKeyGeneration() != GenAuthKeys::None) { bi->GenerateAuthenticationKeys(); return; } if (options.GetGreyKeyGeneration()) { bi->GenerateGreyKey(); return; } if (options.GetMetalKeyGeneration()) { LOG_ERROR("The support to generate Family Key is deprecated."); } LOG_INFO("Building image - %s", bi->Name.c_str()); bi->BuildAndLink(bi->cache); bi->SetOutputSplitModeFormat(options.bifOptions->GetSplitMode(), options.bifOptions->GetSplitFormat()); bi->SetOutputBitstreamModeFormat(options.GetProcessBitstreamType()); OutputMode::Type outputMode = options.GetOutputMode(); bi->ValidateOutputModes(splitFileType, outputMode); if (options.GetOutType() != File::Unknown) { if (!outFilename.empty()) { std::string outFile = outFilename.front(); fName = StringUtils::RemoveExtension(outFile); outFilename.clear(); } else { fName = StringUtils::RemoveExtension(biffilename); } fName += (options.GetOutType() == File::MCS) ? ".mcs" : ".bin"; } if (outputMode == OutputMode::OUT_SPLIT_NORMAL || outputMode == OutputMode::OUT_SPLIT_SLAVEBOOT || splitFileType != File::Unknown) { outFilename.clear(); if (options.GetOutType() != File::Unknown) { fName.clear(); } fName = StringUtils::RemoveExtension(biffilename); fName = fName.substr(fName.find_last_of("\\")+1, std::string::npos); if(splitFileType == File::Unknown) { splitFileType = options.GetOutputFormat(); } fName += (splitFileType == File::MCS) ? ".mcs" : ".bin"; } /* Process Bitstream Mode Create a file with the bitstream filename, add proper extension */ if (outputMode == OutputMode::OUT_BITSTREAM) { outFilename.clear(); fName = bi->bitFilename; if(bi->bitFilename.empty()) { LOG_ERROR("No bitstream in the BIF file - %s ",options.GetBifFilename().c_str()); } fName += (options.GetProcessBitstreamType() == File::MCS) ? ".mcs" : ".bin"; } if (fName != "") { outFilename.push_back(fName); } bi->OutputPartitionFiles(options, *bi->cache); /* Create a BIN/MCS file format from the factory Write to the file outputs based on the format */ for(std::list::iterator filename = outFilename.begin();filename != outFilename.end(); filename++) { std::string out_filename; if (index == (options.bifOptionsList.size() - 1)) { out_filename = *filename; } else { out_filename = StringUtils::RemoveExtension(*filename) + "_" + bi->Name + StringUtils::GetExtension(*filename); if (options.IsSsitBif()) { out_filename = StringUtils::RemoveExtension(*filename) + "_" + bi->Name + ".bin"; } } OutputFile* file = OutputFile::Factory(out_filename); file->Output(options, *bi->cache); delete file; } /* Efuse PPK hash for burning the efuse */ bi->OutputOptionalEfuseHash(); /* Secure Debug Image to enable the JTAG during a secure boot scenario */ bi->OutputOptionalSecureDebugImage(); } } /******************************************************************************/ BootImage::BootImage(Options& options, uint8_t index) : options(options) , headerSignature_Loaded(false) , headerAC(0) , XipMode(false) , nullPartHeaderSection(NULL) , core(Core::A53Singlex64) , legacyEncryptionEnabled(true) , hash(NULL) , totalHeadersSize(0) , currentChecksumCtx(NULL) , pmuFwSize(0) , fsblFwSize(0) , totalPmuFwSize(0) , totalFsblFwSize(0) , sourceAddr(0) , bootloaderFound(false) , bootloaderAuthenticate(false) , bootloaderEncrypt(false) , bootloaderKeySource(KeySource::None) , keygen(NULL) , partCount(0) , authHash(AuthHash::Sha3) , assumeEncryption(false) , convertAieElfToCdo(false) , createSubSystemPdis(false) , encryptedHeaders(NULL) , bootHeader(NULL) , imageHeaderTable(NULL) , partitionHeaderTable(NULL) , currentAuthCtx(NULL) , currentEncryptCtx(NULL) , partitionOutput(NULL) , deviceKey(NULL) , firstIv(NULL) , firstOptKey(NULL) , overlayCDO(NULL) , globalSlrId(0) , iht_optional_data(NULL) , iht_optional_data_length(0) , pmcDataAesFile("") , xplm_modules_data_length(0) , xplm_modules_data(NULL) , authOnPartitionFound(false) , numHashTableEntries(0) { options.bifOptions = bifOptions = options.bifOptionsList.at(index); Name = bifOptions->GetGroupName(); cache = new Binary(); checksumTable = new ChecksumTable(); } /******************************************************************************/ BootImage::~BootImage() { if(currentAuthCtx) { delete currentAuthCtx; } if(currentEncryptCtx) { delete currentEncryptCtx; } if(currentChecksumCtx) { delete currentChecksumCtx; } if (checksumTable) { delete checksumTable; } if (cache) { delete cache; } if (bootHeader) { delete bootHeader; } if (imageHeaderTable) { delete imageHeaderTable; } if (partitionHeaderTable) { delete partitionHeaderTable; } if (partitionOutput) { delete partitionOutput; } if (deviceKey) { delete deviceKey; } if (firstIv) { delete firstIv; } if (firstOptKey) { delete firstOptKey; } if (keygen) { delete keygen; } if (hash) { delete hash; } if (nullPartHeaderSection) { delete nullPartHeaderSection; } } /******************************************************************************/ void BootImage::OutputOptionalEfuseHash() { std::string hashFile = options.GetEfuseHashFileName(); if (hashFile != "") { if (bifOptions->GetPPKFileName() != "" || bifOptions->GetPSKFileName() != "") { if (currentAuthCtx) { currentAuthCtx->GeneratePPKHash(hashFile); } } else { LOG_ERROR("Cannot read PPK/PSK. PPK/PSK is mandatory to generate PPK hash bits, using '-efuseppkbits'."); } } } /******************************************************************************/ void BootImage::BuildAndLink(Binary* cache) { if( imageList.size() == 0 ) { LOG_WARNING("No partition images given"); } currentAuthCtx->SetPpkSelect(bifOptions->GetPpkSelection()); currentAuthCtx->SetSpkSelect(bifOptions->GetSpkSelection()); currentAuthCtx->SetSpkIdentification(bifOptions->GetSpkId()); DetermineEncryptionDefaults(); partitionHeaderList.clear(); /* Build stage */ /* all static fields within the header tables are populated here */ bootHeader->Build(*this,*cache); imageHeaderTable->Build(*this,*cache); partitionHeaderTable->Build(*this,*cache); partitionHeaderTable->BuildPartitions(*this,*cache); checksumTable->Build(*this,*cache); LOG_INFO("After build "); LOG_DUMP_IMAGE(*cache); /* Stack and alignment stage */ /* Once the header tables are created, stack all the tables and do the necessary alignment */ cache->StackAndAlign(options); LOG_INFO("After align "); LOG_DUMP_IMAGE(*cache); PrintPartitionInformation(); /* Link stage - fields which depend on partitions are populated here */ bootHeader->Link(*this); imageHeaderTable->Link(*this); partitionHeaderTable->Link(*this); partitionHeaderTable->LinkPartitions(*this); checksumTable->Link(*this); LOG_INFO("After Link "); LOG_DUMP_IMAGE(*cache); } /******************************************************************************/ void BootImage::PrintPartitionInformation(void) { LOG_INFO("Partition Information: "); std::string lastImageName; for (std::list::iterator pH = partitionHeaderList.begin(); pH != partitionHeaderList.end(); pH++) { static uint8_t index = 0; if ((lastImageName.compare((*pH)->imageHeader->GetName())) != 0) { LOG_INFO("Image: %s", (*pH)->imageHeader->GetName().c_str()); lastImageName = (*pH)->imageHeader->GetName(); } LOG_INFO(" Partition %d: %s, Size: %d", index++, (*pH)->partition->section->Name.c_str(), (*pH)->GetPartitionSize()); } } /******************************************************************************/ void BootImage::ValidateOutputModes(File::Type split, OutputMode::Type outMode) { if(split != File::Unknown && outMode == OutputMode::OUT_SPLIT_SLAVEBOOT) { LOG_ERROR("Split & Split-Slave modes are mutually exclusive, cannot enable both modes"); } if(outMode == OutputMode::OUT_BITSTREAM && (outMode == OutputMode::OUT_SPLIT_SLAVEBOOT || outMode == OutputMode::OUT_SPLIT_NORMAL)) { LOG_ERROR("Process Bitstream & Split modes are mutually exclusive, cannot enable both modes"); } if(split != File::Unknown && outMode == OutputMode::OUT_BITSTREAM) { LOG_ERROR("Process Bitstream & Split mode are mutually exclusive, cannot enable both modes"); } } /******************************************************************************/ void BootImage::OutputPartitionFiles(Options& options, Binary& cache) { partitionOutput->GeneratePartitionFiles(*this, cache); } /******************************************************************************/ void BootImage::SetLegacyEncryptionFlag(bool flag) { legacyEncryptionEnabled = flag; } /******************************************************************************/ AuthHash::Type BootImage::GetAuthHashAlgo(void) { return authHash; } /******************************************************************************/ Core::Type BootImage::GetCore(void) { return core; } /******************************************************************************/ uint32_t BootImage::GetPmuFwSize(void) { return pmuFwSize; } /******************************************************************************/ uint32_t BootImage::GetFsblFwSize(void) { return fsblFwSize; } /******************************************************************************/ uint32_t BootImage::GetTotalPmuFwSize(void) { return totalPmuFwSize; } /******************************************************************************/ uint32_t BootImage::GetTotalFsblFwSize(void) { return totalFsblFwSize; } /******************************************************************************/ Binary::Address_t BootImage::GetFsblSourceAddr(void) { return sourceAddr; } /******************************************************************************/ bool BootImage::IsBootloaderFound() { return bootloaderFound; } /******************************************************************************/ void BootImage::SetCore(Core::Type type) { core = type; } /******************************************************************************/ void BootImage::SetPmuFwSize(uint32_t size) { pmuFwSize = size; } /******************************************************************************/ void BootImage::SetFsblFwSize(uint32_t size) { fsblFwSize = size; } /******************************************************************************/ void BootImage::SetTotalPmuFwSize(uint32_t size) { totalPmuFwSize = size; } /******************************************************************************/ void BootImage::SetTotalFsblFwSize(uint32_t size) { totalFsblFwSize = size; } /******************************************************************************/ void BootImage::SetFsblSourceAddr(Binary::Address_t addr) { sourceAddr = addr; } /******************************************************************************/ void BootImage::GenerateAuthenticationKeys(void) { if(options.GetAuthKeyGeneration() != GenAuthKeys::None) { keygen = new KeyGenerationStruct; keygen->format = options.GetAuthKeyGeneration(); keygen->ppk_file = bifOptions->GetPPKFileName(); keygen->psk_file = bifOptions->GetPSKFileName(); keygen->spk_file = bifOptions->GetSPKFileName(); keygen->ssk_file = bifOptions->GetSSKFileName(); keygen->keyLength = currentAuthCtx->GetRsaKeyLength(); if (keygen->format == GenAuthKeys::PEM || keygen->format == GenAuthKeys::RSA) { Key::GenerateRsaKeys(keygen); } else if (keygen->format == GenAuthKeys::ECDSA || keygen->format == GenAuthKeys::ECDSAP521) { if (options.archType != Arch::VERSAL) { LOG_ERROR("'-generate_keys ' is supported only with '-arch versal'."); } Key::GenerateEcdsaKeys(keygen); } } } /******************************************************************************/ void BootImage::GenerateGreyKey(void) { if (options.GetGreyKeyGeneration()) { currentEncryptCtx->GenerateGreyKey(); } } /******************************************************************************/ void BootImage::SetOutputSplitModeFormat(SplitMode::Type splitMode, File::Type fmt) { if(splitMode == SplitMode::Normal) { options.SetOutputMode(OutputMode::OUT_SPLIT_NORMAL, fmt); } else if (splitMode == SplitMode::SlaveMode) { options.SetOutputMode(OutputMode::OUT_SPLIT_SLAVEBOOT, fmt); } } /******************************************************************************/ void BootImage::SetOutputBitstreamModeFormat(File::Type type) { if(type != File::Unknown) { options.SetOutputMode(OutputMode::OUT_BITSTREAM, type); } } /******************************************************************************/ void BootImage::SetCoreFromDestCpu(DestinationCPU::Type coreType, A53ExecState::Type procType) { switch(coreType) { case DestinationCPU::A53_0: if (procType == A53ExecState::AARCH64) { SetCore(Core::A53Singlex64); } else { SetCore(Core::A53Singlex32); } break; case DestinationCPU::R5_0: SetCore(Core::R5Single); break; case DestinationCPU::R5_lockstep: SetCore(Core::R5Dual); break; case DestinationCPU::A53_1: case DestinationCPU::A53_2: case DestinationCPU::A53_3: case DestinationCPU::R5_1: case DestinationCPU::PMU: LOG_ERROR("FSBL can run from CPU A53-0 / R5-0 only. Please update destination_cpu accordingly."); break; default: case DestinationCPU::NONE: break; } } /******************************************************************************/ void BootImage::SetDestCpuFromCore(Core::Type coreType, DestinationCPU::Type cpuType) { if (cpuType == DestinationCPU::NONE) { switch (coreType) { case Core::A53Singlex64: case Core::A53Singlex32: { cpuType = DestinationCPU::A53_0; } break; case Core::R5Single: { cpuType = DestinationCPU::R5_0; } break; case Core::R5Dual: { cpuType = DestinationCPU::R5_lockstep; } break; } } } /******************************************************************************/ void BootImage::SetAssumeEncryptionFlag(bool flag) { assumeEncryption = flag; } /******************************************************************************/ std::vector& BootImage::GetEncryptionKeyFileVec() { return encryptionKeyFileVec; } /******************************************************************************/ void BootImage::InsertEncryptionKeyFile(std::string filename) { encryptionKeyFileVec.push_back(filename); } /******************************************************************************/ void BIF_File::ParseBifFile(Options& options) { std::string basefile = StringUtils::BaseName(biffilename); LOG_TRACE("Parsing BIF file - %s", basefile.c_str()); BIF::FlexScanner scanner; BIF::BisonParser parser(scanner, options); scanner.filename = biffilename; std::ifstream s(biffilename.c_str()); if (!s) { LOG_ERROR("Cannot read BIF file - %s ", basefile.c_str()); } if (s.peek() == EOF) { LOG_ERROR("BIF file is empty - %s ", basefile.c_str()); } scanner.switch_streams(&s); int res = parser.parse(); if (res) { LOG_ERROR("BIF file - %s, parsing failed with code %d", basefile.c_str(), res); } LOG_INFO("BIF file parsed successfully - %s ", basefile.c_str()); } /******************************************************************************/ void BIF_File::AppendAndReplaceFilesinBIF() { /* If slr number matches between partitions - replace the files */ for (size_t i = 0; i < includeBifOptionList.size(); i++) { for (size_t j = 0; j < bifOptionList.size(); j++) { for (std::list::iterator itr1 = bifOptionList[j]->partitionBifOptionList.begin(); itr1 != bifOptionList[j]->partitionBifOptionList.end(); itr1++) { if (includeBifOptionList[i]->slrNum == (*itr1)->slrNum) { if ((*itr1)->bootloader) { for (std::list::iterator itr2 = includeBifOptionList[i]->partitionBifOptionList.begin(); itr2 != includeBifOptionList[i]->partitionBifOptionList.end(); itr2++) { if ((*itr2)->bootloader) { if((*itr1)->slrNum != 0xFF) LOG_TRACE("Replacing '%s' with '%s' for SLR %d", (*itr2)->filename.c_str(), (*itr1)->filename.c_str(), (*itr1)->slrNum); else LOG_TRACE("Replacing '%s' with '%s'", (*itr2)->filename.c_str(), (*itr1)->filename.c_str()); (*itr2)->filename = (*itr1)->filename; (*itr2)->filelist = (*itr1)->filelist; (*itr1)->erasePartition = true; break; } } } if ((*itr1)->pmcData) { for (std::list::iterator itr2 = includeBifOptionList[i]->partitionBifOptionList.begin(); itr2 != includeBifOptionList[i]->partitionBifOptionList.end(); itr2++) { if ((*itr2)->pmcData) { if ((*itr1)->slrNum != 0xFF) LOG_TRACE("Replacing '%s' with '%s' for SLR %d", (*itr2)->filename.c_str(), (*itr1)->filename.c_str(), (*itr1)->slrNum); else LOG_TRACE("Replacing '%s' with '%s'", (*itr2)->filename.c_str(), (*itr1)->filename.c_str()); (*itr2)->filename = (*itr1)->filename; includeBifOptionList[i]->SetPmcdataFile((*itr1)->filename); (*itr2)->filelist = (*itr1)->filelist; includeBifOptionList[i]->ClearPmcCdoFileList(); for (size_t listSize = 0; listSize < (*itr1)->filelist.size(); listSize++) includeBifOptionList[i]->SetPmcCdoFileList((*itr1)->filelist[listSize]); (*itr1)->erasePartition = true; break; } } } if ((*itr1)->destCPUType == DestinationCPU::PMU) { for (std::list::iterator itr2 = includeBifOptionList[i]->partitionBifOptionList.begin(); itr2 != includeBifOptionList[i]->partitionBifOptionList.end(); itr2++) { if ((*itr2)->destCPUType == DestinationCPU::PMU) { if ((*itr1)->slrNum != 0xFF) LOG_TRACE("Replacing '%s' with '%s' for SLR %d", (*itr2)->filename.c_str(), (*itr1)->filename.c_str(), (*itr1)->slrNum); else LOG_TRACE("Replacing '%s' with '%s'", (*itr2)->filename.c_str(), (*itr1)->filename.c_str()); (*itr2)->filename = (*itr1)->filename; (*itr2)->filelist = (*itr1)->filelist; (*itr1)->erasePartition = true; break; } } } } } for (std::list::iterator itr1 = bifOptionList[j]->imageBifOptionList.begin(); itr1 != bifOptionList[j]->imageBifOptionList.end(); ) { bool incremented = false; for (std::list::iterator itr2 = (*itr1)->partitionBifOptionsList.begin(); itr2 != (*itr1)->partitionBifOptionsList.end(); ) { if ((*itr2)->erasePartition) { (*itr1)->partitionBifOptionsList.remove(*itr2++); if ((*itr1)->partitionBifOptionsList.size() == 0) { bifOptionList[j]->imageBifOptionList.remove(*itr1++); incremented = true; break; } //break; } else { itr2++; } } if(!incremented) itr1++; } } } for (size_t i = 0; i < includeBifOptionList.size(); i++) { if ((includeBifOptionList[i]->pdiType == PartitionType::SLR_CONFIG) || (includeBifOptionList[i]->slrNum == 0)) { for (size_t j = 0; j < bifOptionList.size(); j++) { for (std::list::iterator itr1 = bifOptionList[j]->imageBifOptionList.begin(); itr1 != bifOptionList[j]->imageBifOptionList.end(); itr1++) { std::list::iterator itr2 = (*itr1)->partitionBifOptionsList.begin(); { if (includeBifOptionList[i]->slrNum == (*itr2)->slrNum) { includeBifOptionList[i]->imageBifOptionList.push_back((*itr1)); includeBifOptionList[i]->partitionBifOptionList.insert(includeBifOptionList[i]->partitionBifOptionList.end(), (*itr1)->partitionBifOptionsList.begin(), (*itr1)->partitionBifOptionsList.end()); } } } } } else if(includeBifOptionList[i]->slrNum == 0xFF) { for (size_t j = 0; j < bifOptionList.size(); j++) { includeBifOptionList[i]->imageBifOptionList.splice(includeBifOptionList[i]->imageBifOptionList.end(), bifOptionList[j]->imageBifOptionList); } } } } xilinx-bootgen-2024.2/bootimage.h000077500000000000000000000150521475706442400167130ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _BOOTIMAGE_H_ #define _BOOTIMAGE_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "bootgenenum.h" #include "encryption.h" #include #include "binary.h" #include "checksum.h" #include "bootgenexception.h" #include "logger.h" #include "authkeys.h" #include "partitionheadertable.h" #include "imageheadertable-versal.h" #include "bifoptions.h" #define R5_TCM_START_ADDRESS 0x0000 #define R5_BTCM_START_ADDRESS 0x20000 #define R5_TCM_BANK_LENGTH 0x10000 #define PMU_RAM_END_ADDRESS 0xFFDDFFFF /* Forward class declarations */ class Options; class BifOptions; class PartitionBifOptions; class BootHeader; class ImageHeaderTable; class PartitionHeaderTable; class BootImage; class Partition; class ImageHeader; class ElfFormat; class Elf32ProgramHeader; class BitFile; class ByteFile; class ChecksumContext; class MD5ChecksumContext; class Key; class ChecksumTable; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class BIF_File { public: BIF_File(std::string& filename0) : biffilename(filename0) {} void Process(Options& options); void ParseBifFile(Options& options); void AppendAndReplaceFilesinBIF(); private: std::string biffilename; void Output(Options& options, uint8_t index); std::vector bifOptionList; std::vector includeBifOptionList; std::vector bootImages; }; /******************************************************************************/ class BootImage { public: BootImage(Options& options, uint8_t index); ~BootImage(); virtual void Add(BifOptions* bifoptions) { }; virtual void DetermineEncryptionDefaults() {}; virtual void ParseBootImage(PartitionBifOptions * it) = 0; virtual void ConfigureProcessingStages(ImageHeader* image, PartitionBifOptions* partitionbifoptions) = 0; virtual void OutputOptionalEfuseHash(); virtual void BuildAndLink(Binary* cache); void OutputPartitionFiles(Options& options, Binary& cache); void PrintPartitionInformation(void); void SetLegacyEncryptionFlag(bool flag); void GenerateAuthenticationKeys(void); void GenerateGreyKey(void); void SetOutputSplitModeFormat(SplitMode::Type splitMode, File::Type fmt); void ValidateOutputModes(File::Type split, OutputMode::Type outMode); bool IsBootloaderFound(); virtual void OutputOptionalSecureDebugImage() {}; void SetAssumeEncryptionFlag (bool); void SetCore (Core::Type); void SetPmuFwSize (uint32_t); void SetFsblFwSize (uint32_t); void SetTotalPmuFwSize (uint32_t); void SetTotalFsblFwSize (uint32_t); void SetFsblSourceAddr (Binary::Address_t); void SetOutputBitstreamModeFormat (File::Type); void SetCoreFromDestCpu (DestinationCPU::Type type, A53ExecState::Type procType); void SetDestCpuFromCore(Core::Type coreType, DestinationCPU::Type cpuType); static std::vector encryptionKeyFileVec; std::vector& GetEncryptionKeyFileVec(); void InsertEncryptionKeyFile(std::string filename); std::vector> aesKeyandKeySrc; Core::Type GetCore(void); uint32_t GetPmuFwSize (void); uint32_t GetFsblFwSize (void); uint32_t GetTotalPmuFwSize (void); uint32_t GetTotalFsblFwSize (void); Binary::Address_t GetFsblSourceAddr (void); AuthHash::Type GetAuthHashAlgo(void); std::string Name; BootHeader* bootHeader; std::list headers; Section* encryptedHeaders; ImageHeaderTable* imageHeaderTable; std::list imageList; std::list subSysImageList; PartitionHeaderTable* partitionHeaderTable; std::list partitionHeaderList; Section* nullPartHeaderSection; ChecksumTable* checksumTable; AuthenticationCertificate* headerAC; AuthenticationContext* currentAuthCtx; AuthenticationContext* metaHdrAuthCtx; EncryptionContext* currentEncryptCtx; MD5ChecksumContext* currentChecksumCtx; Hash* hash; Options& options; BifOptions* bifOptions; KeyGenerationStruct* keygen; PartitionOutput* partitionOutput; bool headerSignature_Loaded; bool XipMode; uint32_t totalHeadersSize; uint32_t partCount; Binary* cache; bool createSubSystemPdis; bool convertAieElfToCdo; std::string fsblFilename; std::string bitFilename; void * overlayCDO; virtual uint64_t GetSecureChunkSize(bool isBootloader) { return 0; } std::vector sync_offsets; //private: bool assumeEncryption; uint32_t* deviceKey; uint32_t* firstIv; uint32_t* firstOptKey; Core::Type core; AuthHash::Type authHash; uint32_t pmuFwSize; uint32_t fsblFwSize; uint32_t totalPmuFwSize; uint32_t totalFsblFwSize; Binary::Address_t sourceAddr; bool legacyEncryptionEnabled; bool bootloaderFound; bool bootloaderEncrypt; KeySource::Type bootloaderKeySource; bool bootloaderAuthenticate; uint32_t xplm_modules_data_length; uint32_t* xplm_modules_data; char globalSlrId; bool authOnPartitionFound; uint32_t* iht_optional_data; uint32_t iht_optional_data_length; uint32_t copied_iht_optional_data_length; std::vector> hashTable; uint32_t numHashTableEntries; std::string pmcDataAesFile; }; #endif xilinx-bootgen-2024.2/cJSON.c000077500000000000000000002021141475706442400156510ustar00rootroot00000000000000/* Copyright (c) 2009-2017 Dave Gamble and cJSON contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* cJSON */ /* JSON parser in C. */ #ifdef __GNUC__ #pragma GCC visibility push(default) #endif #include #include #include #include #include #include #include #include #ifdef __GNUC__ #pragma GCC visibility pop #endif #include "cJSON.h" /* define our own boolean type */ #define true ((cJSON_bool)1) #define false ((cJSON_bool)0) typedef struct { const unsigned char *json; size_t position; } error; static error global_error = { NULL, 0 }; CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { return (const char*) (global_error.json + global_error.position); } /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 2) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif CJSON_PUBLIC(const char*) cJSON_Version(void) { static char version[15]; sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); return version; } /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { if ((string1 == NULL) || (string2 == NULL)) { return 1; } if (string1 == string2) { return 0; } for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { if (*string1 == '\0') { return 0; } } return tolower(*string1) - tolower(*string2); } typedef struct internal_hooks { void *(*allocate)(size_t size); void (*deallocate)(void *pointer); void *(*reallocate)(void *pointer, size_t size); } internal_hooks; static internal_hooks global_hooks = { malloc, free, realloc }; static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) { size_t length = 0; unsigned char *copy = NULL; if (string == NULL) { return NULL; } length = strlen((const char*)string) + sizeof(""); if (!(copy = (unsigned char*)hooks->allocate(length))) { return NULL; } memcpy(copy, string, length); return copy; } CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) { if (hooks == NULL) { /* Reset hooks */ global_hooks.allocate = malloc; global_hooks.deallocate = free; global_hooks.reallocate = realloc; return; } global_hooks.allocate = malloc; if (hooks->malloc_fn != NULL) { global_hooks.allocate = hooks->malloc_fn; } global_hooks.deallocate = free; if (hooks->free_fn != NULL) { global_hooks.deallocate = hooks->free_fn; } /* use realloc only if both free and malloc are used */ global_hooks.reallocate = NULL; if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { global_hooks.reallocate = realloc; } } /* Internal constructor. */ static cJSON *cJSON_New_Item(const internal_hooks * const hooks) { cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); if (node) { memset(node, '\0', sizeof(cJSON)); } return node; } /* Delete a cJSON structure. */ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { cJSON *next = NULL; while (item != NULL) { next = item->next; if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); } if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); } if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { global_hooks.deallocate(item->string); } global_hooks.deallocate(item); item = next; } } /* get the decimal point character of the current locale */ static unsigned char get_decimal_point(void) { struct lconv *lconv = localeconv(); return (unsigned char) lconv->decimal_point[0]; } typedef struct { const unsigned char *content; size_t length; size_t offset; size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ internal_hooks hooks; } parse_buffer; /* check if the given size is left to read in a given parse buffer (starting with 1) */ #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) #define cannot_read(buffer, size) (!can_read(buffer, size)) /* check if the buffer can be accessed at the given index (starting with 0) */ #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) /* get a pointer to the buffer at the position */ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) /* Parse the input text to generate a number, and populate the result into item. */ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) { double number = 0; unsigned char *after_end = NULL; unsigned char number_c_string[64]; unsigned char decimal_point = get_decimal_point(); size_t i = 0; if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; } /* copy the number into a temporary buffer and replace '.' with the decimal point * of the current locale (for strtod) * This also takes care of '\0' not necessarily being available for marking the end of the input */ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { switch (buffer_at_offset(input_buffer)[i]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': case 'e': case 'E': number_c_string[i] = buffer_at_offset(input_buffer)[i]; break; case '.': number_c_string[i] = decimal_point; break; default: goto loop_end; } } loop_end: number_c_string[i] = '\0'; number = strtod((const char*)number_c_string, (char**)&after_end); if (number_c_string == after_end) { return false; /* parse_error */ } item->valuedouble = number; /* use saturation in case of overflow */ if (number >= INT_MAX) { item->valueint = INT_MAX; } else if (number <= INT_MIN) { item->valueint = INT_MIN; } else { item->valueint = (int)number; } item->type = cJSON_Number; input_buffer->offset += (size_t)(after_end - number_c_string); return true; } /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) { if (number >= INT_MAX) { object->valueint = INT_MAX; } else if (number <= INT_MIN) { object->valueint = INT_MIN; } else { object->valueint = (int)number; } return object->valuedouble = number; } typedef struct { unsigned char *buffer; size_t length; size_t offset; size_t depth; /* current nesting depth (for formatted printing) */ cJSON_bool noalloc; cJSON_bool format; /* is this print a formatted print */ internal_hooks hooks; } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ static unsigned char* ensure(printbuffer * const p, size_t needed) { unsigned char *newbuffer = NULL; size_t newsize = 0; if ((p == NULL) || (p->buffer == NULL)) { return NULL; } if ((p->length > 0) && (p->offset >= p->length)) { /* make sure that offset is valid */ return NULL; } if (needed > INT_MAX) { /* sizes bigger than INT_MAX are currently not supported */ return NULL; } needed += p->offset + 1; if (needed <= p->length) { return p->buffer + p->offset; } if (p->noalloc) { return NULL; } /* calculate new buffer size */ if (needed > (INT_MAX / 2)) { /* overflow of int, use INT_MAX if possible */ if (needed <= INT_MAX) { newsize = INT_MAX; } else { return NULL; } } else { newsize = needed * 2; } if (p->hooks.reallocate != NULL) { /* reallocate with realloc if available */ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); } else { /* otherwise reallocate manually */ newbuffer = (unsigned char*)p->hooks.allocate(newsize); if (!newbuffer) { p->hooks.deallocate(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } if (newbuffer) { memcpy(newbuffer, p->buffer, p->offset + 1); } p->hooks.deallocate(p->buffer); } p->length = newsize; p->buffer = newbuffer; return newbuffer + p->offset; } /* calculate the new length of the string in a printbuffer and update the offset */ static void update_offset(printbuffer * const buffer) { const unsigned char *buffer_pointer = NULL; if ((buffer == NULL) || (buffer->buffer == NULL)) { return; } buffer_pointer = buffer->buffer + buffer->offset; buffer->offset += strlen((const char*)buffer_pointer); } /* Render the number nicely from the given item into a string. */ static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) { unsigned char *output_pointer = NULL; double d = item->valuedouble; int length = 0; size_t i = 0; unsigned char number_buffer[26]; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); double test; if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ if ((d * 0) != 0) { length = sprintf((char*)number_buffer, "null"); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ length = sprintf((char*)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) { /* If not, print with 17 decimal places of precision */ length = sprintf((char*)number_buffer, "%1.17g", d); } } /* sprintf failed or buffer overrun occured */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } /* reserve appropriate space in the output */ output_pointer = ensure(output_buffer, (size_t)length); if (output_pointer == NULL) { return false; } /* copy the printed number to the output and replace locale * dependent decimal point with '.' */ for (i = 0; i < ((size_t)length); i++) { if (number_buffer[i] == decimal_point) { output_pointer[i] = '.'; continue; } output_pointer[i] = number_buffer[i]; } output_pointer[i] = '\0'; output_buffer->offset += (size_t)length; return true; } /* parse 4 digit hexadecimal number */ static unsigned parse_hex4(const unsigned char * const input) { unsigned int h = 0; size_t i = 0; for (i = 0; i < 4; i++) { /* parse digit */ if ((input[i] >= '0') && (input[i] <= '9')) { h += (unsigned int) input[i] - '0'; } else if ((input[i] >= 'A') && (input[i] <= 'F')) { h += (unsigned int) 10 + input[i] - 'A'; } else if ((input[i] >= 'a') && (input[i] <= 'f')) { h += (unsigned int) 10 + input[i] - 'a'; } else /* invalid */ { return 0; } if (i < 3) { /* shift left to make place for the next nibble */ h = h << 4; } } return h; } /* converts a UTF-16 literal to UTF-8 * A literal can be one or two sequences of the form \uXXXX */ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) { long unsigned int codepoint = 0; unsigned int first_code = 0; const unsigned char *first_sequence = input_pointer; unsigned char utf8_length = 0; unsigned char utf8_position = 0; unsigned char sequence_length = 0; unsigned char first_byte_mark = 0; if ((input_end - first_sequence) < 6) { /* input ends unexpectedly */ goto fail; } /* get the first utf16 sequence */ first_code = parse_hex4(first_sequence + 2); /* check that the code is valid */ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { goto fail; } /* UTF16 surrogate pair */ if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { const unsigned char *second_sequence = first_sequence + 6; unsigned int second_code = 0; sequence_length = 12; /* \uXXXX\uXXXX */ if ((input_end - second_sequence) < 6) { /* input ends unexpectedly */ goto fail; } if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { /* missing second half of the surrogate pair */ goto fail; } /* get the second utf16 sequence */ second_code = parse_hex4(second_sequence + 2); /* check that the code is valid */ if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { /* invalid second half of the surrogate pair */ goto fail; } /* calculate the unicode codepoint from the surrogate pair */ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); } else { sequence_length = 6; /* \uXXXX */ codepoint = first_code; } /* encode as UTF-8 * takes at maximum 4 bytes to encode: * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (codepoint < 0x80) { /* normal ascii, encoding 0xxxxxxx */ utf8_length = 1; } else if (codepoint < 0x800) { /* two bytes, encoding 110xxxxx 10xxxxxx */ utf8_length = 2; first_byte_mark = 0xC0; /* 11000000 */ } else if (codepoint < 0x10000) { /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ utf8_length = 3; first_byte_mark = 0xE0; /* 11100000 */ } else if (codepoint <= 0x10FFFF) { /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ utf8_length = 4; first_byte_mark = 0xF0; /* 11110000 */ } else { /* invalid unicode codepoint */ goto fail; } /* encode as utf8 */ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { /* 10xxxxxx */ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); codepoint >>= 6; } /* encode first byte */ if (utf8_length > 1) { (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); } else { (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); } *output_pointer += utf8_length; return sequence_length; fail: return 0; } /* Parse the input text into an unescaped cinput, and populate item. */ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) { const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; unsigned char *output_pointer = NULL; unsigned char *output = NULL; /* not a string */ if (buffer_at_offset(input_buffer)[0] != '\"') { goto fail; } { /* calculate approximate size of the output (overestimate) */ size_t allocation_length = 0; size_t skipped_bytes = 0; while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { /* is escape sequence */ if (input_end[0] == '\\') { if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { /* prevent buffer overflow when last input character is a backslash */ goto fail; } skipped_bytes++; input_end++; } input_end++; } if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); if (output == NULL) { goto fail; /* allocation failure */ } } output_pointer = output; /* loop through the string literal */ while (input_pointer < input_end) { if (*input_pointer != '\\') { *output_pointer++ = *input_pointer++; } /* escape sequence */ else { unsigned char sequence_length = 2; if ((input_end - input_pointer) < 1) { goto fail; } switch (input_pointer[1]) { case 'b': *output_pointer++ = '\b'; break; case 'f': *output_pointer++ = '\f'; break; case 'n': *output_pointer++ = '\n'; break; case 'r': *output_pointer++ = '\r'; break; case 't': *output_pointer++ = '\t'; break; case '\"': case '\\': case '/': *output_pointer++ = input_pointer[1]; break; /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); if (sequence_length == 0) { /* failed to convert UTF16-literal to UTF-8 */ goto fail; } break; default: goto fail; } input_pointer += sequence_length; } } /* zero terminate the output */ *output_pointer = '\0'; item->type = cJSON_String; item->valuestring = (char*)output; input_buffer->offset = (size_t) (input_end - input_buffer->content); input_buffer->offset++; return true; fail: if (output != NULL) { input_buffer->hooks.deallocate(output); } if (input_pointer != NULL) { input_buffer->offset = (size_t)(input_pointer - input_buffer->content); } return false; } /* Render the cstring provided to an escaped version that can be printed. */ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) { const unsigned char *input_pointer = NULL; unsigned char *output = NULL; unsigned char *output_pointer = NULL; size_t output_length = 0; /* numbers of additional characters needed for escaping */ size_t escape_characters = 0; if (output_buffer == NULL) { return false; } /* empty string */ if (input == NULL) { output = ensure(output_buffer, sizeof("\"\"")); if (output == NULL) { return false; } strcpy((char*)output, "\"\""); return true; } /* set "flag" to 1 if something needs to be escaped */ for (input_pointer = input; *input_pointer; input_pointer++) { switch (*input_pointer) { case '\"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': /* one character escape sequence */ escape_characters++; break; default: if (*input_pointer < 32) { /* UTF-16 escape sequence uXXXX */ escape_characters += 5; } break; } } output_length = (size_t)(input_pointer - input) + escape_characters; output = ensure(output_buffer, output_length + sizeof("\"\"")); if (output == NULL) { return false; } /* no characters have to be escaped */ if (escape_characters == 0) { output[0] = '\"'; memcpy(output + 1, input, output_length); output[output_length + 1] = '\"'; output[output_length + 2] = '\0'; return true; } output[0] = '\"'; output_pointer = output + 1; /* copy the string */ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { /* normal character, copy */ *output_pointer = *input_pointer; } else { /* character needs to be escaped */ *output_pointer++ = '\\'; switch (*input_pointer) { case '\\': *output_pointer = '\\'; break; case '\"': *output_pointer = '\"'; break; case '\b': *output_pointer = 'b'; break; case '\f': *output_pointer = 'f'; break; case '\n': *output_pointer = 'n'; break; case '\r': *output_pointer = 'r'; break; case '\t': *output_pointer = 't'; break; default: /* escape and print as unicode codepoint */ sprintf((char*)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } } } output[output_length + 1] = '\"'; output[output_length + 2] = '\0'; return true; } /* Invoke print_string_ptr (which is useful) on an item. */ static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) { return print_string_ptr((unsigned char*)item->valuestring, p); } /* Predeclare these prototypes. */ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); /* Utility to jump whitespace and cr/lf */ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) { if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; } while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; } if (buffer->offset == buffer->length) { buffer->offset--; } return buffer; } /* Parse an object - create a new root, and populate. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; /* reset error position */ global_error.json = NULL; global_error.position = 0; if (value == NULL) { goto fail; } buffer.content = (const unsigned char*)value; buffer.length = strlen((const char*)value) + sizeof(""); buffer.offset = 0; buffer.hooks = global_hooks; item = cJSON_New_Item(&global_hooks); if (item == NULL) /* memory fail */ { goto fail; } if (!parse_value(item, buffer_skip_whitespace(&buffer))) { /* parse failure. ep is set. */ goto fail; } /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ if (require_null_terminated) { buffer_skip_whitespace(&buffer); if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { goto fail; } } if (return_parse_end) { *return_parse_end = (const char*)buffer_at_offset(&buffer); } return item; fail: if (item != NULL) { cJSON_Delete(item); } if (value != NULL) { error local_error; local_error.json = (const unsigned char*)value; local_error.position = 0; if (buffer.offset < buffer.length) { local_error.position = buffer.offset; } else if (buffer.length > 0) { local_error.position = buffer.length - 1; } if (return_parse_end != NULL) { *return_parse_end = (const char*)local_error.json + local_error.position; } else { global_error = local_error; } } return NULL; } /* Default options for cJSON_Parse */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) { return cJSON_ParseWithOpts(value, 0, 0); } #define cjson_min(a, b) ((a < b) ? a : b) static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) { printbuffer buffer[1]; unsigned char *printed = NULL; memset(buffer, 0, sizeof(buffer)); /* create buffer */ buffer->buffer = (unsigned char*) hooks->allocate(256); buffer->format = format; buffer->hooks = *hooks; if (buffer->buffer == NULL) { goto fail; } /* print the value */ if (!print_value(item, buffer)) { goto fail; } update_offset(buffer); /* check if reallocate is available */ if (hooks->reallocate != NULL) { printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length); buffer->buffer = NULL; if (printed == NULL) { goto fail; } } else /* otherwise copy the JSON over to a new buffer */ { printed = (unsigned char*) hooks->allocate(buffer->offset + 1); if (printed == NULL) { goto fail; } memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); printed[buffer->offset] = '\0'; /* just to be sure */ /* free the buffer */ hooks->deallocate(buffer->buffer); } return printed; fail: if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); } if (printed != NULL) { hooks->deallocate(printed); } return NULL; } /* Render a cJSON item/entity/structure to text. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) { return (char*)print(item, true, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) { return (char*)print(item, false, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; if (prebuffer < 0) { return NULL; } p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); if (!p.buffer) { return NULL; } p.length = (size_t)prebuffer; p.offset = 0; p.noalloc = false; p.format = fmt; p.hooks = global_hooks; if (!print_value(item, &p)) { return NULL; } return (char*)p.buffer; } CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; if (len < 0) { return false; } p.buffer = (unsigned char*)buf; p.length = (size_t)len; p.offset = 0; p.noalloc = true; p.format = fmt; p.hooks = global_hooks; return print_value(item, &p); } /* Parser core - when encountering text, process appropriately. */ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) { if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; /* no input */ } /* parse the different types of values */ /* null */ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) { item->type = cJSON_NULL; input_buffer->offset += 4; return true; } /* false */ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) { item->type = cJSON_False; input_buffer->offset += 5; return true; } /* true */ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) { item->type = cJSON_True; item->valueint = 1; input_buffer->offset += 4; return true; } /* string */ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); } /* number */ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { return parse_number(item, input_buffer); } /* array */ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { return parse_array(item, input_buffer); } /* object */ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); } return false; } /* Render a value to text. */ static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) { unsigned char *output = NULL; if ((item == NULL) || (output_buffer == NULL)) { return false; } switch ((item->type) & 0xFF) { case cJSON_NULL: output = ensure(output_buffer, 5); if (output == NULL) { return false; } strcpy((char*)output, "null"); return true; case cJSON_False: output = ensure(output_buffer, 6); if (output == NULL) { return false; } strcpy((char*)output, "false"); return true; case cJSON_True: output = ensure(output_buffer, 5); if (output == NULL) { return false; } strcpy((char*)output, "true"); return true; case cJSON_Number: return print_number(item, output_buffer); case cJSON_Raw: { size_t raw_length = 0; if (item->valuestring == NULL) { if (!output_buffer->noalloc) { output_buffer->hooks.deallocate(output_buffer->buffer); } return false; } raw_length = strlen(item->valuestring) + sizeof(""); output = ensure(output_buffer, raw_length); if (output == NULL) { return false; } memcpy(output, item->valuestring, raw_length); return true; } case cJSON_String: return print_string(item, output_buffer); case cJSON_Array: return print_array(item, output_buffer); case cJSON_Object: return print_object(item, output_buffer); default: return false; } } /* Build an array from input text. */ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) { cJSON *head = NULL; /* head of the linked list */ cJSON *current_item = NULL; if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; if (buffer_at_offset(input_buffer)[0] != '[') { /* not an array */ goto fail; } input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { /* empty array */ goto success; } /* check if we skipped to the end of the buffer */ if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ if (head == NULL) { /* start the linked list */ current_item = head = new_item; } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; current_item = new_item; } /* parse next value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { goto fail; /* expected end of array */ } success: input_buffer->depth--; item->type = cJSON_Array; item->child = head; input_buffer->offset++; return true; fail: if (head != NULL) { cJSON_Delete(head); } return false; } /* Render an array to text */ static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_element = item->child; if (output_buffer == NULL) { return false; } /* Compose the output array. */ /* opening square bracket */ output_pointer = ensure(output_buffer, 1); if (output_pointer == NULL) { return false; } *output_pointer = '['; output_buffer->offset++; output_buffer->depth++; while (current_element != NULL) { if (!print_value(current_element, output_buffer)) { return false; } update_offset(output_buffer); if (current_element->next) { length = (size_t) (output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length + 1); if (output_pointer == NULL) { return false; } *output_pointer++ = ','; if(output_buffer->format) { *output_pointer++ = ' '; } *output_pointer = '\0'; output_buffer->offset += length; } current_element = current_element->next; } output_pointer = ensure(output_buffer, 2); if (output_pointer == NULL) { return false; } *output_pointer++ = ']'; *output_pointer = '\0'; output_buffer->depth--; return true; } /* Build an object from the text. */ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) { cJSON *head = NULL; /* linked list head */ cJSON *current_item = NULL; if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ if (head == NULL) { /* start the linked list */ current_item = head = new_item; } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; current_item = new_item; } /* parse the name of the child */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_string(current_item, input_buffer)) { goto fail; /* faile to parse name */ } buffer_skip_whitespace(input_buffer); /* swap valuestring and string, because we parsed the name */ current_item->string = current_item->valuestring; current_item->valuestring = NULL; if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { goto fail; /* expected end of object */ } success: input_buffer->depth--; item->type = cJSON_Object; item->child = head; input_buffer->offset++; return true; fail: if (head != NULL) { cJSON_Delete(head); } return false; } /* Render an object to text. */ static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_item = item->child; if (output_buffer == NULL) { return false; } /* Compose the output: */ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ output_pointer = ensure(output_buffer, length + 1); if (output_pointer == NULL) { return false; } *output_pointer++ = '{'; output_buffer->depth++; if (output_buffer->format) { *output_pointer++ = '\n'; } output_buffer->offset += length; while (current_item) { if (output_buffer->format) { size_t i; output_pointer = ensure(output_buffer, output_buffer->depth); if (output_pointer == NULL) { return false; } for (i = 0; i < output_buffer->depth; i++) { *output_pointer++ = '\t'; } output_buffer->offset += output_buffer->depth; } /* print key */ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) { return false; } update_offset(output_buffer); length = (size_t) (output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length); if (output_pointer == NULL) { return false; } *output_pointer++ = ':'; if (output_buffer->format) { *output_pointer++ = '\t'; } output_buffer->offset += length; /* print value */ if (!print_value(current_item, output_buffer)) { return false; } update_offset(output_buffer); /* print comma if not last */ length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); output_pointer = ensure(output_buffer, length + 1); if (output_pointer == NULL) { return false; } if (current_item->next) { *output_pointer++ = ','; } if (output_buffer->format) { *output_pointer++ = '\n'; } *output_pointer = '\0'; output_buffer->offset += length; current_item = current_item->next; } output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); if (output_pointer == NULL) { return false; } if (output_buffer->format) { size_t i; for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; } } *output_pointer++ = '}'; *output_pointer = '\0'; output_buffer->depth--; return true; } /* Get Array size/item / object item. */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) { cJSON *c = array->child; size_t i = 0; while(c) { i++; c = c->next; } /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ return (int)i; } static cJSON* get_array_item(const cJSON *array, size_t index) { cJSON *current_child = NULL; if (array == NULL) { return NULL; } current_child = array->child; while ((current_child != NULL) && (index > 0)) { index--; current_child = current_child->next; } return current_child; } CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) { if (index < 0) { return NULL; } return get_array_item(array, (size_t)index); } static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) { cJSON *current_element = NULL; if ((object == NULL) || (name == NULL)) { return NULL; } current_element = object->child; if (case_sensitive) { while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; } } else { while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) { current_element = current_element->next; } } return current_element; } CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) { return get_object_item(object, string, false); } CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) { return get_object_item(object, string, true); } CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) { return cJSON_GetObjectItem(object, string) ? 1 : 0; } /* Utility for array list handling. */ static void suffix_object(cJSON *prev, cJSON *item) { prev->next = item; item->prev = prev; } /* Utility for handling references. */ static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) { cJSON *ref = cJSON_New_Item(hooks); if (!ref) { return NULL; } memcpy(ref, item, sizeof(cJSON)); ref->string = NULL; ref->type |= cJSON_IsReference; ref->next = ref->prev = NULL; return ref; } /* Add item to array/object. */ CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) { cJSON *child = NULL; if ((item == NULL) || (array == NULL)) { return; } child = array->child; if (child == NULL) { /* list is empty, start new one */ array->child = item; } else { /* append to the end */ while (child->next) { child = child->next; } suffix_object(child, item); } } CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) { /* call cJSON_AddItemToObjectCS for code reuse */ cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item); /* remove cJSON_StringIsConst flag */ item->type &= ~cJSON_StringIsConst; } #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) #pragma GCC diagnostic push #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wcast-qual" #endif /* Add an item to an object with constant string as key */ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) { if (!item) { return; } if (!(item->type & cJSON_StringIsConst) && item->string) { global_hooks.deallocate(item->string); } item->string = (char*)string; item->type |= cJSON_StringIsConst; cJSON_AddItemToArray(object, item); } #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) #pragma GCC diagnostic pop #endif CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { cJSON_AddItemToArray(array, create_reference(item, &global_hooks)); } CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) { cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks)); } CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) { if ((parent == NULL) || (item == NULL)) { return NULL; } if (item->prev != NULL) { /* not the first element */ item->prev->next = item->next; } if (item->next != NULL) { /* not the last element */ item->next->prev = item->prev; } if (item == parent->child) { /* first element */ parent->child = item->next; } /* make sure the detached item doesn't point anywhere anymore */ item->prev = NULL; item->next = NULL; return item; } CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) { if (which < 0) { return NULL; } return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); } CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) { cJSON_Delete(cJSON_DetachItemFromArray(array, which)); } CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) { cJSON *to_detach = cJSON_GetObjectItem(object, string); return cJSON_DetachItemViaPointer(object, to_detach); } CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) { cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); return cJSON_DetachItemViaPointer(object, to_detach); } CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) { cJSON_Delete(cJSON_DetachItemFromObject(object, string)); } CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) { cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); } /* Replace array/object items with new ones. */ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) { cJSON *after_inserted = NULL; if (which < 0) { return; } after_inserted = get_array_item(array, (size_t)which); if (after_inserted == NULL) { cJSON_AddItemToArray(array, newitem); return; } newitem->next = after_inserted; newitem->prev = after_inserted->prev; after_inserted->prev = newitem; if (after_inserted == array->child) { array->child = newitem; } else { newitem->prev->next = newitem; } } CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) { if ((parent == NULL) || (replacement == NULL)) { return false; } if (replacement == item) { return true; } replacement->next = item->next; replacement->prev = item->prev; if (replacement->next != NULL) { replacement->next->prev = replacement; } if (replacement->prev != NULL) { replacement->prev->next = replacement; } if (parent->child == item) { parent->child = replacement; } item->next = NULL; item->prev = NULL; cJSON_Delete(item); return true; } CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { if (which < 0) { return; } cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); } CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItem(object, string), newitem); } CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) { cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItemCaseSensitive(object, string), newitem); } /* Create basic types: */ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_NULL; } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_True; } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_False; } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = b ? cJSON_True : cJSON_False; } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_Number; item->valuedouble = num; /* use saturation in case of overflow */ if (num >= INT_MAX) { item->valueint = INT_MAX; } else if (num <= INT_MIN) { item->valueint = INT_MIN; } else { item->valueint = (int)num; } } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_String; item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); if(!item->valuestring) { cJSON_Delete(item); return NULL; } } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type = cJSON_Raw; item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); if(!item->valuestring) { cJSON_Delete(item); return NULL; } } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { cJSON *item = cJSON_New_Item(&global_hooks); if(item) { item->type=cJSON_Array; } return item; } CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { cJSON *item = cJSON_New_Item(&global_hooks); if (item) { item->type = cJSON_Object; } return item; } /* Create Arrays: */ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) { size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; cJSON *a = NULL; if (count < 0) { return NULL; } a = cJSON_CreateArray(); for(i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if (!n) { cJSON_Delete(a); return NULL; } if(!i) { a->child = n; } else { suffix_object(p, n); } p = n; } return a; } CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) { size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; cJSON *a = NULL; if (count < 0) { return NULL; } a = cJSON_CreateArray(); for(i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber((double)numbers[i]); if(!n) { cJSON_Delete(a); return NULL; } if(!i) { a->child = n; } else { suffix_object(p, n); } p = n; } return a; } CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) { size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; cJSON *a = NULL; if (count < 0) { return NULL; } a = cJSON_CreateArray(); for(i = 0;a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if(!n) { cJSON_Delete(a); return NULL; } if(!i) { a->child = n; } else { suffix_object(p, n); } p = n; } return a; } CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) { size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; cJSON *a = NULL; if (count < 0) { return NULL; } a = cJSON_CreateArray(); for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateString(strings[i]); if(!n) { cJSON_Delete(a); return NULL; } if(!i) { a->child = n; } else { suffix_object(p,n); } p = n; } return a; } /* Duplication */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) { cJSON *newitem = NULL; cJSON *child = NULL; cJSON *next = NULL; cJSON *newchild = NULL; /* Bail on bad ptr */ if (!item) { goto fail; } /* Create new item */ newitem = cJSON_New_Item(&global_hooks); if (!newitem) { goto fail; } /* Copy over all vars */ newitem->type = item->type & (~cJSON_IsReference); newitem->valueint = item->valueint; newitem->valuedouble = item->valuedouble; if (item->valuestring) { newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); if (!newitem->valuestring) { goto fail; } } if (item->string) { newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); if (!newitem->string) { goto fail; } } /* If non-recursive, then we're done! */ if (!recurse) { return newitem; } /* Walk the ->next chain for the child. */ child = item->child; while (child != NULL) { newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ if (!newchild) { goto fail; } if (next != NULL) { /* If newitem->child already set, then crosswire ->prev and ->next and move on */ next->next = newchild; newchild->prev = next; next = newchild; } else { /* Set newitem->child and move to it */ newitem->child = newchild; next = newchild; } child = child->next; } return newitem; fail: if (newitem != NULL) { cJSON_Delete(newitem); } return NULL; } CJSON_PUBLIC(void) cJSON_Minify(char *json) { unsigned char *into = (unsigned char*)json; while (*json) { if (*json == ' ') { json++; } else if (*json == '\t') { /* Whitespace characters. */ json++; } else if (*json == '\r') { json++; } else if (*json=='\n') { json++; } else if ((*json == '/') && (json[1] == '/')) { /* double-slash comments, to end of line. */ while (*json && (*json != '\n')) { json++; } } else if ((*json == '/') && (json[1] == '*')) { /* multiline comments. */ while (*json && !((*json == '*') && (json[1] == '/'))) { json++; } json += 2; } else if (*json == '\"') { /* string literals, which are \" sensitive. */ *into++ = (unsigned char)*json++; while (*json && (*json != '\"')) { if (*json == '\\') { *into++ = (unsigned char)*json++; } *into++ = (unsigned char)*json++; } *into++ = (unsigned char)*json++; } else { /* All other characters. */ *into++ = (unsigned char)*json++; } } /* and null-terminate. */ *into = '\0'; } CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Invalid; } CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_False; } CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xff) == cJSON_True; } CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & (cJSON_True | cJSON_False)) != 0; } CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_NULL; } CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Number; } CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_String; } CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Array; } CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Object; } CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) { if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Raw; } CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) { if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) { return false; } /* check if type is valid */ switch (a->type & 0xFF) { case cJSON_False: case cJSON_True: case cJSON_NULL: case cJSON_Number: case cJSON_String: case cJSON_Raw: case cJSON_Array: case cJSON_Object: break; default: return false; } /* identical objects are equal */ if (a == b) { return true; } switch (a->type & 0xFF) { /* in these cases and equal type is enough */ case cJSON_False: case cJSON_True: case cJSON_NULL: return true; case cJSON_Number: if (a->valuedouble == b->valuedouble) { return true; } return false; case cJSON_String: case cJSON_Raw: if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; } if (strcmp(a->valuestring, b->valuestring) == 0) { return true; } return false; case cJSON_Array: { cJSON *a_element = a->child; cJSON *b_element = b->child; for (; (a_element != NULL) && (b_element != NULL);) { if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } a_element = a_element->next; b_element = b_element->next; } return true; } case cJSON_Object: { cJSON *a_element = NULL; cJSON_ArrayForEach(a_element, a) { /* TODO This has O(n^2) runtime, which is horrible! */ cJSON *b_element = get_object_item(b, a_element->string, case_sensitive); if (b_element == NULL) { return false; } if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } } return true; } default: return false; } } CJSON_PUBLIC(void *) cJSON_malloc(size_t size) { return global_hooks.allocate(size); } CJSON_PUBLIC(void) cJSON_free(void *object) { global_hooks.deallocate(object); } char* read_file(const char *filename) { FILE *file = NULL; long length = 0; char *content = NULL; size_t read_chars = 0; /* open in read binary mode */ file = fopen(filename, "rb"); if (file == NULL) { goto cleanup; } /* get the length */ if (fseek(file, 0, SEEK_END) != 0) { goto cleanup; } length = ftell(file); if (length < 0) { goto cleanup; } if (fseek(file, 0, SEEK_SET) != 0) { goto cleanup; } /* allocate content buffer */ content = (char*)malloc((size_t)length + sizeof("")); if (content == NULL) { goto cleanup; } /* read the file into memory */ read_chars = fread(content, sizeof(char), (size_t)length, file); if ((long)read_chars != length) { free(content); content = NULL; goto cleanup; } content[read_chars] = '\0'; cleanup: if (file != NULL) { fclose(file); } return content; } cJSON *parse_file(const char * filename) { char *file = NULL; cJSON *json = NULL; file = read_file(filename); //TEST_ASSERT_NOT_NULL_MESSAGE(file, "Failed to read file."); json = cJSON_Parse(file); //TEST_ASSERT_NOT_NULL_MESSAGE(json, "Failed to parse test json."); //TEST_ASSERT_TRUE_MESSAGE(cJSON_IsArray(json), "Json is not an array."); free(file); return json; } xilinx-bootgen-2024.2/cJSON.h000077500000000000000000000327011475706442400156610ustar00rootroot00000000000000/* Copyright (c) 2009-2017 Dave Gamble and cJSON contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef cJSON__h #define cJSON__h #ifdef __cplusplus extern "C" { #endif /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 5 #define CJSON_VERSION_PATCH 2 #include /* cJSON Types: */ #define cJSON_Invalid (0) #define cJSON_False (1 << 0) #define cJSON_True (1 << 1) #define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) #define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) #define cJSON_Raw (1 << 7) /* raw json */ #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 /* The cJSON structure: */ typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ int type; /* The item's string, if type==cJSON_String and type == cJSON_Raw */ char *valuestring; /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ int valueint; /* The item's number, if type==cJSON_Number */ double valuedouble; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ char *string; } cJSON; typedef struct cJSON_Hooks { void *(*malloc_fn)(size_t sz); void (*free_fn)(void *ptr); } cJSON_Hooks; typedef int cJSON_bool; #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) #define __WINDOWS__ #endif #ifdef __WINDOWS__ /* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol For *nix builds that support visibility attribute, you can define similar behavior by setting default visibility to hidden by adding -fvisibility=hidden (for gcc) or -xldscope=hidden (for sun cc) to CFLAGS then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does */ /* export symbols by default, this is necessary for copy pasting the C and header file */ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) #define CJSON_EXPORT_SYMBOLS #endif #if defined(CJSON_HIDE_SYMBOLS) #define CJSON_PUBLIC(type) type __stdcall #elif defined(CJSON_EXPORT_SYMBOLS) #define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall #elif defined(CJSON_IMPORT_SYMBOLS) #define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall #endif #else /* !WIN32 */ #if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) #define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type #else #define CJSON_PUBLIC(type) type #endif #endif /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. * This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif /* returns the version of cJSON as a string */ CJSON_PUBLIC(const char*) cJSON_Version(void); /* Supply malloc, realloc and free functions to cJSON */ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); /* Render a cJSON entity to text for transfer/storage without any formatting. */ CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); /* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); /* Delete a cJSON entity and all subentities. */ CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); /* Returns the number of items in an array (or object). */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); /* Get item "string" from object. Case insensitive. */ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); /* These calls create a cJSON item of the appropriate type. */ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); /* raw json */ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* These utilities create an Array of count items. */ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); /* Append item to the specified array/object. */ CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before * writing to `item->string` */ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); /* Remove/Detatch items from Arrays/Objects. */ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); /* Update array items. */ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will need to be released. With recurse!=0, it will duplicate any children connected to the item. The item->next and ->prev pointers are always zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Macros for creating things quickly. */ #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) #define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s)) /* When assigning an integer value, it needs to be propagated to valuedouble too. */ #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) /* helper for the cJSON_SetNumberValue macro */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); #define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) /* Macro for iterating over an array */ #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void) cJSON_free(void *object); extern cJSON *parse_file(const char * filename); #ifdef __cplusplus } #endif #endif xilinx-bootgen-2024.2/cdo-alloc.c000077500000000000000000000040371475706442400165760ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include "cdo-alloc.h" void * myalloc(size_t len) { void * p = malloc(len); if (p == NULL) { fprintf(stderr, "end of memory\n"); exit(1); } return p; } void * myalloc_zero(size_t len) { void * p = myalloc(len); memset(p, 0, len); return p; } void * myrealloc(void * p, size_t len) { p = realloc(p, len); if (p == NULL) { fprintf(stderr, "end of memory\n"); exit(1); } return p; } /** * @brief This function similar to strdup() which is duplicate input string * however, this will make sure the length of the output is divisible by 4 * @param src string source * @return char* string return */ char* my_strdup(const char* src) { if (src == NULL) return NULL; // Calculate the length of the original string size_t len = strlen(src) + 1; size_t padded_length = (len + 3) & ~3; // Round up to nearest multiple of 4 // Allocate memory for the new string with padding char* dup = (char*)myalloc_zero(padded_length); if (dup == NULL) return NULL; // Copy the string and pad with null characters strcpy(dup, src); return dup; } void myfree(void * p) { free(p); } xilinx-bootgen-2024.2/cdo-alloc.h000077500000000000000000000017661475706442400166110ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_alloc #define D_cdo_alloc void * myalloc(size_t len); void * myalloc_zero(size_t len); void * myrealloc(void * p, size_t len); void myfree(void * p); char* my_strdup(const char* src); #endif /* D_cdo_alloc */ xilinx-bootgen-2024.2/cdo-binary.c000077500000000000000000003021371475706442400167720ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include "cdo-binary.h" static uint32_t verbose; static uint32_t auto_align; static uint32_t add_offset; uint32_t id_code_binary; #define u32xe(v) (be ? u32be(v) : u32le(v)) #define u32xe_lo(v) u32xe((uint32_t)(v)) #define u32xe_hi(v) u32xe((uint32_t)(v >> 32)) #define u32pair(hi, lo) (((uint64_t)(hi) << 32) | (lo)) #define HDR_IDN_WRD (0x584C4E58U) static uint32_t* slr_sync_points; static uint32_t* noc_start_markers; static uint32_t* noc_end_markers; static uint8_t num_start_markers = 0; static uint8_t num_end_markers = 0; static uint8_t num_of_sync_points = 0; static uint8_t search_sync_points = 0; enum { /*General Commands */ CMD1_MASK_POLL = 0x101U, CMD1_MASK_WRITE = 0x102U, CMD1_WRITE = 0x103U, CMD1_DELAY = 0x104U, CMD1_DMA_WRITE = 0x105U, CMD1_MASK_POLL64 = 0x106U, CMD1_MASK_WRITE64 = 0x107U, CMD1_WRITE64 = 0x108U, CMD1_DMA_XFER = 0x109U, /* NPI Commands */ CMD1_NPI_SEQ = 0x201U, CMD1_NPI_PRECFG = 0x202U, CMD1_NPI_WRITE = 0x203U, CMD1_NPI_SHUTDN = 0x204U, /* CFU Commands */ CMD1_CFU_SET_CRC32 = 0x301U, CMD1_CFU_DECOMPRESS = 0x302U, CMD1_CFU_CRAM_RW = 0x303U, CMD1_CFU_SEU_GO = 0x304U, CMD1_CFU_CRC8_DIS = 0x305U, CMD1_CFU_SSI_PER_SLR_PR = 0x306U, CMD1_CFU_GSR_GSC = 0x307U, CMD1_CFU_GCAP_CLK_EN = 0x308U, CMD1_CFU_CFRAME_READ = 0x309U, CMD1_END = 0xffffffffU, }; enum { /*General Commands */ CMD2_END_MARK = 0x100U, CMD2_MASK_POLL = 0x101U, CMD2_MASK_WRITE = 0x102U, CMD2_WRITE = 0x103U, CMD2_DELAY = 0x104U, CMD2_DMA_WRITE = 0x105U, CMD2_MASK_POLL64 = 0x106U, CMD2_MASK_WRITE64 = 0x107U, CMD2_WRITE64 = 0x108U, CMD2_DMA_XFER = 0x109U, CMD2_INIT_SEQ = 0x10aU, CMD2_CFRAME_READ = 0x10bU, CMD2_SET = 0x10cU, CMD2_DMA_WRITE_KEYHOLE = 0x10dU, CMD2_SSIT_SYNC_MASTER = 0x10eU, CMD2_SSIT_SYNC_SLAVES = 0x10fU, CMD2_SSIT_WAIT_SLAVES = 0x110U, CMD2_NOP = 0x111U, CMD2_GET_DEVICE_ID = 0x112U, CMD2_EVENT_LOGGING = 0x113U, CMD2_SET_BOARD = 0x114U, CMD2_GET_BOARD = 0x115U, CMD2_SET_PLM_WDT = 0x116U, CMD2_LOG_STRING = 0x117U, CMD2_LOG_ADDRESS = 0x118U, CMD2_MARKER = 0x119U, CMD2_PROC = 0x11aU, CMD2_BLOCK_BEGIN = 0x11bU, CMD2_BLOCK_END = 0x11cU, CMD2_BREAK = 0x11dU, CMD2_OT_CHECK = 0x11eU, CMD2_PSM_SEQUENCE = 0x11fU, CMD2_PLM_UPDATE = 0x120U, CMD2_SCATTER_WRITE = 0x121U, CMD2_SCATTER_WRITE2 = 0x122U, CMD2_TAMPER_TRIGGER = 0x123U, CMD2_SET_IPI_ACCESS = 0x125U, CMD2_RUN_PROC = 0x126U, CMD2_LIST_SET = 0x127U, CMD2_LIST_WRITE = 0x128U, CMD2_LIST_MASK_WRITE = 0x129U, CMD2_LIST_MASK_POLL = 0x12AU, CMD2_CDO_SEQUENCE = 0x12CU, /* PM Commands */ CMD2_PM_GET_API_VERSION = 0x201U, CMD2_PM_GET_DEVICE_STATUS = 0x203U, CMD2_PM_GET_OP_CHARACTERISTIC = 0x204U, CMD2_PM_REGISTER_NOTIFIER = 0x205U, CMD2_PM_REQUEST_SUSPEND = 0x206U, CMD2_PM_SELF_SUSPEND = 0x207U, CMD2_PM_FORCE_POWERDOWN = 0x208U, CMD2_PM_ABORT_SUSPEND = 0x209U, CMD2_PM_REQUEST_WAKEUP = 0x20aU, CMD2_PM_SET_WAKEUP_SOURCE = 0x20bU, CMD2_PM_SYSTEM_SHUTDOWN = 0x20cU, CMD2_PM_REQUEST_DEVICE = 0x20dU, CMD2_PM_RELEASE_DEVICE = 0x20eU, CMD2_PM_SET_REQUIREMENT = 0x20fU, CMD2_PM_SET_MAX_LATENCY = 0x210U, CMD2_PM_RESET_ASSERT = 0x211U, CMD2_PM_RESET_GET_STATUS = 0x212U, CMD2_PM_PINCTRL_REQUEST = 0x21cU, CMD2_PM_PINCTRL_RELEASE = 0x21dU, CMD2_PM_PINCTRL_GET_FUNCTION = 0x21eU, CMD2_PM_PINCTRL_SET_FUNCTION = 0x21fU, CMD2_PM_PINCTRL_CONFIG_PARAM_GET = 0x220U, CMD2_PM_PINCTRL_CONFIG_PARAM_SET = 0x221U, CMD2_PM_IOCTL = 0x222U, CMD2_PM_QUERY_DATA = 0x223U, CMD2_PM_CLOCK_ENABLE = 0x224U, CMD2_PM_CLOCK_DISABLE = 0x225U, CMD2_PM_CLOCK_GETSTATE = 0x226U, CMD2_PM_CLOCK_SETDIVIDER = 0x227U, CMD2_PM_CLOCK_GETDIVIDER = 0x228U, CMD2_PM_CLOCK_SETRATE = 0x229U, CMD2_PM_CLOCK_GETRATE = 0x22aU, CMD2_PM_CLOCK_SETPARENT = 0x22bU, CMD2_PM_CLOCK_GETPARENT = 0x22cU, CMD2_PM_PLL_SET_PARAMETER = 0x230U, CMD2_PM_PLL_GET_PARAMETER = 0x231U, CMD2_PM_PLL_SET_MODE = 0x232U, CMD2_PM_PLL_GET_MODE = 0x233U, CMD2_PM_ADD_SUBSYSTEM = 0x236U, CMD2_PM_DESTROY_SUBSYSTEM = 0x237U, CMD2_PM_DESCRIBE_NODES = 0x238U, CMD2_PM_ADD_NODE = 0x239U, CMD2_PM_ADD_NODE_PARENT = 0x23aU, CMD2_PM_ADD_NODE_NAME = 0x23bU, CMD2_PM_ADD_REQUIREMENT = 0x23cU, CMD2_PM_SET_CURRENT_SUBSYSTEM = 0x23dU, CMD2_PM_INIT_NODE = 0x23eU, CMD2_PM_FEATURE_CHECK = 0x23fU, CMD2_PM_ISO_CONTROL = 0x240U, CMD2_PM_ACTIVATE_SUBSYSTEM = 0x241U, CMD2_PM_SET_NODE_ACCESS = 0x242U, CMD2_PM_BISR = 0x243, CMD2_PM_APPLY_TRIM = 0x244, CMD2_PM_NOC_CLOCK_ENABLE = 0x245, CMD2_PM_IF_NOC_CLOCK_ENABLE = 0x246, CMD2_PM_FORCE_HC =0x247, CMD2_PM_HNICX_NPI_DATA_XFER = 0x24AU, /* NPI Commands */ /* Version 1.50 and later, but not version 2.00 */ CMD2_NPI_SEQ = 0x301U, CMD2_NPI_PRECFG = 0x302U, CMD2_NPI_WRITE = 0x303U, CMD2_NPI_SHUTDN = 0x304U, /* SEM Commands */ /* Version 2.00 and later */ CMD2_SEM_NPI_TABLE = 0x300U, /* CFU Commands */ /* Version 1.50 and later, but not version 2.00 */ CMD2_CFU_SET_CRC32 = 0x401U, CMD2_CFU_DECOMPRESS = 0x402U, CMD2_CFU_CRAM_RW = 0x403U, CMD2_CFU_SEU_GO = 0x404U, CMD2_CFU_CRC8_DIS = 0x405U, CMD2_CFU_SSI_PER_SLR_PR = 0x406U, CMD2_CFU_GSR_GSC = 0x407U, CMD2_CFU_GCAP_CLK_EN = 0x408U, CMD2_CFU_CFI_TYPE = 0x409U, /* Loader Commands */ CMD2_LDR_SET_IMAGE_INFO = 0x704U, CMD2_LDR_CFRAME_CLEAR_CHECK = 0x70cU, /* EM Commands */ CMD2_EM_SET_ACTION = 0x801U, CMD2_END = 0xffffffffU }; struct cdo_device { const char* name; uint32_t idcode; } binary_device_list[] = { { "xcvm1402", 0x04C08093 }, { "xcvm1302", 0x04C09093 }, { "xcv20", 0x04C0F093 }, { "xcvp1052", 0x04C18093 }, { "xcvp1002", 0x04C1B093 }, { "xcvm2102", 0x04C1C093 }, { "xcvp1402", 0x04C20093 }, { "xcvp1102", 0x04C22093 }, { "xcvm2902", 0x04C23093 }, { "xcvm2302", 0x04C24093 }, { "xcvr1352", 0x04C90093 }, { "xcvr1302", 0x04C91093 }, { "xcvc1352", 0x04C93093 }, { "xcvr1402", 0x04C94093 }, { "xcvc1702", 0x04C98093 }, { "xcvm1502", 0x04C99093 }, { "xcve1752", 0x04C9A093 }, { "xcvc1502", 0x04C9B093 }, { "xcvr1702", 0x04CA0093 }, { "xcvr1502", 0x04CA2093 }, { "xcvr1602", 0x04CA3093 }, { "xcvr1802", 0x04CA5093 }, { "xcvc1802", 0x14CA9093 }, { "xcvm1802", 0x14CAA093 }, { "xcv65", 0x14CAF093 }, { "xcve2102", 0x04CC0093 }, { "xcve2002", 0x04CC1093 }, { "xcve2302", 0x14CC8093 }, { "xcve2202", 0x14CC9093 }, { "xcvm1102", 0x14CCA093 }, { "xcvc2802", 0x14CD0093 }, { "xcvc2602", 0x14CD1093 }, { "xcve2602", 0x14CD2093 }, { "xcve2802", 0x14CD3093 }, { "xcvm2202", 0x14CD4093 }, { "xcv70", 0x14CD7093 }, { "xcvp1202", 0x14D00093 }, { "xcvm2502", 0x14D01093 }, { "xcvp1502", 0x14D08093 }, { "xcvp1702", 0x14D10093 }, { "xcvp1802", 0x14D14093 }, { "xcvp2502", 0x14D1C093 }, { "xcvp2802", 0x14D20093 }, { "xcvh1582", 0x14D28093 }, { "xcvh1542", 0x14D29093 }, { "xcvh1522", 0x14D2A093 }, { "xcvh1782", 0x14D2C093 }, { "xcvh1742", 0x14D2D093 }, { "xcv80", 0x14D2F093 }, { "xcvp1552", 0x14D34093 }, { "xcvp1752", 0x14D38093 }, { "xcvn3716", 0x14D80093 }, { "xcvn3516", 0x14D81093 }, { "xcvn3408", 0x14D82093 }, { "xcvn3708", 0x14D83093 }, { "xcvc1902", 0x14CA8093 }, { NULL, 0 } }; void cdobinary_set_verbose(uint32_t level) { verbose = level; } void cdobinary_set_auto_align(uint32_t enable) { auto_align = enable; } void cdobinary_set_add_offset(uint32_t enable) { add_offset = enable; } static void byte_swap_buffer(uint32_t * p, uint32_t count, uint32_t be) { if (is_be_host() != be) { uint32_t i; for (i = 0; i < count; i++) { p[i] = u32swap(p[i]); } } } uint32_t idcode_from_binary(uint32_t id) { if (id_code_binary != 0) { id = id_code_binary; id_code_binary = 0; } return id; } static uint32_t find_device(char * name) { struct cdo_device * device = binary_device_list; while (device->name != NULL) { if (strncmp(device->name, name, sizeof(char*)) == 0) break; device++; } return device->idcode; } static uint32_t decode_v1(CdoSequence * seq, uint32_t * p, uint32_t l, uint32_t be) { uint32_t i = u32xe(p[0]) + 1; uint32_t sections = u32xe(p[3]); uint32_t secno = 0; while (secno < sections && i + 3 <= l) { uint32_t secid = u32xe(p[i++]); uint32_t seclen = u32xe(p[i++]); uint32_t secend = l; uint32_t seccmds = u32xe(p[i++]); uint32_t cmdno = 0; if (verbose) { fprintf(stderr, "info: decoding section %#"PRIx32" len %"PRIu32" cmds %"PRIu32" at %"PRIu32"\n", secid, seclen, seccmds, i - 3); } if (add_offset) { cdocmd_add_comment(seq, "offset: %#"PRIx64, (uint64_t)i * 4); } cdocmd_add_section(seq, secid); while (i < l && cmdno < seccmds) { uint32_t id = u32xe(p[i++]); uint32_t args = 0; if (verbose) { fprintf(stderr, "info: decoding command %#"PRIx32" at %"PRIu32"\n", id, i - 1); } if (add_offset) { cdocmd_add_comment(seq, "offset: %#"PRIx64, (uint64_t)i * 4); } switch (id) { case CMD1_MASK_POLL: args = 4; if (secend - i < args) break; cdocmd_add_mask_poll(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])*1000, 0); break; case CMD1_MASK_WRITE: args = 3; if (secend - i < args) break; cdocmd_add_mask_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD1_WRITE: args = 2; if (secend - i < args) break; cdocmd_add_write(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD1_DELAY: args = 1; if (secend - i < args) break; cdocmd_add_delay(seq, u32xe(p[i+0])*1000); break; case CMD1_DMA_WRITE: args = 3; if (secend - i < args) break; args += u32xe(p[i+1]) + u32xe(p[i+2]); if (secend - i < args) break; cdocmd_add_block_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), &p[i+3+u32xe(p[i+2])], be); break; case CMD1_MASK_POLL64: args = 5; if (secend - i < args) break; cdocmd_add_mask_poll(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4])*1000, 0); break; case CMD1_MASK_WRITE64: args = 4; if (secend - i < args) break; cdocmd_add_mask_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD1_WRITE64: args = 3; if (secend - i < args) break; cdocmd_add_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2])); break; case CMD1_DMA_XFER: args = 6; if (secend - i < args) break; if (u32xe(p[i+0]) == 0 && u32xe(p[i+1]) == 0) { args += u32xe(p[i+4]); if (secend - i < args) break; cdocmd_add_dma_xfer(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32pair(u32xe(p[i+2]), u32xe(p[i+3])), u32xe(p[i+4]), u32xe(p[i+5]), &p[i+6], be); } else { cdocmd_add_dma_xfer(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32pair(u32xe(p[i+2]), u32xe(p[i+3])), u32xe(p[i+4]), u32xe(p[i+5]), NULL, be); } break; case CMD1_NPI_SEQ: args = 2; if (secend - i < args) break; cdocmd_add_npi_seq(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD1_NPI_PRECFG: args = 2; if (secend - i < args) break; cdocmd_add_npi_precfg(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD1_NPI_WRITE: args = 3; if (secend - i < args) break; args += u32xe(p[i+2]); if (secend - i < args) break; cdocmd_add_npi_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), &p[i+3], be); break; case CMD1_NPI_SHUTDN: args = 2; if (secend - i < args) break; cdocmd_add_npi_shutdown(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD1_CFU_SET_CRC32: args = 1; if (secend - i < args) break; if (u32xe(p[i+0]) == 0) { cdocmd_add_cfu_set_crc32(seq, 0, 0); break; } args = 2; if (secend - i < args) break; cdocmd_add_cfu_set_crc32(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD1_CFU_DECOMPRESS: args = 1; if (secend - i < args) break; cdocmd_add_cfu_decompress(seq, u32xe(p[i+0])); break; case CMD1_CFU_CRAM_RW: args = 1; if (secend - i < args) break; cdocmd_add_cfu_cram_rw(seq, u32xe(p[i+0])); break; case CMD1_CFU_SEU_GO: args = 1; if (secend - i < args) break; cdocmd_add_cfu_seu_go(seq, u32xe(p[i+0])); break; case CMD1_CFU_CRC8_DIS: args = 1; if (secend - i < args) break; cdocmd_add_cfu_crc8_dis(seq, u32xe(p[i+0])); break; case CMD1_CFU_SSI_PER_SLR_PR: args = 1; if (secend - i < args) break; cdocmd_add_cfu_ssi_per_slr_pr(seq, u32xe(p[i+0])); break; case CMD1_CFU_GSR_GSC: args = 1; if (secend - i < args) break; cdocmd_add_cfu_gsr_gsc(seq, u32xe(p[i+0])); break; case CMD1_CFU_GCAP_CLK_EN: args = 1; if (secend - i < args) break; cdocmd_add_cfu_gcap_clk_en(seq, u32xe(p[i+0])); break; case CMD1_CFU_CFRAME_READ: args = 20; if (secend - i < args) break; cdocmd_add_cframe_read(seq, u32xe(p[i+0]), u32pair(u32xe(p[i+1]), u32xe(p[i+2])), u32xe(p[i+3]), 16, &p[i+4], be); break; case CMD1_END: goto end_of_section; default: fprintf(stderr, "unknown command %"PRIx32"\n", id); return 1; } if (secend - i < args) { fprintf(stderr, "incomplete command payload %"PRIu32", expected %"PRIu32"\n", secend - i, args); return 1; } i += args; cmdno++; } if (cmdno < seccmds) { fprintf(stderr, "incomplete command count %"PRIu32", expected %"PRIu32"\n", cmdno, seccmds); return 1; } end_of_section: secno++; } if (secno < sections) { fprintf(stderr, "incomplete section count %"PRIu32", expected %"PRIu32"\n", secno, sections); return 1; } if (i < l) { fprintf(stderr, "warning: mismatching CDO word count %"PRIu32", expected %"PRIu32"\n", i, l); } return 0; } static uint32_t decode_v2_cmd(CdoSequence * seq, uint32_t * p, uint32_t * ip, uint32_t l, uint32_t be) { uint32_t i = *ip; uint32_t cmdpos = 0; uint32_t hdr; while (i < l) { uint32_t args; cmdpos = i; if (add_offset) { cdocmd_add_comment(seq, "offset: %#"PRIx64, (uint64_t)cmdpos * 4); } hdr = u32xe(p[i++]); if (verbose) { fprintf(stderr, "info: decoding command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); } args = (hdr >> 16) & 255; if (args == 255) { if (hdr == CMD2_END) goto found_end_marker; if (i >= l) { fprintf(stderr, "incomplete CDO command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); goto error; } args = u32xe(p[i++]); } if (l - i < args) { fprintf(stderr, "incomplete CDO command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); goto error; } switch (hdr & 0xffff) { case CMD2_END_MARK: goto found_end_marker; case CMD2_MASK_POLL: if (args == 4) { cdocmd_add_mask_poll(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3]), 0); } else if (args == 5) { cdocmd_add_mask_poll(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4])); } else if (args == 6) { cdocmd_add_mask_poll_w_err(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4]), u32xe(p[i+5])); } else { goto unexpected; } break; case CMD2_MASK_WRITE: if (args != 3) goto unexpected; cdocmd_add_mask_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_WRITE: if (args != 2) goto unexpected; cdocmd_add_write(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_RUN_PROC: if (args != 1) goto unexpected; cdocmd_add_run_proc(seq, u32xe(p[i+0])); break; case CMD2_LIST_SET: if (args < 2) goto unexpected; cdocmd_add_list_set(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_LIST_WRITE: if (args != 2) goto unexpected; cdocmd_add_list_write(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_LIST_MASK_WRITE: if (args != 3) goto unexpected; cdocmd_add_list_mask_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_LIST_MASK_POLL: if (args == 4) { cdocmd_add_list_mask_poll(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3]), 0); } else if (args == 5) { cdocmd_add_list_mask_poll(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4])); } else { goto unexpected; } break; case CMD2_DELAY: if (args != 1) goto unexpected; cdocmd_add_delay(seq, u32xe(p[i+0])); break; case CMD2_DMA_WRITE: if (args < 2) goto unexpected; cdocmd_add_block_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), args - 2, &p[i+2], be); break; case CMD2_DMA_WRITE_KEYHOLE: if (args < 3) goto unexpected; cdocmd_add_keyhole_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), args - 3, &p[i+3], be); break; case CMD2_SSIT_SYNC_MASTER: if (args != 0) goto unexpected; cdocmd_add_ssit_sync_master(seq); break; case CMD2_SSIT_SYNC_SLAVES: if (args != 2) goto unexpected; cdocmd_add_ssit_sync_slaves(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_SSIT_WAIT_SLAVES: if (args != 2) goto unexpected; cdocmd_add_ssit_wait_slaves(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_MASK_POLL64: if (args == 5) { cdocmd_add_mask_poll(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4]), 0); } else if (args == 6) { cdocmd_add_mask_poll(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4]), u32xe(p[i+5])); } else if (args == 7) { cdocmd_add_mask_poll_w_err(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3]), u32xe(p[i+4]), u32xe(p[i+5]), u32xe(p[i+6])); } else { goto unexpected; } break; case CMD2_MASK_WRITE64: if (args != 4) goto unexpected; cdocmd_add_mask_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_WRITE64: if (args != 3) goto unexpected; cdocmd_add_write(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2])); break; case CMD2_DMA_XFER: if (args != 6) goto unexpected; cdocmd_add_dma_xfer(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32pair(u32xe(p[i+2]), u32xe(p[i+3])), u32xe(p[i+4]), u32xe(p[i+5]), NULL, be); break; case CMD2_CFRAME_READ: if (args < 4) goto unexpected; cdocmd_add_cframe_read(seq, u32xe(p[i+0]), u32pair(u32xe(p[i+1]), u32xe(p[i+2])), u32xe(p[i+3]), args - 4, &p[i+4], be); break; case CMD2_SET: if (args != 4) goto unexpected; cdocmd_add_block_set(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_NOP: cdocmd_add_nop(seq, args, &p[i+0], be); break; case CMD2_EVENT_LOGGING: if (args < 1) goto unexpected; cdocmd_add_event_logging(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_SET_BOARD: { uint32_t * tmpbuf; tmpbuf = malloc((args + 1) * sizeof *tmpbuf); memcpy(tmpbuf, &p[i+0], args * sizeof *tmpbuf); tmpbuf[args] = 0; byte_swap_buffer(tmpbuf, args, be); cdocmd_add_set_board(seq, (char *)tmpbuf); free(tmpbuf); break; } case CMD2_SET_PLM_WDT: if (args != 2) goto unexpected; cdocmd_add_set_plm_wdt(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_LOG_STRING: { uint32_t * tmpbuf; tmpbuf = malloc((args + 1) * sizeof *tmpbuf); memcpy(tmpbuf, &p[i+0], args * sizeof *tmpbuf); tmpbuf[args] = 0; byte_swap_buffer(tmpbuf, args, be); cdocmd_add_log_string(seq, (char *)tmpbuf); free(tmpbuf); break; } case CMD2_LOG_ADDRESS: if (args == 1) { cdocmd_add_log_address(seq, u32xe(p[i+0])); } else if (args == 2) { cdocmd_add_log_address(seq, u32pair(u32xe(p[i+1]), u32xe(p[i+0]))); } else { goto unexpected; } break; case CMD2_MARKER: { uint32_t * tmpbuf; if (args < 1) goto unexpected; tmpbuf = malloc(args * sizeof *tmpbuf); memcpy(tmpbuf, &p[i+1], (args - 1) * sizeof *tmpbuf); tmpbuf[args - 1] = 0; byte_swap_buffer(tmpbuf, args - 1, be); cdocmd_add_marker(seq, u32xe(p[i+0]), (char *)tmpbuf); free(tmpbuf); break; } case CMD2_PROC: { uint32_t i2 = i + 1; if (args < 1) goto unexpected; cdocmd_add_proc(seq, u32xe(p[i+0])); if (decode_v2_cmd(seq, p, &i2, i2 + args - 1, be)) { goto error; } cdocmd_add_end(seq); break; } case CMD2_BLOCK_BEGIN: { uint32_t * tmpbuf; if (args < 1) goto unexpected; tmpbuf = malloc(args * sizeof *tmpbuf); memcpy(tmpbuf, &p[i+1], (args - 1) * sizeof *tmpbuf); tmpbuf[args - 1] = 0; byte_swap_buffer(tmpbuf, args - 1, be); cdocmd_add_begin(seq, (char *)tmpbuf); free(tmpbuf); break; } case CMD2_BLOCK_END: { if (args != 0) goto unexpected; cdocmd_add_end(seq); break; } case CMD2_BREAK: { if (args > 1) goto unexpected; cdocmd_add_break(seq, args > 0 ? u32xe(p[i+0]) : 1); break; } case CMD2_OT_CHECK: if (args != 1) goto unexpected; cdocmd_add_ot_check(seq, u32xe(p[i+0])); break; case CMD2_PSM_SEQUENCE: { uint32_t i2 = i; cdocmd_add_psm_sequence(seq); if (decode_v2_cmd(seq, p, &i2, i2 + args, be)) { goto error; } cdocmd_add_end(seq); break; } case CMD2_CDO_SEQUENCE: { uint32_t i2 = i + 3; if (args < 3) goto unexpected; cdocmd_add_cdo_sequence(seq, u32pair(u32xe(p[i+0]), u32xe(p[i+1])), u32xe(p[i+2])); if (decode_v2_cmd(seq, p, &i2, i2 + args - 3, be)) { goto error; } cdocmd_add_end(seq); break; } case CMD2_SCATTER_WRITE: if (args < 2) goto unexpected; cdocmd_add_scatter_write(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_SCATTER_WRITE2: if (args < 3) goto unexpected; cdocmd_add_scatter_write2(seq, u32xe(p[i+0]), u32xe(p[i+1]), args - 2, &p[i+2], be); break; case CMD2_TAMPER_TRIGGER: if (args != 1) goto unexpected; cdocmd_add_tamper_trigger(seq, u32xe(p[i+0])); break; case CMD2_SET_IPI_ACCESS: if (args != 2) goto unexpected; cdocmd_add_set_ipi_access(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_NPI_SEQ: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args != 2) goto unexpected; cdocmd_add_npi_seq(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_NPI_PRECFG: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args != 2) goto unexpected; cdocmd_add_npi_precfg(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_NPI_WRITE: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 2) goto unexpected; cdocmd_add_npi_write(seq, u32xe(p[i+0]), u32xe(p[i+1]), args - 2, &p[i+2], be); break; case CMD2_NPI_SHUTDN: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args != 2) goto unexpected; cdocmd_add_npi_shutdown(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_HNICX_NPI_DATA_XFER: if (args != 2) goto unexpected; cdocmd_add_pm_hnicx_npi_data_xfer(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_GET_API_VERSION: if (args != 0) goto unexpected; cdocmd_add_pm_get_api_version(seq); break; case CMD2_PM_GET_DEVICE_STATUS: if (args != 1) goto unexpected; cdocmd_add_pm_get_device_status(seq, u32xe(p[i+0])); break; case CMD2_PM_REGISTER_NOTIFIER: if (args != 4) goto unexpected; cdocmd_add_pm_register_notifier(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_PM_REQUEST_SUSPEND: if (args != 4) goto unexpected; cdocmd_add_pm_request_suspend(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_PM_SELF_SUSPEND: if (args != 5) goto unexpected; cdocmd_add_pm_self_suspend(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32pair(u32xe(p[i+4]), u32xe(p[i+3]))); break; case CMD2_PM_FORCE_POWERDOWN: if (args != 2) goto unexpected; cdocmd_add_pm_force_powerdown(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_ABORT_SUSPEND: if (args != 2) goto unexpected; cdocmd_add_pm_abort_suspend(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_REQUEST_WAKEUP: if (args != 4) goto unexpected; cdocmd_add_pm_request_wakeup(seq, u32xe(p[i+0]), u32pair(u32xe(p[i+2]), u32xe(p[i+1])), u32xe(p[i+3])); break; case CMD2_PM_SET_WAKEUP_SOURCE: if (args != 3) goto unexpected; cdocmd_add_pm_set_wakeup_source(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_PM_SYSTEM_SHUTDOWN: if (args != 2) goto unexpected; cdocmd_add_pm_system_shutdown(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_REQUEST_DEVICE: if (args != 4) goto unexpected; cdocmd_add_pm_request_device(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_PM_RELEASE_DEVICE: if (args != 1) goto unexpected; cdocmd_add_pm_release_device(seq, u32xe(p[i+0])); break; case CMD2_PM_SET_REQUIREMENT: if (args != 4) goto unexpected; cdocmd_add_pm_set_requirement(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_PM_SET_MAX_LATENCY: if (args != 2) goto unexpected; cdocmd_add_pm_set_max_latency(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_RESET_ASSERT: if (args != 2) goto unexpected; cdocmd_add_pm_reset_assert(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_RESET_GET_STATUS: if (args != 1) goto unexpected; cdocmd_add_pm_reset_get_status(seq, u32xe(p[i+0])); break; case CMD2_PM_PINCTRL_REQUEST: if (args != 1) goto unexpected; cdocmd_add_pm_pinctrl_request(seq, u32xe(p[i+0])); break; case CMD2_PM_PINCTRL_RELEASE: if (args != 1) goto unexpected; cdocmd_add_pm_pinctrl_release(seq, u32xe(p[i+0])); break; case CMD2_PM_PINCTRL_GET_FUNCTION: if (args != 1) goto unexpected; cdocmd_add_pm_pinctrl_get_function(seq, u32xe(p[i+0])); break; case CMD2_PM_PINCTRL_SET_FUNCTION: if (args != 2) goto unexpected; cdocmd_add_pm_pinctrl_set_function(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_PINCTRL_CONFIG_PARAM_GET: if (args != 2) goto unexpected; cdocmd_add_pm_pinctrl_config_param_get(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_PINCTRL_CONFIG_PARAM_SET: if (args != 3) goto unexpected; cdocmd_add_pm_pinctrl_config_param_set(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_PM_IOCTL: if (args < 2) goto unexpected; cdocmd_add_pm_ioctl(seq, u32xe(p[i+0]), u32xe(p[i+1]), &p[i+2], args-2, be); break; case CMD2_PM_QUERY_DATA: if (args < 1) goto unexpected; cdocmd_add_pm_query_data(seq, u32xe(p[i+0]), &p[i+1], args-1, be); break; case CMD2_PM_CLOCK_ENABLE: if (args != 1) goto unexpected; cdocmd_add_pm_clock_enable(seq, u32xe(p[i+0])); break; case CMD2_PM_CLOCK_DISABLE: if (args != 1) goto unexpected; cdocmd_add_pm_clock_disable(seq, u32xe(p[i+0])); break; case CMD2_PM_CLOCK_GETSTATE: if (args != 1) goto unexpected; cdocmd_add_pm_clock_getstate(seq, u32xe(p[i+0])); break; case CMD2_PM_CLOCK_SETDIVIDER: if (args != 2) goto unexpected; cdocmd_add_pm_clock_setdivider(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_CLOCK_GETDIVIDER: if (args != 1) goto unexpected; cdocmd_add_pm_clock_getdivider(seq, u32xe(p[i+0])); break; case CMD2_PM_CLOCK_SETRATE: if (args != 2) goto unexpected; cdocmd_add_pm_clock_setrate(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_CLOCK_GETRATE: if (args != 1) goto unexpected; cdocmd_add_pm_clock_getrate(seq, u32xe(p[i+0])); break; case CMD2_PM_CLOCK_SETPARENT: if (args != 2) goto unexpected; cdocmd_add_pm_clock_setparent(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_CLOCK_GETPARENT: if (args != 1) goto unexpected; cdocmd_add_pm_clock_getparent(seq, u32xe(p[i+0])); break; case CMD2_PM_PLL_SET_PARAMETER: if (args != 3) goto unexpected; cdocmd_add_pm_pll_set_parameter(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_PM_PLL_GET_PARAMETER: if (args != 2) goto unexpected; cdocmd_add_pm_pll_get_parameter(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_PLL_SET_MODE: if (args != 2) goto unexpected; cdocmd_add_pm_pll_set_mode(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_PLL_GET_MODE: if (args != 1) goto unexpected; cdocmd_add_pm_pll_get_mode(seq, u32xe(p[i+0])); break; case CMD2_PM_ADD_SUBSYSTEM: if (args != 1) goto unexpected; cdocmd_add_pm_add_subsystem(seq, u32xe(p[i+0])); break; case CMD2_PM_DESTROY_SUBSYSTEM: if (args != 1) goto unexpected; cdocmd_add_pm_destroy_subsystem(seq, u32xe(p[i+0])); break; case CMD2_PM_DESCRIBE_NODES: cdocmd_add_pm_describe_nodes(seq, &p[i+0], args, be); break; case CMD2_PM_ADD_NODE: if (args < 1) goto unexpected; cdocmd_add_pm_add_node(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_PM_ADD_NODE_PARENT: if (args < 2) goto unexpected; cdocmd_add_pm_add_node_parent(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_PM_ADD_NODE_NAME: { uint32_t * tmpbuf; if (args < 2) goto unexpected; tmpbuf = malloc(args * sizeof *tmpbuf); memcpy(tmpbuf, &p[i+1], (args - 1) * sizeof *tmpbuf); tmpbuf[args - 1] = 0; byte_swap_buffer(tmpbuf, args - 1, be); cdocmd_add_pm_add_node_name(seq, u32xe(p[i+0]), (char *)tmpbuf); free(tmpbuf); break; } case CMD2_PM_ADD_REQUIREMENT: if (args < 3) goto unexpected; cdocmd_add_pm_add_requirement(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), args - 3, &p[i+3], be); break; case CMD2_PM_SET_CURRENT_SUBSYSTEM: if (args != 1) goto unexpected; cdocmd_add_pm_set_current_subsystem(seq, u32xe(p[i+0])); break; case CMD2_PM_INIT_NODE: if (args < 2) goto unexpected; cdocmd_add_pm_init_node(seq, u32xe(p[i+0]), u32xe(p[i+1]), args - 2, &p[i+2], be); break; case CMD2_PM_FEATURE_CHECK: if (args != 1) goto unexpected; cdocmd_add_pm_feature_check(seq, u32xe(p[i+0])); break; case CMD2_PM_ISO_CONTROL: if (args != 2) goto unexpected; cdocmd_add_pm_iso_control(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_PM_ACTIVATE_SUBSYSTEM: if (args != 1) goto unexpected; cdocmd_add_pm_activate_subsystem(seq, u32xe(p[i+0])); break; case CMD2_PM_SET_NODE_ACCESS: if (args < 1) goto unexpected; cdocmd_add_pm_set_node_access(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_PM_BISR: if (args != 1) goto unexpected; cdocmd_add_pm_bisr(seq, u32xe(p[i+0])); break; case CMD2_PM_APPLY_TRIM: if (args != 1) goto unexpected; cdocmd_add_pm_apply_trim(seq, u32xe(p[i+0])); break; case CMD2_PM_NOC_CLOCK_ENABLE: if (args < 1) goto unexpected; cdocmd_add_pm_noc_clock_enable(seq, u32xe(p[i+0]), args - 1, &p[i+1], be); break; case CMD2_PM_IF_NOC_CLOCK_ENABLE: if (args != 2 && args != 3) goto unexpected; cdocmd_add_pm_if_noc_clock_enable(seq, u32xe(p[i+0]), u32xe(p[i+1]), args == 3 ? u32xe(p[i+2]) : 1); break; case CMD2_PM_FORCE_HC: if (args != 1) goto unexpected; cdocmd_add_pm_force_hc(seq, u32xe(p[i+0])); break; case CMD2_CFU_SET_CRC32: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; if (u32xe(p[i+0]) == 0) { cdocmd_add_cfu_set_crc32(seq, 0, 0); break; } if (args < 2) goto unexpected; cdocmd_add_cfu_set_crc32(seq, u32xe(p[i+0]), u32xe(p[i+1])); break; case CMD2_CFU_DECOMPRESS: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_decompress(seq, u32xe(p[i+0])); break; case CMD2_CFU_CRAM_RW: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_cram_rw(seq, u32xe(p[i+0])); break; case CMD2_CFU_SEU_GO: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_seu_go(seq, u32xe(p[i+0])); break; case CMD2_CFU_CRC8_DIS: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_crc8_dis(seq, u32xe(p[i+0])); break; case CMD2_CFU_SSI_PER_SLR_PR: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_ssi_per_slr_pr(seq, u32xe(p[i+0])); break; case CMD2_CFU_GSR_GSC: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_gsr_gsc(seq, u32xe(p[i+0])); break; case CMD2_CFU_GCAP_CLK_EN: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_gcap_clk_en(seq, u32xe(p[i+0])); break; case CMD2_CFU_CFI_TYPE: if (seq->version >= CDO_VERSION_2_00) goto unexpected; if (args < 1) goto unexpected; cdocmd_add_cfu_cfi_type(seq, u32xe(p[i+0])); break; case CMD2_EM_SET_ACTION: if (args != 3) goto unexpected; cdocmd_add_em_set_action(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2])); break; case CMD2_LDR_SET_IMAGE_INFO: if (args != 4) goto unexpected; cdocmd_add_ldr_set_image_info(seq, u32xe(p[i+0]), u32xe(p[i+1]), u32xe(p[i+2]), u32xe(p[i+3])); break; case CMD2_LDR_CFRAME_CLEAR_CHECK: if (args != 1) goto unexpected; cdocmd_add_ldr_cframe_clear_check(seq, u32xe(p[i+0])); break; case CMD2_SEM_NPI_TABLE: if (args < 2) goto unexpected; cdocmd_add_sem_npi_table(seq, u32xe(p[i+0]), u32xe(p[i+1]), args - 2, &p[i+2], be); break; default: cdocmd_add_generic_command(seq, hdr & 0xffff, p + i, args, be); break; } i += args; } found_end_marker: *ip = i; return 0; unexpected: fprintf(stderr, "invalid payload size command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); error: *ip = i; return 1; } int check_cdo_commands(void* data, uint32_t l, uint32_t * xplm_data, uint32_t xplm_length) { uint32_t be = 0; uint32_t * p = (uint32_t *)data; uint32_t hdrlen = u32xe(p[0]); uint32_t len = u32xe(p[3]); uint32_t total_len = hdrlen + 1 + len; uint32_t i = hdrlen + 1; uint32_t cmdpos = 0; uint32_t hdr; uint8_t cmd_id; uint8_t module_id; size_t index; if (l < total_len) { fprintf(stderr, "warning: incomplete CDO buffer %"PRIu32", expected %"PRIu32"\n", l, total_len); total_len = l; } else if (l > total_len) { l = total_len; } while (i < l) { uint32_t args; int cmd_found; cmdpos = i; hdr = u32xe(p[i++]); if (verbose) { fprintf(stderr, "info: decoding command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); } args = (hdr >> 16) & 255; if (args == 255) { if (hdr == CMD2_END) goto found_end_marker; if (i >= l) { fprintf(stderr, "incomplete CDO command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); } args = u32xe(p[i++]); } if (l - i < args) { fprintf(stderr, "incomplete CDO command %#"PRIx32" at %"PRIu32"\n", hdr, cmdpos); } cmd_id = hdr & 0xff; module_id = (hdr & 0xff00) >> 0x8; // TODO: only PLM commands are supported for now if (module_id == 0x1 && xplm_length != 0){ cmd_found = 0; size_t cmdInfo_size = sizeof(XPlmi_CmdInfo); for (index = 0; index < (xplm_length/ cmdInfo_size); index++) { uint8_t* cmdInfo = (uint8_t*)malloc(cmdInfo_size); memset(cmdInfo, 0, cmdInfo_size); memcpy(cmdInfo, xplm_data + (index * (cmdInfo_size/4)), cmdInfo_size); XPlmi_CmdInfo* cmd_info = (XPlmi_CmdInfo*)(cmdInfo); if (cmd_info->cmd_id == cmd_id && cmd_info->module_id == module_id && args >= cmd_info->min_arg_cnt && args <= cmd_info->max_arg_cnt) { cmd_found = 1; break; } } if (cmd_found == 0 && cmd_id != 5 && cmd_id != 13 && cmd_id != 0) { return 1; } } i += args; } found_end_marker: return 0; } static uint32_t decode_v2(CdoSequence * seq, uint32_t * p, uint32_t l, uint32_t be) { uint32_t hdrlen = u32xe(p[0]); uint32_t len = u32xe(p[3]); uint32_t total_len = hdrlen + 1 + len; uint32_t i = hdrlen + 1; if (l < total_len) { fprintf(stderr, "warning: incomplete CDO buffer %"PRIu32", expected %"PRIu32"\n", l, total_len); total_len = l; } else if (l > total_len) { l = total_len; } if (decode_v2_cmd(seq, p, &i, l, be)) { return 1; } if (i < total_len) { fprintf(stderr, "warning: mismatching CDO word count %"PRIu32", expected %"PRIu32"\n", i, total_len); } return 0; } static uint32_t checksum32(uint32_t * p, uint32_t l, uint32_t be) { uint32_t csum = 0; while (l-- > 0) csum += u32xe(*p++); return ~csum; } int is_cdo_data(void * data, size_t size) { uint32_t * p = (uint32_t *)data; uint32_t hdrlen = 0; uint32_t identification; uint32_t csum; uint32_t be = 0; if (size > 4) { hdrlen = u32xe(p[0]); if (hdrlen >= 0x10000) { be = 1; hdrlen = u32xe(p[0]); if (hdrlen >= 0x10000) return 0; } } if (hdrlen < 4 || hdrlen >= size/4) return 0; csum = checksum32(p, hdrlen, be); if (u32xe(p[hdrlen]) != csum) return 0; identification = u32xe(p[1]); if (identification != 0x584C4E58 && identification != 0x004F4443) return 0; return 1; } CdoSequence * decode_cdo_binary(const void * data, size_t size) { CdoSequence * seq; uint32_t (*decode)(CdoSequence * seq, uint32_t * p, uint32_t l, uint32_t be) = NULL; uint32_t * p = (uint32_t *)data; uint32_t hdrlen = 0; uint32_t version; uint32_t identification; uint32_t csum; uint32_t be = 0; if (size > 4) { hdrlen = u32xe(p[0]); if (hdrlen >= 0x10000) { be = 1; hdrlen = u32xe(p[0]); if (hdrlen >= 0x10000) { fprintf(stderr, "invalid header length %#"PRIx32"\n", hdrlen); return NULL; } } } if (hdrlen < 4 || hdrlen >= size/4) { fprintf(stderr, "invalid header length %"PRIu32"\n", hdrlen); return NULL; } csum = checksum32(p, hdrlen, be); if (u32xe(p[hdrlen]) != csum) { fprintf(stderr, "invalid header checksum %#"PRIx32"\n", csum); return NULL; } identification = u32xe(p[1]); version = u32xe(p[2]); if (version < CDO_VERSION_1_50) { if (identification != 0x584C4E58) { fprintf(stderr, "invalid identification word %#"PRIx32"\n", identification); return NULL; } decode = decode_v1; } else if (version < CDO_VERSION_3_00) { if (identification != 0x004F4443) { fprintf(stderr, "invalid identification word %#"PRIx32"\n", identification); return NULL; } decode = decode_v2; } else { fprintf(stderr, "unsupported version %#"PRIx32"\n", version); return NULL; } seq = cdocmd_create_sequence(); seq->version = version; if (decode(seq, p, size/4, be) != 0) { cdocmd_delete_sequence(seq); return NULL; } return seq; } static uint32_t * cdobuf; static uint32_t cdocap; static void clear_cdobuf(void) { cdobuf = NULL; cdocap = 0; } static uint32_t * grow_cdobuf(uint32_t len) { if (cdocap < len) { do { cdocap = cdocap ? cdocap * 2 : 1; } while (cdocap < len); cdobuf = (uint32_t *)realloc(cdobuf, cdocap * sizeof *cdobuf); } return cdobuf; } static void * encode_v1(CdoSequence * seq, size_t * sizep, uint32_t be) { LINK * l = seq->cmds.next; uint32_t align = 1; /* TODO: is this needed? */ uint32_t hdrlen = 4; uint32_t pos = hdrlen + 1; uint32_t * p = grow_cdobuf(pos); CdoCommand * section_cmd = NULL; uint32_t section_pos = 0; uint32_t sections = 0; uint32_t commands = 0; p[0] = u32xe(pos - 1); p[1] = u32xe(0x584C4E58); p[2] = u32xe(seq->version); if (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); if (cmd->type != CdoCmdSection) { fprintf(stderr, "missing section information\n"); clear_cdobuf(); return NULL; } } while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdSection: if (section_cmd != NULL) { p[section_pos+0] = u32xe(section_cmd->id); p[section_pos+1] = u32xe(pos - section_pos - 2); p[section_pos+2] = u32xe(commands - 1); } section_cmd = cmd; section_pos = pos; commands = 0; sections++; pos += 3; break; #if 0 case CdoCmdSetBaseAddress: fprintf(f, "set_base_address "); print_x64(f, cmd->dstaddr); fprintf(f, "\n"); break; #endif case CdoCmdComment: continue; case CdoCmdWrite: if (cmd->count == 1) { if ((cmd->dstaddr >> 32) == 0) { p = grow_cdobuf(pos + 3); p[pos++] = u32xe(CMD1_WRITE); p[pos++] = u32xe_lo(cmd->dstaddr); } else { p = grow_cdobuf(pos + 4); p[pos++] = u32xe(CMD1_WRITE64); p[pos++] = u32xe_lo(cmd->dstaddr); } } else { uint32_t offset = -(pos + 4) & (align - 1); p = grow_cdobuf(pos + 4 + offset + cmd->count); p[pos++] = u32xe(CMD1_DMA_WRITE); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(offset); while (offset-- > 0) p[pos++] = u32xe(0); } memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; #if 0 case CdoCmdSetBlock: fprintf(f, "set "); print_x64(f, cmd->dstaddr); fprintf(f, " %"PRIu32" ", cmd->count); print_x64(f, cmd->value); fprintf(f, "\n"); break; #endif case CdoCmdMaskWrite: if ((cmd->dstaddr >> 32) == 0) { p = grow_cdobuf(pos + 4); p[pos++] = u32xe(CMD1_MASK_WRITE); p[pos++] = u32xe_lo(cmd->dstaddr); } else { p = grow_cdobuf(pos + 5); p[pos++] = u32xe(CMD1_MASK_WRITE64); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); } p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); break; case CdoCmdMaskPoll: if ((cmd->dstaddr >> 32) == 0) { p = grow_cdobuf(pos + 4); p[pos++] = u32xe(CMD1_MASK_POLL); p[pos++] = u32xe_lo(cmd->dstaddr); } else { p = grow_cdobuf(pos + 5); p[pos++] = u32xe(CMD1_MASK_POLL64); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); } p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe((cmd->count + 999)/1000); break; #if 0 case CdoCmdMaskPollEq: fprintf(f, "mask_poll_eq "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; #endif case CdoCmdDelay: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_DELAY); p[pos++] = u32xe((cmd->value + 999)/1000); break; case CdoCmdDmaXfer: p = grow_cdobuf(pos + 8); p[pos++] = u32xe(CMD1_DMA_XFER); p[pos++] = u32xe_hi(cmd->srcaddr); p[pos++] = u32xe_lo(cmd->srcaddr); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->flags); if (cmd->buf) { p = grow_cdobuf(pos + cmd->count); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; } break; case CdoCmdNpiSeq: p = grow_cdobuf(pos + 3); p[pos++] = u32xe(CMD1_NPI_SEQ); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdNpiPreCfg: p = grow_cdobuf(pos + 3); p[pos++] = u32xe(CMD1_NPI_PRECFG); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdNpiWrite: p = grow_cdobuf(pos + 4 + cmd->count); p[pos++] = u32xe(CMD1_NPI_WRITE); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe(cmd->count); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdNpiShutdown: p = grow_cdobuf(pos + 3); p[pos++] = u32xe(CMD1_NPI_SHUTDN); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuSetCrc32: p = grow_cdobuf(pos + 3); p[pos++] = u32xe(CMD1_CFU_SET_CRC32); p[pos++] = u32xe(cmd->flags); if (cmd->flags != 0) { p[pos++] = u32xe(cmd->value); } break; case CdoCmdCfuDecompress: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_DECOMPRESS); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuCramRW: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_CRAM_RW); p[pos++] = u32xe(cmd->value); break; case CdoCmdCfuSeuGo: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_SEU_GO); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuCrc8Dis: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_CRC8_DIS); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuSsiPerSlrPr: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_SSI_PER_SLR_PR); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuGsrGsc: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_GSR_GSC); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuGcapClkEn: p = grow_cdobuf(pos + 2); p[pos++] = u32xe(CMD1_CFU_GCAP_CLK_EN); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCframeRead: if (cmd->count != 16) { fprintf(stderr, "error: cfu_cframe_read must have length 16, got %u\n", cmd->count); } p = grow_cdobuf(pos + 4 + cmd->count); p[pos++] = u32xe(CMD1_CFU_CFRAME_READ); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->value); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; default: fprintf(stderr, "unknown command (%u)\n", cmd->type); break; } commands++; } assert(section_cmd != NULL); p[section_pos+0] = u32xe(section_cmd->id); p[section_pos+1] = u32xe(pos - section_pos - 2); p[section_pos+2] = u32xe(commands - 1); p[3] = u32xe(sections); p[hdrlen] = u32xe(checksum32(p, hdrlen, be)); clear_cdobuf(); *sizep = pos*4; return p; } static void hdr2l(uint32_t ** bufp, uint32_t * posp, uint32_t cmd, uint32_t len, uint32_t be, uint32_t long_header) { uint32_t * p = *bufp; uint32_t pos = *posp; if (len < 255 && !long_header) { p = grow_cdobuf(pos + len + 1); p[pos++] = u32xe((len << 16) | cmd); } else { p = grow_cdobuf(pos + len + 2); p[pos++] = u32xe((255 << 16) | cmd); p[pos++] = u32xe(len); } *bufp = p; *posp = pos; } static void hdr2(uint32_t ** bufp, uint32_t * posp, uint32_t cmd, uint32_t len, uint32_t be) { hdr2l(bufp, posp, cmd, len, be, 0); } static LINK * find_block_end(LINK * l, LINK * lh) { uint32_t level = 0; while (l != lh) { CdoCommand * cmd = all2cmds(l); switch (cmd->type) { case CdoCmdProc: case CdoCmdPsmSequence: case CdoCmdBegin: level++; break; case CdoCmdEnd: if (level == 0) return l; level--; break; default: break; } l = l->next; } return lh; } static void * encode_v2_cmd(uint32_t version, LINK * l, LINK * lh, uint32_t * posp, uint32_t be, uint32_t * aligned_commandp) { uint32_t pos = *posp; uint32_t * p = grow_cdobuf(pos); uint32_t aligned_command = 0; while (l != lh) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { #if 0 case CdoCmdSetBaseAddress: fprintf(f, "set_base_address "); print_x64(f, cmd->dstaddr); fprintf(f, "\n"); break; #endif case CdoCmdGeneric: hdr2(&p, &pos, cmd->id, cmd->count, be); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdComment: break; case CdoCmdWrite: if (cmd->count == 1) { if ((cmd->dstaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_WRITE, 2, be); p[pos++] = u32xe_lo(cmd->dstaddr); } else { hdr2(&p, &pos, CMD2_WRITE64, 3, be); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); } memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; } else { uint32_t padding = 0; uint32_t pos_save = pos; uint64_t dstaddr = cmd->dstaddr; uint32_t count = cmd->count; uint32_t count2 = 0; void * buf = cmd->buf; if (auto_align && dstaddr >= 0xf6000000 && dstaddr < 0xf8000000) { /* DMA writes to NPI must be 16 byte aligned on * both address and size (EDT-983251) */ while (count > 0 && ((dstaddr >> 2) & 3) != 0) { if ((dstaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_WRITE, 2, be); p[pos++] = u32xe_lo(dstaddr); } else { hdr2(&p, &pos, CMD2_WRITE64, 3, be); p[pos++] = u32xe_hi(dstaddr); p[pos++] = u32xe_lo(dstaddr); } memcpy(p + pos, buf, sizeof(uint32_t)); byte_swap_buffer(p + pos, 1, be); pos++; dstaddr += sizeof(uint32_t); buf = (char *)buf + sizeof(uint32_t); count--; } count2 = count & 3; count -= count2; pos_save = pos; } do { assert(padding < 4); if (padding) { hdr2(&p, &pos, CMD2_NOP, padding - 1, be); memset(p + pos, 0, (padding - 1)*4); pos += padding - 1; } hdr2(&p, &pos, CMD2_DMA_WRITE, 2 + count, be); p[pos++] = u32xe_hi(dstaddr); p[pos++] = u32xe_lo(dstaddr); if (!auto_align) break; aligned_command = 1; if ((pos & 3) == ((dstaddr >> 2) & 3)) break; padding++; pos = pos_save; } while (1); memcpy(p + pos, buf, count * sizeof(uint32_t)); byte_swap_buffer(p + pos, count, be); pos += count; if (count2 > 0) { dstaddr += count * sizeof(uint32_t); buf = (char *)buf + count * sizeof(uint32_t); while (count2 > 0) { if ((dstaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_WRITE, 2, be); p[pos++] = u32xe_lo(dstaddr); } else { hdr2(&p, &pos, CMD2_WRITE64, 3, be); p[pos++] = u32xe_hi(dstaddr); p[pos++] = u32xe_lo(dstaddr); } memcpy(p + pos, buf, sizeof(uint32_t)); byte_swap_buffer(p + pos, 1, be); pos++; dstaddr += sizeof(uint32_t); buf = (char *)buf + sizeof(uint32_t); count2--; } } } break; case CdoCmdWriteKeyhole: { uint32_t padding = 0; uint32_t pos_save = pos; do { assert(padding < 4); if (padding) { hdr2(&p, &pos, CMD2_NOP, padding - 1, be); memset(p + pos, 0, (padding - 1)*4); pos += padding - 1; } hdr2(&p, &pos, CMD2_DMA_WRITE_KEYHOLE, 3 + cmd->count, be); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->value); if (!auto_align) break; aligned_command = 1; if ((pos & 3) == ((cmd->dstaddr >> 2) & 3)) break; padding++; pos = pos_save; } while (1); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; } case CdoCmdSetBlock: hdr2(&p, &pos, CMD2_SET, 4, be); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->value); break; case CdoCmdMaskWrite: if ((cmd->dstaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_MASK_WRITE, 3, be); p[pos++] = u32xe_lo(cmd->dstaddr); } else { hdr2(&p, &pos, CMD2_MASK_WRITE64, 4, be); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); } p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); break; case CdoCmdListSet: hdr2(&p, &pos, CMD2_LIST_SET, 1 + cmd->count, be); p[pos++] = u32xe_lo(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdRunProc: hdr2(&p, &pos, CMD2_RUN_PROC, 1, be); p[pos++] = u32xe_lo(cmd->id); break; case CdoCmdListWrite: hdr2(&p, &pos, CMD2_LIST_WRITE, 2, be); p[pos++] = u32xe_lo(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdListMaskWrite: hdr2(&p, &pos, CMD2_LIST_MASK_WRITE, 3, be); p[pos++] = u32xe_lo(cmd->id); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); break; case CdoCmdListMaskPoll: { uint32_t has_flags = cmd->flags != 0; hdr2(&p, &pos, CMD2_LIST_MASK_POLL, has_flags ? 5 : 4, be); p[pos++] = u32xe_lo(cmd->id); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->count); if (has_flags) { p[pos++] = u32xe(cmd->flags); } break; } case CdoCmdMaskPoll: { uint32_t has_flags = cmd->flags != 0; uint32_t has_errorcode = cmd->errorcode != 0; if ((cmd->dstaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_MASK_POLL, has_errorcode ? 6: (has_flags ? 5 : 4), be); p[pos++] = u32xe_lo(cmd->dstaddr); } else { hdr2(&p, &pos, CMD2_MASK_POLL64, has_errorcode ? 7: (has_flags ? 6 : 5), be); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); } p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->count); if (has_flags || has_errorcode) { p[pos++] = u32xe(cmd->flags); } if (has_errorcode) { p[pos++] = u32xe(cmd->errorcode); } break; } #if 0 case CdoCmdMaskPollEq: fprintf(f, "mask_poll_eq "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; #endif case CdoCmdDelay: hdr2(&p, &pos, CMD2_DELAY, 1, be); p[pos++] = u32xe(cmd->value); break; case CdoCmdDmaXfer: hdr2(&p, &pos, CMD2_DMA_XFER, 6, be); p[pos++] = u32xe_hi(cmd->srcaddr); p[pos++] = u32xe_lo(cmd->srcaddr); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCframeRead: { uint32_t padding = 0; uint32_t pos_save = pos; do { assert(padding < 4); if (padding) { hdr2(&p, &pos, CMD2_NOP, padding - 1, be); memset(p + pos, 0, (padding - 1)*4); pos += padding - 1; } hdr2(&p, &pos, CMD2_CFRAME_READ, 4 + cmd->count, be); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->value); if (!auto_align) break; aligned_command = 1; if ((pos & 3) == 0) break; padding++; pos = pos_save; } while (1); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; } case CdoCmdSsitSyncMaster: if (search_sync_points) { num_of_sync_points++; slr_sync_points = (uint32_t *)realloc(slr_sync_points, num_of_sync_points * sizeof(uint32_t)); memcpy(slr_sync_points + (num_of_sync_points - 1), &pos, 4); } hdr2(&p, &pos, CMD2_SSIT_SYNC_MASTER, 0, be); break; case CdoCmdSsitSyncSlaves: if (search_sync_points) { num_of_sync_points++; slr_sync_points = (uint32_t *)realloc(slr_sync_points, num_of_sync_points * sizeof(uint32_t)); memcpy(slr_sync_points + (num_of_sync_points - 1), &pos, 4); } hdr2(&p, &pos, CMD2_SSIT_SYNC_SLAVES, 2, be); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->count); break; case CdoCmdSsitWaitSlaves: hdr2(&p, &pos, CMD2_SSIT_WAIT_SLAVES, 2, be); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->count); break; case CdoCmdNop: hdr2(&p, &pos, CMD2_NOP, cmd->count, be); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdEventLogging: hdr2(&p, &pos, CMD2_EVENT_LOGGING, 1 + cmd->count, be); p[pos++] = u32xe(cmd->value); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdSetBoard: { uint32_t len = strlen((char *)cmd->buf); uint32_t count = (len + 3)/4; hdr2(&p, &pos, CMD2_SET_BOARD, count, be); memset(p + pos, 0, count*4); memcpy(p + pos, cmd->buf, len); byte_swap_buffer(p + pos, count, be); pos += count; break; } case CdoCmdSetPlmWdt: hdr2(&p, &pos, CMD2_SET_PLM_WDT, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdLogString: { uint32_t len = strlen((char *)cmd->buf); uint32_t count = (len + 3)/4; hdr2(&p, &pos, CMD2_LOG_STRING, count, be); memset(p + pos, 0, count*4); memcpy(p + pos, cmd->buf, len); byte_swap_buffer(p + pos, count, be); pos += count; break; } case CdoCmdLogAddress: if ((cmd->srcaddr >> 32) == 0) { hdr2(&p, &pos, CMD2_LOG_ADDRESS, 1, be); p[pos++] = u32xe_lo(cmd->srcaddr); } else { hdr2(&p, &pos, CMD2_LOG_ADDRESS, 2, be); p[pos++] = u32xe_lo(cmd->srcaddr); p[pos++] = u32xe_hi(cmd->srcaddr); } break; case CdoCmdMarker: { uint32_t len = strlen((char *)cmd->buf); uint32_t count = (len + 3)/4; if (cmd->value == MARKER_DEVICE || cmd->value == MARKER_DATE) { break; } if (cmd->value == MARKER_PART) { id_code_binary = find_device((char*)cmd->buf); } /* Search for the START markers with string "NOC Start up", only for SSIT devices */ if (search_sync_points && (cmd->value == 0x64 || cmd->value == 0x65) && (strcmp((char*)cmd->buf, "NOC Startup") == 0)) { /* Store the offset of each of the START and END marker with "NOC Start up" string */ if (cmd->value == 0x64) { num_start_markers++; noc_start_markers = (uint32_t *)realloc(noc_start_markers, num_start_markers * 2 * sizeof(uint32_t)); memcpy(noc_start_markers + (num_start_markers - 1), &pos, 4); } else { num_end_markers++; noc_end_markers = (uint32_t *)realloc(noc_end_markers, num_end_markers * 2 * sizeof(uint32_t)); memcpy(noc_end_markers + (num_end_markers - 1), &pos, 4); } } hdr2(&p, &pos, CMD2_MARKER, 1 + count, be); p[pos++] = u32xe(cmd->value); memset(p + pos, 0, count*4); memcpy(p + pos, cmd->buf, len); byte_swap_buffer(p + pos, count, be); pos += count; break; } case CdoCmdProc: { uint32_t pos_save = pos; uint32_t long_header = 0; uint32_t aligned_proc_command = 0; LINK * blockend = find_block_end(l, lh); for (;;) { uint32_t hdr_len = long_header ? 2 : 1; uint32_t payload_start; uint32_t restart = 0; uint32_t pos_hdr; pos = pos_save; if (aligned_proc_command && auto_align && ((pos + hdr_len + 1) & 3) != 0) { /* Align proc if it contains commands that require alignment */ uint32_t padding = 4 - ((pos + hdr_len + 1) & 3); hdr2(&p, &pos, CMD2_NOP, padding - 1, be); memset(p + pos, 0, (padding - 1)*4); pos += padding - 1; } /* Remember header location and reserve space */ pos_hdr = pos; hdr2l(&p, &pos, CMD2_PROC, 1, be, long_header); payload_start = pos; p[pos++] = u32xe(cmd->value); /* Store commands as payload */ p = encode_v2_cmd(version, l, blockend, &pos, be, &aligned_proc_command); /* Store header in reserved space. */ hdr2l(&p, &pos_hdr, CMD2_PROC, pos - payload_start, be, long_header); if (pos_hdr != payload_start) { /* Header grew, restart with long header */ assert(!long_header); assert(pos_hdr - payload_start == 1); long_header = 1; restart = 1; } if (aligned_proc_command) { aligned_command = 1; if (auto_align && ((pos_hdr + 1) & 3) != 0) { /* Update padding. */ restart = 1; } } if (!restart) break; } l = blockend; if (l != lh) l = l->next; break; } case CdoCmdCdoSequence: { uint32_t pos_save = pos; uint32_t long_header = 0; uint32_t aligned_cdo_command = 0; LINK * blockend = find_block_end(l, lh); for (;;) { uint32_t hdr_len = long_header ? 2 : 1; uint32_t payload_start; uint32_t restart = 0; uint32_t pos_hdr; pos = pos_save; if (aligned_cdo_command && auto_align && ((pos + hdr_len + 3) & 3) != 0) { /* Align command if it contains commands that require alignment */ uint32_t padding = 4 - ((pos + hdr_len + 3) & 3); hdr2(&p, &pos, CMD2_NOP, padding - 1, be); memset(p + pos, 0, (padding - 1)*4); pos += padding - 1; } /* Remember header location and reserve space */ pos_hdr = pos; hdr2l(&p, &pos, CMD2_CDO_SEQUENCE, 3, be, long_header); payload_start = pos; p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->value); /* Store commands as payload */ p = encode_v2_cmd(version, l, blockend, &pos, be, &aligned_cdo_command); /* Store header in reserved space. */ hdr2l(&p, &pos_hdr, CMD2_CDO_SEQUENCE, pos - payload_start, be, long_header); if (pos_hdr != payload_start) { /* Header grew, restart with long header */ assert(!long_header); assert(pos_hdr - payload_start == 1); long_header = 1; restart = 1; } if (aligned_cdo_command) { aligned_command = 1; if (auto_align && ((pos_hdr + 3) & 3) != 0) { /* Update padding. */ restart = 1; } } if (!restart) break; } l = blockend; if (l != lh) l = l->next; break; } case CdoCmdBegin: { uint32_t len = strlen((char *)cmd->buf); uint32_t count = (len + 3)/4; LINK * blockend = find_block_end(l, lh); uint32_t payload_start; hdr2(&p, &pos, CMD2_BLOCK_BEGIN, 1 + count, be); payload_start = pos++; memset(p + pos, 0, count*4); memcpy(p + pos, cmd->buf, len); byte_swap_buffer(p + pos, count, be); pos += count; p = encode_v2_cmd(version, l, blockend, &pos, be, &aligned_command); p[payload_start] = u32xe(pos - payload_start - 1); l = blockend; break; } case CdoCmdEnd: hdr2(&p, &pos, CMD2_BLOCK_END, 0, be); break; case CdoCmdBreak: if (cmd->value == 1) { hdr2(&p, &pos, CMD2_BREAK, 0, be); } else { hdr2(&p, &pos, CMD2_BREAK, 1, be); p[pos++] = u32xe(cmd->value); } break; case CdoCmdOtCheck: hdr2(&p, &pos, CMD2_OT_CHECK, 1, be); p[pos++] = u32xe(cmd->value); break; case CdoCmdPsmSequence: { uint32_t pos_save = pos; uint32_t payload_start; LINK * blockend = find_block_end(l, lh); hdr2(&p, &pos, CMD2_PSM_SEQUENCE, 0, be); payload_start = pos; p = encode_v2_cmd(version, l, blockend, &pos, be, &aligned_command); hdr2(&p, &pos_save, CMD2_PSM_SEQUENCE, pos - payload_start, be); if (pos_save != payload_start) { /* Header grew, regenerate payload */ pos = pos_save; p = encode_v2_cmd(version, l, blockend, &pos, be, &aligned_command); } l = blockend; if (l != lh) l = l->next; break; } case CdoCmdScatterWrite: hdr2(&p, &pos, CMD2_SCATTER_WRITE, 1 + cmd->count, be); p[pos++] = u32xe(cmd->value); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdScatterWrite2: hdr2(&p, &pos, CMD2_SCATTER_WRITE2, 2 + cmd->count, be); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->mask); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdTamperTrigger: hdr2(&p, &pos, CMD2_TAMPER_TRIGGER, 1, be); p[pos++] = u32xe(cmd->value); break; case CdoCmdSetIpiAccess: hdr2(&p, &pos, CMD2_SET_IPI_ACCESS, 2, be); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->mask); break; case CdoCmdNpiSeq: if (version >= CDO_VERSION_2_00) goto npi_error; hdr2(&p, &pos, CMD2_NPI_SEQ, 2, be); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdNpiPreCfg: if (version >= CDO_VERSION_2_00) goto npi_error; hdr2(&p, &pos, CMD2_NPI_PRECFG, 2, be); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdNpiWrite: if (version >= CDO_VERSION_2_00) goto npi_error; hdr2(&p, &pos, CMD2_NPI_WRITE, 2 + cmd->count, be); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdNpiShutdown: if (version >= CDO_VERSION_2_00) goto npi_error; hdr2(&p, &pos, CMD2_NPI_SHUTDN, 2, be); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmHnicxNpiDataXfer: hdr2(&p, &pos, CMD2_PM_HNICX_NPI_DATA_XFER, 2, be); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmGetApiVersion: hdr2(&p, &pos, CMD2_PM_GET_API_VERSION, 0, be); break; case CdoCmdPmGetDeviceStatus: hdr2(&p, &pos, CMD2_PM_GET_DEVICE_STATUS, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmRegisterNotifier: hdr2(&p, &pos, CMD2_PM_REGISTER_NOTIFIER, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->count); break; case CdoCmdPmRequestSuspend: hdr2(&p, &pos, CMD2_PM_REQUEST_SUSPEND, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmSelfSuspend: hdr2(&p, &pos, CMD2_PM_SELF_SUSPEND, 5, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe_hi(cmd->dstaddr); break; case CdoCmdPmForcePowerdown: hdr2(&p, &pos, CMD2_PM_FORCE_POWERDOWN, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmAbortSuspend: hdr2(&p, &pos, CMD2_PM_ABORT_SUSPEND, 2, be); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmRequestWakeup: hdr2(&p, &pos, CMD2_PM_REQUEST_WAKEUP, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe_lo(cmd->dstaddr); p[pos++] = u32xe_hi(cmd->dstaddr); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmSetWakeupSource: hdr2(&p, &pos, CMD2_PM_SET_WAKEUP_SOURCE, 3, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmSystemShutdown: hdr2(&p, &pos, CMD2_PM_SYSTEM_SHUTDOWN, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmRequestDevice: hdr2(&p, &pos, CMD2_PM_REQUEST_DEVICE, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmReleaseDevice: hdr2(&p, &pos, CMD2_PM_RELEASE_DEVICE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmSetRequirement: hdr2(&p, &pos, CMD2_PM_SET_REQUIREMENT, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->count); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmSetMaxLatency: hdr2(&p, &pos, CMD2_PM_SET_MAX_LATENCY, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->count); break; case CdoCmdPmResetAssert: hdr2(&p, &pos, CMD2_PM_RESET_ASSERT, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmResetGetStatus: hdr2(&p, &pos, CMD2_PM_RESET_GET_STATUS, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmPinctrlRequest: hdr2(&p, &pos, CMD2_PM_PINCTRL_REQUEST, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmPinctrlRelease: hdr2(&p, &pos, CMD2_PM_PINCTRL_RELEASE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmPinctrlGetFunction: hdr2(&p, &pos, CMD2_PM_PINCTRL_GET_FUNCTION, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmPinctrlSetFunction: hdr2(&p, &pos, CMD2_PM_PINCTRL_SET_FUNCTION, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmPinctrlConfigParamGet: hdr2(&p, &pos, CMD2_PM_PINCTRL_CONFIG_PARAM_GET, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmPinctrlConfigParamSet: hdr2(&p, &pos, CMD2_PM_PINCTRL_CONFIG_PARAM_SET, 3, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmIoctl: hdr2(&p, &pos, CMD2_PM_IOCTL, 2 + cmd->count, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmQueryData: hdr2(&p, &pos, CMD2_PM_QUERY_DATA, 1 + cmd->count, be); p[pos++] = u32xe(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmClockEnable: hdr2(&p, &pos, CMD2_PM_CLOCK_ENABLE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmClockDisable: hdr2(&p, &pos, CMD2_PM_CLOCK_DISABLE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmClockGetState: hdr2(&p, &pos, CMD2_PM_CLOCK_GETSTATE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmClockSetDivider: hdr2(&p, &pos, CMD2_PM_CLOCK_SETDIVIDER, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmClockGetDivider: hdr2(&p, &pos, CMD2_PM_CLOCK_GETDIVIDER, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmClockSetRate: hdr2(&p, &pos, CMD2_PM_CLOCK_SETRATE, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmClockGetRate: hdr2(&p, &pos, CMD2_PM_CLOCK_GETRATE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmClockSetParent: hdr2(&p, &pos, CMD2_PM_CLOCK_SETPARENT, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmClockGetParent: hdr2(&p, &pos, CMD2_PM_CLOCK_GETPARENT, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmPllSetParameter: hdr2(&p, &pos, CMD2_PM_PLL_SET_PARAMETER, 3, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmPllGetParameter: hdr2(&p, &pos, CMD2_PM_PLL_GET_PARAMETER, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); break; case CdoCmdPmPllSetMode: hdr2(&p, &pos, CMD2_PM_PLL_SET_MODE, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmPllGetMode: hdr2(&p, &pos, CMD2_PM_PLL_GET_MODE, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmAddSubsystem: hdr2(&p, &pos, CMD2_PM_ADD_SUBSYSTEM, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmDestroySubsystem: hdr2(&p, &pos, CMD2_PM_DESTROY_SUBSYSTEM, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmDescribeNodes: hdr2(&p, &pos, CMD2_PM_DESCRIBE_NODES, 0 + cmd->count, be); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmAddNode: hdr2(&p, &pos, CMD2_PM_ADD_NODE, 1 + cmd->count, be); p[pos++] = u32xe(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmAddNodeParent: hdr2(&p, &pos, CMD2_PM_ADD_NODE_PARENT, 1 + cmd->count, be); p[pos++] = u32xe(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmAddNodeName: { uint32_t len = strlen((char *)cmd->buf); uint32_t count = (len + 3)/4; /* This should not be necessary, but its there for now to * avoid null termination issues in libpm. */ if (count < 4) count = 4; hdr2(&p, &pos, CMD2_PM_ADD_NODE_NAME, 1 + count, be); p[pos++] = u32xe(cmd->id); memset(p + pos, 0, count*4); memcpy(p + pos, cmd->buf, len); byte_swap_buffer(p + pos, count, be); pos += count; break; } case CdoCmdPmAddRequirement: hdr2(&p, &pos, CMD2_PM_ADD_REQUIREMENT, 3 + cmd->count, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->flags); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmSetCurrentSubsystem: hdr2(&p, &pos, CMD2_PM_SET_CURRENT_SUBSYSTEM, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmInitNode: hdr2(&p, &pos, CMD2_PM_INIT_NODE, 2 + cmd->count, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmFeatureCheck: hdr2(&p, &pos, CMD2_PM_FEATURE_CHECK, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmIsoControl: hdr2(&p, &pos, CMD2_PM_ISO_CONTROL, 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); break; case CdoCmdPmBisr: hdr2(&p, &pos, CMD2_PM_BISR, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmApplyTrim: hdr2(&p, &pos, CMD2_PM_APPLY_TRIM, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmNocClockEnable: hdr2(&p, &pos, CMD2_PM_NOC_CLOCK_ENABLE, 1 + cmd->count, be); p[pos++] = u32xe(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmIfNocClockEnable: hdr2(&p, &pos, CMD2_PM_IF_NOC_CLOCK_ENABLE, cmd->flags != 1 ? 3 : 2, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); if (cmd->flags != 1) { p[pos++] = u32xe(cmd->flags); } break; case CdoCmdPmActivateSubsystem: hdr2(&p, &pos, CMD2_PM_ACTIVATE_SUBSYSTEM, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdPmSetNodeAccess: hdr2(&p, &pos, CMD2_PM_SET_NODE_ACCESS, 1 + cmd->count, be); p[pos++] = u32xe(cmd->id); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; case CdoCmdPmForceHc: hdr2(&p, &pos, CMD2_PM_FORCE_HC, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdCfuSetCrc32: if (version >= CDO_VERSION_2_00) goto cfu_error; if (cmd->flags != 0) { hdr2(&p, &pos, CMD2_CFU_SET_CRC32, 2, be); p[pos++] = u32xe(cmd->flags); p[pos++] = u32xe(cmd->value); } else { hdr2(&p, &pos, CMD2_CFU_SET_CRC32, 1, be); p[pos++] = u32xe(cmd->flags); } break; case CdoCmdCfuDecompress: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_DECOMPRESS, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuCramRW: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_CRAM_RW, 1, be); p[pos++] = u32xe(cmd->value); break; case CdoCmdCfuSeuGo: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_SEU_GO, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuCrc8Dis: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_CRC8_DIS, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuSsiPerSlrPr: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_SSI_PER_SLR_PR, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuGsrGsc: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_GSR_GSC, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuGcapClkEn: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_GCAP_CLK_EN, 1, be); p[pos++] = u32xe(cmd->flags); break; case CdoCmdCfuCfiType: if (version >= CDO_VERSION_2_00) goto cfu_error; hdr2(&p, &pos, CMD2_CFU_CFI_TYPE, 1, be); p[pos++] = u32xe(cmd->value); break; case CdoCmdEmSetAction: hdr2(&p, &pos, CMD2_EM_SET_ACTION, 3, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->mask); break; case CdoCmdLdrSetImageInfo: hdr2(&p, &pos, CMD2_LDR_SET_IMAGE_INFO, 4, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->value); p[pos++] = u32xe(cmd->mask); p[pos++] = u32xe(cmd->count); break; case CdoCmdLdrCframeClearCheck: hdr2(&p, &pos, CMD2_LDR_CFRAME_CLEAR_CHECK, 1, be); p[pos++] = u32xe(cmd->id); break; case CdoCmdSemNpiTable: hdr2(&p, &pos, CMD2_SEM_NPI_TABLE, 2 + cmd->count, be); p[pos++] = u32xe(cmd->id); p[pos++] = u32xe(cmd->flags); memcpy(p + pos, cmd->buf, cmd->count * sizeof(uint32_t)); byte_swap_buffer(p + pos, cmd->count, be); pos += cmd->count; break; default: fprintf(stderr, "unknown command (%u)\n", cmd->type); break; npi_error: fprintf(stderr, "npi related commands are not supported in CDO version 2 or newer\n"); break; cfu_error: fprintf(stderr, "cfu related commands are not supported in CDO version 2 or newer\n"); break; } } if (aligned_commandp) *aligned_commandp = aligned_command; *posp = pos; return p; } static void * encode_v2(CdoSequence * seq, size_t * sizep, uint32_t be) { LINK * l = seq->cmds.next; uint32_t hdrlen = 4; uint32_t pos = hdrlen + 1; uint32_t * p = grow_cdobuf(pos); p[0] = u32xe(pos - 1); p[1] = u32xe(0x004F4443); p[2] = u32xe(seq->version); p = encode_v2_cmd(seq->version, l, &seq->cmds, &pos, be, NULL); p[3] = u32xe(pos - hdrlen - 1); p[4] = u32xe(checksum32(p, hdrlen, be)); clear_cdobuf(); *sizep = pos*4; return p; } void cdoseq_write_header_raw(FILE * f, CdoSequence ** seq) { LINK * l = (*seq)->cmds.next; char * buf; fprintf(f, "Xilinx ASCII NPI Deviceimage\n"); while (l != &((*seq)->cmds)) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type != CdoCmdMarker) { /* header markers are at the top */ break; } switch (cmd->value) { case 1: buf = "Created by"; break; case 2: buf = "Design name:"; break; case 3: buf = "Architecture:"; break; case 4: buf = "Part:"; break; case 5: buf = "SLR:"; break; case 6: buf = "Date:"; break; default: buf = NULL; break; } if (buf) { fprintf(f, "%s %s\n", buf, (char *)cmd->buf); cdocmd_free(cmd); } } } void * cdoseq_to_binary(CdoSequence * seq, size_t * sizep, uint32_t be) { void * (*encode)(CdoSequence * seq, size_t * sizep, uint32_t be) = NULL; *sizep = 0; if (seq->version < CDO_VERSION_1_50) { encode = encode_v1; } else if (seq->version < CDO_VERSION_3_00) { encode = encode_v2; } else { fprintf(stderr, "unsupported version %#"PRIx32"\n", seq->version); return NULL; } return encode(seq, sizep, be); } void search_for_sync_points(void) { num_of_sync_points = 0; num_start_markers = 0; num_end_markers = 0; search_sync_points = 1; slr_sync_points = NULL; noc_start_markers = NULL; noc_end_markers = NULL; } uint32_t* get_slr_sync_point_offsets(void) { search_sync_points = 0; return slr_sync_points; } uint32_t* get_slr_start_marker_offsets(void) { search_sync_points = 0; return noc_start_markers; } uint32_t* get_slr_end_marker_offsets(void) { search_sync_points = 0; return noc_end_markers; } size_t get_num_of_sync_points(void) { return num_of_sync_points; } size_t get_num_start_markers(void) { return num_start_markers; } size_t get_num_end_markers(void) { return num_end_markers; } xilinx-bootgen-2024.2/cdo-binary.h000077500000000000000000000034771475706442400170040ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_binary #define D_cdo_binary #include "cdo-command.h" typedef struct { uint8_t cmd_id; uint8_t module_id; uint16_t reserved1; uint8_t min_arg_cnt; uint8_t max_arg_cnt; uint16_t reserved2; } XPlmi_CmdInfo; void cdobinary_set_verbose(uint32_t verbose); void cdobinary_set_auto_align(uint32_t enable); void cdobinary_set_add_offset(uint32_t enable); CdoSequence * decode_cdo_binary(const void * data, size_t len); void cdoseq_write_header_raw(FILE * f, CdoSequence ** seq); void * cdoseq_to_binary(CdoSequence * seq, size_t * sizep, uint32_t be); int check_cdo_commands(void* data, uint32_t l, uint32_t * xplm_data, uint32_t xplm_length); int is_cdo_data(void * data, size_t size); uint32_t* get_slr_sync_point_offsets(void); uint32_t* get_slr_start_marker_offsets(void); uint32_t* get_slr_end_marker_offsets(void); void search_for_sync_points(void); size_t get_num_of_sync_points(void); size_t get_num_start_markers(void); size_t get_num_end_markers(void); uint32_t idcode_from_binary(uint32_t id); #endif /* D_cdo_binary */ xilinx-bootgen-2024.2/cdo-command.c000077500000000000000000001165721475706442400171320ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include #include #include "cdo-alloc.h" #include "cdo-command.h" UserKeys user_keys; static CdoSequence * default_seq; #define USER_KEYS_BASE_ADDR 0xF11E0110 #define USER_KEYS_END_ADDR 0xF11E020C #define USER_KEY_OFFSET 0x20 void cdocmd_free(CdoCommand * cmd) { if (!list_is_empty(&cmd->link_all)) list_remove(&cmd->link_all); if (cmd->buf) myfree(cmd->buf); myfree(cmd); } CdoCommand * cdocmd_alloc(CdoCmdType type) { CdoCommand * cmd = (CdoCommand *)myalloc_zero(sizeof *cmd); cmd->type = type; return cmd; }; CdoSequence * cdocmd_create_sequence(void) { CdoSequence * seq = myalloc_zero(sizeof *seq); seq->version = DEFAULT_CDO_VERSION; list_init(&seq->cmds); return seq; } void cdocmd_delete_sequence(CdoSequence * seq) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; cdocmd_free(cmd); } myfree(seq); } static void * copy_buf(void * buf, uint32_t count, uint32_t be) { uint32_t * p = NULL; if (buf != NULL) { p = myalloc(count * 4); memcpy(p, buf, count * 4); if (is_be_host() != be) { uint32_t i; for (i = 0; i < count; i++) { p[i] = u32swap(p[i]); } } } return p; } CdoCommand * cdocmd_duplicate(CdoCommand * origcmd) { CdoCommand * cmd = (CdoCommand *)myalloc(sizeof *cmd); *cmd = *origcmd; list_init(&cmd->link_all) cmd->buf = copy_buf(cmd->buf, cmd->count, is_be_host()); return cmd; } void cdocmd_set_default_sequence(CdoSequence * seq) { default_seq = seq; } static void add_command(CdoSequence * seq, CdoCommand * cmd) { /* Append cmd to sequence */ if (seq == NULL) seq = default_seq; list_add_last(&cmd->link_all, &seq->cmds); } void cdocmd_append_command(CdoSequence * seq, CdoCommand * newcmd) { /* Append newcmd to sequence */ if (!list_is_empty(&newcmd->link_all)) list_remove(&newcmd->link_all); add_command(seq, newcmd); } void cdocmd_insert_command(CdoCommand * cmd, CdoCommand * newcmd) { /* Insert newcmd before cmd */ if (!list_is_empty(&newcmd->link_all)) list_remove(&newcmd->link_all); list_add_last(&newcmd->link_all, &cmd->link_all); } static int myrand(void) { static unsigned long next; static int firsttime = 1; if (firsttime) { firsttime = 0; next = time(NULL); } next = next * 1103515245 + 12345; return((unsigned)(next/65536) % 32768); } static uint8_t randchar() { static char chrs[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return chrs[myrand() % (sizeof chrs - 1)]; } static uint32_t randu32() { uint32_t width = myrand() & 3; uint32_t value = myrand() & 255; while (width-- > 0) { value <<= 8; value |= myrand() & 255; } return value; } static uint64_t randu64() { uint64_t width = myrand() & 7; uint64_t value = myrand() & 255; while (width-- > 0) { value <<= 8; value |= myrand() & 255; } return value; } void cdocmd_add_random_command(CdoSequence * seq, uint32_t * levelp) { uint32_t level = *levelp; CdoCmdType type; CdoCommand * cmd; do { type = randu32() % CdoCmdLast; } while (type == CdoCmdGeneric || type == CdoCmdSection || type == CdoCmdInclude || type == CdoCmdComment || type == CdoCmdSetBaseAddress || (type == CdoCmdProc && level != 0) || (type == CdoCmdPsmSequence && level != 0) || (type == CdoCmdCdoSequence && level != 0) || (type == CdoCmdBegin && level >= (randu32() & 3)) || (type == CdoCmdEnd && level == 0) || (type == CdoCmdBreak && level == 0) || (seq->version >= CDO_VERSION_2_00 && ( type == CdoCmdNpiPreCfg || type == CdoCmdNpiSeq || type == CdoCmdNpiWrite || type == CdoCmdNpiShutdown || type == CdoCmdCfuSetCrc32 || type == CdoCmdCfuDecompress || type == CdoCmdCfuCramRW || type == CdoCmdCfuSeuGo || type == CdoCmdCfuCrc8Dis || type == CdoCmdCfuSsiPerSlrPr || type == CdoCmdCfuGsrGsc || type == CdoCmdCfuGcapClkEn || type == CdoCmdCfuCfiType))); cmd = cdocmd_alloc(type); cmd->id = randu32(); cmd->dstaddr = randu64(); cmd->srcaddr = randu64(); cmd->mask = randu32(); cmd->value = randu32(); cmd->count = randu32(); cmd->flags = randu32(); if (cmd->type == CdoCmdMaskPoll) { if ((randu32() & 3) == 0) cmd->flags = 0; } if (cmd->type == CdoCmdNpiPreCfg || cmd->type == CdoCmdNpiSeq || cmd->type == CdoCmdNpiWrite || cmd->type == CdoCmdNpiShutdown) { cmd->dstaddr &= 0xffffffff; } if (cmd->type == CdoCmdWrite || cmd->type == CdoCmdWriteKeyhole || cmd->type == CdoCmdDmaXfer || cmd->type == CdoCmdCframeRead || cmd->type == CdoCmdNop || cmd->type == CdoCmdEventLogging || cmd->type == CdoCmdScatterWrite || cmd->type == CdoCmdScatterWrite2 || cmd->type == CdoCmdNpiWrite || cmd->type == CdoCmdPmIoctl || cmd->type == CdoCmdPmQueryData || cmd->type == CdoCmdPmDescribeNodes || cmd->type == CdoCmdPmAddNode || cmd->type == CdoCmdPmAddNodeParent || cmd->type == CdoCmdPmAddRequirement || cmd->type == CdoCmdPmInitNode || cmd->type == CdoCmdPmSetNodeAccess || cmd->type == CdoCmdPmNocClockEnable || cmd->type == CdoCmdListSet || cmd->type == CdoCmdSemNpiTable) { uint32_t * p; uint32_t i; cmd->count = (cmd->count & 15) + 1; cmd->buf = p = (uint32_t *)myalloc(cmd->count * 4); for (i = 0; i < cmd->count; i++) { p[i] = randu32(); } if (cmd->type == CdoCmdDmaXfer) { if (myrand() & 1) cmd->srcaddr = 0; if (cmd->srcaddr != 0) { free(cmd->buf); cmd->buf = NULL; } } } else if (cmd->type == CdoCmdComment || cmd->type == CdoCmdSetBoard || cmd->type == CdoCmdLogString || cmd->type == CdoCmdMarker || cmd->type == CdoCmdBegin || cmd->type == CdoCmdPmAddNodeName) { uint8_t * p; uint32_t count = (cmd->count & 7) + 1; uint32_t i; cmd->count = count / 4 + 1; cmd->buf = p = (uint8_t *)myalloc(cmd->count * 4); for (i = 0; i < count; i++) { p[i] = randchar(); } p[i] = '\0'; } else if (cmd->type == CdoCmdBreak) { cmd->value = (cmd->value % level) + 1; } if (cmd->type == CdoCmdProc) level++; if (cmd->type == CdoCmdPsmSequence) level++; if (cmd->type == CdoCmdCdoSequence) level++; if (cmd->type == CdoCmdBegin) level++; if (cmd->type == CdoCmdEnd) level--; add_command(seq, cmd); *levelp = level; } void cdocmd_add_generic_command(CdoSequence * seq, uint32_t id, void * buf, uint32_t count, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdGeneric); cmd->id = id; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_comment(CdoSequence * seq, const char * comment, ...) { CdoCommand * cmd = cdocmd_alloc(CdoCmdComment); va_list ap; int size = 4; /* Align on 4 to avoid issues in copy_buf() */ cmd->buf = (char *)myalloc(size); while (1) { int n; va_start(ap, comment); n = vsnprintf(cmd->buf, size, comment, ap); va_end(ap); if (n >= 0) { if (n < size) break; size = (n + 4) & ~3; } else { size *= 2; } cmd->buf = myrealloc(cmd->buf, size); } cmd->count = strlen(cmd->buf) / 4 + 1; add_command(seq, cmd); } void cdocmd_add_section(CdoSequence * seq, uint32_t id) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSection); cmd->id = id; add_command(seq, cmd); } void cdocmd_add_include(CdoSequence * seq, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdInclude); cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } static CdoCommand * build_block_write(uint64_t addr, void * buf, uint32_t count, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdWrite); cmd->dstaddr = addr; cmd->count = count; if (addr >= USER_KEYS_BASE_ADDR && addr <= USER_KEYS_END_ADDR) { /* copy user keys*/ int i, j; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) { if ((addr == USER_KEYS_BASE_ADDR + (USER_KEY_OFFSET * j) + (4 * i)) && (user_keys.user_keys_array[j] != 0)) { memcpy(buf, &user_keys.user_keys_array[j][7 - i], sizeof(uint32_t)); } } } } cmd->buf = copy_buf(buf, count, be); return cmd; } static CdoCommand * build_set_block(uint64_t addr, uint32_t count, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSetBlock); cmd->dstaddr = addr; cmd->count = count; cmd->value = value; return cmd; } void cdocmd_add_mask_poll(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags) { CdoCommand * cmd = cdocmd_alloc(CdoCmdMaskPoll); cmd->dstaddr = addr; cmd->mask = mask; cmd->value = value; cmd->count = count; cmd->flags = flags; add_command(seq, cmd); } void cdocmd_add_mask_poll_w_err(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags, uint32_t errorcode) { CdoCommand * cmd = cdocmd_alloc(CdoCmdMaskPoll); cmd->dstaddr = addr; cmd->mask = mask; cmd->value = value; cmd->count = count; cmd->flags = flags; cmd->errorcode = errorcode; add_command(seq, cmd); } void cdocmd_add_mask_write(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdMaskWrite); cmd->dstaddr = addr; cmd->mask = mask; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_write(CdoSequence * seq, uint64_t addr, uint32_t value) { cdocmd_add_block_write(seq, addr, 1, &value, is_be_host()); } void cdocmd_add_list_set(CdoSequence * seq, uint32_t id, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdListSet); cmd->id = id; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_list_write(CdoSequence * seq, uint32_t id, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdListWrite); cmd->id = id; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_list_mask_write(CdoSequence * seq, uint32_t id, uint32_t mask, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdListMaskWrite); cmd->id = id; cmd->mask = mask; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_list_mask_poll(CdoSequence * seq, uint32_t id, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags) { CdoCommand * cmd = cdocmd_alloc(CdoCmdListMaskPoll); cmd->id = id; cmd->mask = mask; cmd->value = value; cmd->count = count; cmd->flags = flags; add_command(seq, cmd); } void cdocmd_add_run_proc(CdoSequence * seq, uint32_t id) { CdoCommand * cmd = cdocmd_alloc(CdoCmdRunProc); cmd->id = id; add_command(seq, cmd); } void cdocmd_add_delay(CdoSequence * seq, uint32_t delay) { CdoCommand * cmd = cdocmd_alloc(CdoCmdDelay); cmd->value = delay; add_command(seq, cmd); } void cdocmd_add_block_write(CdoSequence * seq, uint64_t addr, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = build_block_write(addr, buf, count, be); add_command(seq, cmd); } void cdocmd_add_keyhole_write(CdoSequence * seq, uint64_t addr, uint32_t keyhole_size, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdWriteKeyhole); cmd->dstaddr = addr; cmd->value = keyhole_size; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_block_set(CdoSequence * seq, uint64_t addr, uint32_t count, uint32_t value) { CdoCommand * cmd = build_set_block(addr, count, value); add_command(seq, cmd); } void cdocmd_add_dma_xfer(CdoSequence * seq, uint64_t srcaddr, uint64_t dstaddr, uint32_t count, uint32_t flags, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdDmaXfer); cmd->srcaddr = srcaddr; cmd->dstaddr = dstaddr; cmd->count = count; cmd->flags = flags; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_npi_seq(CdoSequence * seq, uint32_t addr, uint32_t flags) { CdoCommand * cmd = cdocmd_alloc(CdoCmdNpiSeq); cmd->dstaddr = addr; cmd->flags = flags; add_command(seq, cmd); } void cdocmd_add_npi_precfg(CdoSequence * seq, uint32_t addr, uint32_t flags) { CdoCommand * cmd = cdocmd_alloc(CdoCmdNpiPreCfg); cmd->dstaddr = addr; cmd->flags = flags; add_command(seq, cmd); } void cdocmd_add_npi_write(CdoSequence * seq, uint32_t addr, uint32_t flags, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdNpiWrite); cmd->dstaddr = addr; cmd->flags = flags; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_npi_shutdown(CdoSequence * seq, uint32_t addr, uint32_t flags) { CdoCommand * cmd = cdocmd_alloc(CdoCmdNpiShutdown); cmd->dstaddr = addr; cmd->flags = flags; add_command(seq, cmd); } void cdocmd_add_pm_get_api_version(CdoSequence * seq) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmGetApiVersion); add_command(seq, cmd); } void cdocmd_add_pm_get_device_status(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmGetDeviceStatus); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_request_suspend(CdoSequence * seq, uint32_t nodeid, uint32_t ack, uint32_t latency, uint32_t state) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmRequestSuspend); cmd->id = nodeid; cmd->flags = ack; cmd->count = latency; cmd->value = state; add_command(seq, cmd); } void cdocmd_add_pm_self_suspend(CdoSequence * seq, uint32_t nodeid, uint32_t latency, uint32_t state, uint64_t addr) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSelfSuspend); cmd->id = nodeid; cmd->count = latency; cmd->value = state; cmd->dstaddr = addr; add_command(seq, cmd); } void cdocmd_add_pm_force_powerdown(CdoSequence * seq, uint32_t nodeid, uint32_t ack) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmForcePowerdown); cmd->id = nodeid; cmd->flags = ack; add_command(seq, cmd); } void cdocmd_add_pm_abort_suspend(CdoSequence * seq, uint32_t reason, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAbortSuspend); cmd->value = reason; cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_request_wakeup(CdoSequence * seq, uint32_t nodeid, uint64_t addr, uint32_t ack) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmRequestWakeup); cmd->id = nodeid; cmd->dstaddr = addr; cmd->flags = ack; add_command(seq, cmd); } void cdocmd_add_pm_hnicx_npi_data_xfer(CdoSequence * seq, uint32_t addr, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmHnicxNpiDataXfer); cmd->dstaddr = addr; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_pm_set_wakeup_source(CdoSequence * seq, uint32_t target, uint32_t source, uint32_t enable) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSetWakeupSource); cmd->id = target; cmd->value = source; cmd->flags = enable; add_command(seq, cmd); } void cdocmd_add_pm_system_shutdown(CdoSequence * seq, uint32_t type, uint32_t subtype) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSystemShutdown); cmd->id = type; cmd->value = subtype; add_command(seq, cmd); } void cdocmd_add_pm_request_device(CdoSequence * seq, uint32_t nodeid, uint32_t capabilities, uint32_t qos, uint32_t ack) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmRequestDevice); cmd->id = nodeid; cmd->value = capabilities; cmd->count = qos; cmd->flags = ack; add_command(seq, cmd); } void cdocmd_add_pm_release_device(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmReleaseDevice); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_set_requirement(CdoSequence * seq, uint32_t nodeid, uint32_t capabilities, uint32_t qos, uint32_t ack) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSetRequirement); cmd->id = nodeid; cmd->value = capabilities; cmd->count = qos; cmd->flags = ack; add_command(seq, cmd); } void cdocmd_add_pm_set_max_latency(CdoSequence * seq, uint32_t nodeid, uint32_t latency) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSetMaxLatency); cmd->id = nodeid; cmd->count = latency; add_command(seq, cmd); } void cdocmd_add_pm_reset_assert(CdoSequence * seq, uint32_t nodeid, uint32_t action) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmResetAssert); cmd->id = nodeid; cmd->flags = action; add_command(seq, cmd); } void cdocmd_add_pm_reset_get_status(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmResetGetStatus); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_request(CdoSequence * seq, uint32_t pinid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlRequest); cmd->id = pinid; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_release(CdoSequence * seq, uint32_t pinid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlRelease); cmd->id = pinid; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_get_function(CdoSequence * seq, uint32_t pinid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlGetFunction); cmd->id = pinid; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_set_function(CdoSequence * seq, uint32_t pinid, uint32_t funcid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlSetFunction); cmd->id = pinid; cmd->value = funcid; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_config_param_get(CdoSequence * seq, uint32_t pinid, uint32_t param) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlConfigParamGet); cmd->id = pinid; cmd->flags = param; add_command(seq, cmd); } void cdocmd_add_pm_pinctrl_config_param_set(CdoSequence * seq, uint32_t pinid, uint32_t param, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPinctrlConfigParamSet); cmd->id = pinid; cmd->flags = param; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_pm_ioctl(CdoSequence * seq, uint32_t nodeid, uint32_t ioctlid, void * buf, uint32_t count, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmIoctl); cmd->id = nodeid; cmd->flags = ioctlid; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_query_data(CdoSequence * seq, uint32_t id, void * buf, uint32_t count, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmQueryData); cmd->id = id; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_clock_enable(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockEnable); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_clock_disable(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockDisable); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_clock_getstate(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockGetState); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_clock_setdivider(CdoSequence * seq, uint32_t nodeid, uint32_t div) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockSetDivider); cmd->id = nodeid; cmd->value = div; add_command(seq, cmd); } void cdocmd_add_pm_clock_getdivider(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockGetDivider); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_clock_setrate(CdoSequence * seq, uint32_t nodeid, uint32_t rate) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockSetRate); cmd->id = nodeid; cmd->value = rate; add_command(seq, cmd); } void cdocmd_add_pm_clock_getrate(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockGetRate); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_clock_setparent(CdoSequence * seq, uint32_t nodeid, uint32_t parentid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockSetParent); cmd->id = nodeid; cmd->value = parentid; add_command(seq, cmd); } void cdocmd_add_pm_clock_getparent(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmClockGetParent); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_pll_set_parameter(CdoSequence * seq, uint32_t nodeid, uint32_t param, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPllSetParameter); cmd->id = nodeid; cmd->flags = param; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_pm_pll_get_parameter(CdoSequence * seq, uint32_t nodeid, uint32_t param) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPllGetParameter); cmd->id = nodeid; cmd->flags = param; add_command(seq, cmd); } void cdocmd_add_pm_pll_set_mode(CdoSequence * seq, uint32_t nodeid, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPllSetMode); cmd->id = nodeid; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_pm_pll_get_mode(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmPllGetMode); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_pm_add_subsystem(CdoSequence * seq, uint32_t ssid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAddSubsystem); cmd->id = ssid; add_command(seq, cmd); } void cdocmd_add_pm_destroy_subsystem(CdoSequence * seq, uint32_t ssid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmDestroySubsystem); cmd->id = ssid; add_command(seq, cmd); } void cdocmd_add_pm_describe_nodes(CdoSequence * seq, void * buf, uint32_t count, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmDescribeNodes); cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_add_node(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAddNode); cmd->id = nodeid; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_add_node_parent(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAddNodeParent); cmd->id = nodeid; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_add_node_name(CdoSequence * seq, uint32_t nodeid, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAddNodeName); cmd->id = nodeid; cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } void cdocmd_add_pm_add_requirement(CdoSequence * seq, uint32_t ssid, uint32_t nodeid, uint32_t flags, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmAddRequirement); cmd->id = ssid; cmd->value = nodeid; cmd->flags = flags; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_set_current_subsystem(CdoSequence * seq, uint32_t ssid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSetCurrentSubsystem); cmd->id = ssid; add_command(seq, cmd); } void cdocmd_add_pm_init_node(CdoSequence * seq, uint32_t nodeid, uint32_t function, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmInitNode); cmd->id = nodeid; cmd->value = function; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_feature_check(CdoSequence * seq, uint32_t id) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmFeatureCheck); cmd->id = id; add_command(seq, cmd); } void cdocmd_add_pm_iso_control(CdoSequence * seq, uint32_t nodeid, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmIsoControl); cmd->id = nodeid; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_pm_activate_subsystem(CdoSequence * seq, uint32_t ssid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmActivateSubsystem); cmd->id = ssid; add_command(seq, cmd); } void cdocmd_add_pm_set_node_access(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmSetNodeAccess); cmd->id = nodeid; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_bisr(CdoSequence * seq, uint32_t tagid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmBisr); cmd->id = tagid; add_command(seq, cmd); } void cdocmd_add_pm_apply_trim(CdoSequence * seq, uint32_t trimtype) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmApplyTrim); cmd->id = trimtype; add_command(seq, cmd); } void cdocmd_add_pm_noc_clock_enable(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmNocClockEnable); cmd->id = nodeid; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_pm_if_noc_clock_enable(CdoSequence * seq, uint32_t index, uint32_t state, uint32_t level) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmIfNocClockEnable); cmd->id = index; cmd->value = state; cmd->flags = level; add_command(seq, cmd); } void cdocmd_add_pm_force_hc(CdoSequence * seq, uint32_t nodeid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmForceHc); cmd->id = nodeid; add_command(seq, cmd); } void cdocmd_add_cfu_set_crc32(CdoSequence * seq, uint32_t type, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuSetCrc32); cmd->flags = type; cmd->value = value; add_command(seq, cmd); } void cdocmd_add_cfu_decompress(CdoSequence * seq, uint32_t type) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuDecompress); cmd->flags = type; add_command(seq, cmd); } void cdocmd_add_cfu_cram_rw(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuCramRW); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_cfu_seu_go(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuSeuGo); cmd->flags = value; add_command(seq, cmd); } void cdocmd_add_cfu_crc8_dis(CdoSequence * seq, uint32_t type) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuCrc8Dis); cmd->flags = type; add_command(seq, cmd); } void cdocmd_add_cfu_ssi_per_slr_pr(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuSsiPerSlrPr); cmd->flags = value; add_command(seq, cmd); } void cdocmd_add_cfu_gsr_gsc(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuGsrGsc); cmd->flags = value; add_command(seq, cmd); } void cdocmd_add_cfu_gcap_clk_en(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuGcapClkEn); cmd->flags = value; add_command(seq, cmd); } void cdocmd_add_cfu_cfi_type(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCfuCfiType); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_cframe_read(CdoSequence * seq, uint32_t param, uint64_t addr, uint32_t read_count, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCframeRead); cmd->flags = param; cmd->dstaddr = addr; cmd->value = read_count; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_ssit_sync_master(CdoSequence * seq) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSsitSyncMaster); add_command(seq, cmd); } void cdocmd_add_ssit_sync_slaves(CdoSequence * seq, uint32_t mask, uint32_t count) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSsitSyncSlaves); cmd->mask = mask; cmd->count = count; add_command(seq, cmd); } void cdocmd_add_ssit_wait_slaves(CdoSequence * seq, uint32_t mask, uint32_t count) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSsitWaitSlaves); cmd->mask = mask; cmd->count = count; add_command(seq, cmd); } void cdocmd_add_nop(CdoSequence * seq, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdNop); cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_event_logging(CdoSequence * seq, uint32_t subcmd, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdEventLogging); cmd->value = subcmd; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_set_board(CdoSequence * seq, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSetBoard); cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } void cdocmd_add_set_plm_wdt(CdoSequence * seq, uint32_t nodeid, uint32_t periodicity) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSetPlmWdt); cmd->id = nodeid; cmd->value = periodicity; add_command(seq, cmd); } void cdocmd_add_log_string(CdoSequence * seq, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdLogString); cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } void cdocmd_add_log_address(CdoSequence * seq, uint64_t addr) { CdoCommand * cmd = cdocmd_alloc(CdoCmdLogAddress); cmd->srcaddr = addr; add_command(seq, cmd); } void cdocmd_add_marker(CdoSequence * seq, uint32_t value, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdMarker); cmd->value = value; cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } void cdocmd_add_proc(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdProc); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_begin(CdoSequence * seq, const char * name) { CdoCommand * cmd = cdocmd_alloc(CdoCmdBegin); cmd->count = strlen(name) / 4 + 1; cmd->buf = my_strdup(name); add_command(seq, cmd); } void cdocmd_add_end(CdoSequence * seq) { CdoCommand * cmd = cdocmd_alloc(CdoCmdEnd); add_command(seq, cmd); } void cdocmd_add_break(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdBreak); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_ot_check(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdOtCheck); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_psm_sequence(CdoSequence * seq) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPsmSequence); add_command(seq, cmd); } void cdocmd_add_cdo_sequence(CdoSequence * seq, uint64_t addr, uint32_t keyhole_size) { CdoCommand * cmd = cdocmd_alloc(CdoCmdCdoSequence); cmd->dstaddr = addr; cmd->value = keyhole_size; add_command(seq, cmd); } void cdocmd_add_scatter_write(CdoSequence * seq, uint32_t value, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdScatterWrite); cmd->value = value; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_scatter_write2(CdoSequence * seq, uint32_t value1, uint32_t value2, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdScatterWrite2); cmd->value = value1; cmd->mask = value2; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_add_tamper_trigger(CdoSequence * seq, uint32_t value) { CdoCommand * cmd = cdocmd_alloc(CdoCmdTamperTrigger); cmd->value = value; add_command(seq, cmd); } void cdocmd_add_set_ipi_access(CdoSequence * seq, uint32_t value, uint32_t mask) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSetIpiAccess); cmd->value = value; cmd->mask = mask; add_command(seq, cmd); } void cdocmd_add_pm_register_notifier(CdoSequence * seq, uint32_t nodeid, uint32_t mask, uint32_t arg1, uint32_t arg2) { CdoCommand * cmd = cdocmd_alloc(CdoCmdPmRegisterNotifier); cmd->id = nodeid; cmd->mask = mask; cmd->value = arg1; cmd->count = arg2; add_command(seq, cmd); } void cdocmd_add_em_set_action(CdoSequence * seq, uint32_t nodeid, uint32_t action, uint32_t mask) { CdoCommand * cmd = cdocmd_alloc(CdoCmdEmSetAction); cmd->id = nodeid; cmd->value = action; cmd->mask = mask; add_command(seq, cmd); } void cdocmd_add_ldr_set_image_info(CdoSequence * seq, uint32_t nodeid, uint32_t uid, uint32_t puid, uint32_t funcid) { CdoCommand * cmd = cdocmd_alloc(CdoCmdLdrSetImageInfo); cmd->id = nodeid; cmd->value = uid; cmd->mask = puid; cmd->count = funcid; add_command(seq, cmd); } void cdocmd_add_ldr_cframe_clear_check(CdoSequence * seq, uint32_t block_type) { CdoCommand * cmd = cdocmd_alloc(CdoCmdLdrCframeClearCheck); cmd->id = block_type; add_command(seq, cmd); } void cdocmd_add_sem_npi_table(CdoSequence * seq, uint32_t nodeid, uint32_t flags, uint32_t count, void * buf, uint32_t be) { CdoCommand * cmd = cdocmd_alloc(CdoCmdSemNpiTable); cmd->id = nodeid; cmd->flags = flags; cmd->count = count; cmd->buf = copy_buf(buf, count, be); add_command(seq, cmd); } void cdocmd_insert_seq(CdoCommand * cmd, CdoSequence * seq) { list_concat(&cmd->link_all, &seq->cmds); list_init(&seq->cmds); } void cdocmd_concat_seq(CdoSequence * seq, CdoSequence * seq2) { list_concat(&seq->cmds, &seq2->cmds); list_init(&seq2->cmds); } void cdocmd_rewrite_address(CdoSequence * seq) { LINK * l = seq->cmds.next; uint64_t mask = 0x1000 - 1; uint64_t baseaddr = 0; int basevalid = 0; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdWrite: case CdoCmdMaskWrite: case CdoCmdMaskPoll: if (!basevalid || baseaddr != (cmd->dstaddr & ~mask)) { CdoCommand * newcmd = cdocmd_alloc(CdoCmdSetBaseAddress); newcmd->dstaddr = baseaddr = cmd->dstaddr & ~mask; cdocmd_insert_command(cmd, newcmd); basevalid = 1; } cmd->dstaddr &= mask; break; default: break; } } } void cdocmd_rewrite_block(CdoSequence * seq) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdWrite: if (cmd->count > 1) { uint64_t dstaddr = cmd->dstaddr; uint32_t * valuep = (uint32_t *)cmd->buf; uint32_t i; for (i = 0; i < cmd->count; i++) { CdoCommand * newcmd = build_block_write(dstaddr, valuep, 1, is_be_host()); cdocmd_insert_command(cmd, newcmd); dstaddr += 4; valuep++; } cdocmd_free(cmd); } break; default: break; } } } void cdocmd_rewrite_sequential(CdoSequence * seq) { LINK * l = seq->cmds.next; CdoCommand * prevcmd = NULL; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdWrite: if (prevcmd != NULL && prevcmd->dstaddr + prevcmd->count*4 == cmd->dstaddr) { prevcmd->buf = myrealloc(prevcmd->buf, (prevcmd->count + cmd->count)*4); memcpy((char *)prevcmd->buf + prevcmd->count*4, cmd->buf, cmd->count*4); prevcmd->count += cmd->count; cdocmd_free(cmd); } else { prevcmd = cmd; } break; default: prevcmd = NULL; break; } } } void cdocmd_rewrite_repeat(CdoSequence * seq) { LINK * l = seq->cmds.next; uint64_t minset = 3; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdWrite: { uint64_t addr = cmd->dstaddr; uint32_t * start = (uint32_t *)cmd->buf; uint32_t * end = start + cmd->count; uint32_t * p = start; uint32_t value = 0; uint32_t repeat = 0; while (p < end) { uint32_t value2 = *p++; if (value2 == value) { repeat++; if (repeat == minset) { uint32_t count = p - start - repeat; if (count > 0) { CdoCommand * newcmd = build_block_write(addr, start, count, is_be_host()); cdocmd_insert_command(cmd, newcmd); addr += count * 4; start += count; } } continue; } if (repeat >= minset) { CdoCommand * newcmd = build_set_block(addr, repeat, u32be(value)); cdocmd_insert_command(cmd, newcmd); addr += repeat * 4; start += repeat; } value = value2; repeat = 1; } if (repeat >= minset) { CdoCommand * newcmd = build_set_block(addr, repeat, u32be(value)); cdocmd_insert_command(cmd, newcmd); cdocmd_free(cmd); addr += repeat * 4; start += repeat; } else if (cmd->dstaddr != addr) { CdoCommand * newcmd = build_block_write(addr, start, p - start, is_be_host()); cdocmd_insert_command(cmd, newcmd); cdocmd_free(cmd); } break; } default: break; } } } void cdocmd_remove_comments(CdoSequence * seq) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case CdoCmdComment: cdocmd_free(cmd); break; default: break; } } } xilinx-bootgen-2024.2/cdo-command.h000077500000000000000000000375401475706442400171340ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_command #define D_cdo_command #include #include #include #include "link.h" #define MARKER_DEVICE 0x1 #define MARKER_ARCHITECTURE 0x3 #define MARKER_PART 0x4 #define MARKER_SLRID 0x5 #define MARKER_DATE 0x6 #define is_be_host() (0) /* CDO Version 1.50 is using CDOv2 format, but allows CDOv1 commands * for NPI and CFU */ #define CDO_VERSION_1_50 ((1 << 8) | 50) /* CDO Version 2.00 is using CDOv2 format, but replaces NPI and CFU * commands with SEM */ #define CDO_VERSION_2_00 ((2 << 8) | 0) /* CDO Version 3.00 is not defined and therefore the upper allowed boundary */ #define CDO_VERSION_3_00 ((3 << 8) | 0) #define DEFAULT_CDO_VERSION CDO_VERSION_2_00 typedef struct CdoSequence CdoSequence; struct CdoSequence { LINK cmds; uint32_t version; }; typedef struct UserKeys { uint32_t user_keys_array[8][8]; }UserKeys; #ifdef __cplusplus extern "C" { #endif extern UserKeys user_keys; #ifdef __cplusplus } #endif #define all2cmds(A) list_item_type((A), CdoCommand, link_all) typedef struct CdoCommand CdoCommand; typedef enum CdoCmdType { CdoCmdGeneric, CdoCmdSection, CdoCmdInclude, CdoCmdComment, CdoCmdSetBaseAddress, CdoCmdWrite, CdoCmdSetBlock, CdoCmdWriteKeyhole, CdoCmdMaskWrite, CdoCmdMaskPoll, CdoCmdDelay, CdoCmdDmaXfer, CdoCmdCframeRead, CdoCmdSsitSyncMaster, CdoCmdSsitSyncSlaves, CdoCmdSsitWaitSlaves, CdoCmdNop, CdoCmdEventLogging, CdoCmdSetBoard, CdoCmdSetPlmWdt, CdoCmdLogString, CdoCmdLogAddress, CdoCmdMarker, CdoCmdProc, CdoCmdBegin, CdoCmdEnd, CdoCmdBreak, CdoCmdOtCheck, CdoCmdPsmSequence, CdoCmdScatterWrite, CdoCmdScatterWrite2, CdoCmdTamperTrigger, CdoCmdSetIpiAccess, CdoCmdNpiSeq, CdoCmdNpiPreCfg, CdoCmdNpiWrite, CdoCmdNpiShutdown, CdoCmdPmHnicxNpiDataXfer, CdoCmdPmGetApiVersion, CdoCmdPmGetDeviceStatus, CdoCmdPmRegisterNotifier, CdoCmdPmRequestSuspend, CdoCmdPmSelfSuspend, CdoCmdPmForcePowerdown, CdoCmdPmAbortSuspend, CdoCmdPmRequestWakeup, CdoCmdPmSetWakeupSource, CdoCmdPmSystemShutdown, CdoCmdPmRequestDevice, CdoCmdPmReleaseDevice, CdoCmdPmSetRequirement, CdoCmdPmSetMaxLatency, CdoCmdPmResetAssert, CdoCmdPmResetGetStatus, CdoCmdPmPinctrlRequest, CdoCmdPmPinctrlRelease, CdoCmdPmPinctrlGetFunction, CdoCmdPmPinctrlSetFunction, CdoCmdPmPinctrlConfigParamGet, CdoCmdPmPinctrlConfigParamSet, CdoCmdPmIoctl, CdoCmdPmQueryData, CdoCmdPmClockEnable, CdoCmdPmClockDisable, CdoCmdPmClockGetState, CdoCmdPmClockSetDivider, CdoCmdPmClockGetDivider, CdoCmdPmClockSetRate, CdoCmdPmClockGetRate, CdoCmdPmClockSetParent, CdoCmdPmClockGetParent, CdoCmdPmPllSetParameter, CdoCmdPmPllGetParameter, CdoCmdPmPllSetMode, CdoCmdPmPllGetMode, CdoCmdPmAddSubsystem, CdoCmdPmDestroySubsystem, CdoCmdPmDescribeNodes, CdoCmdPmAddNode, CdoCmdPmAddNodeParent, CdoCmdPmAddNodeName, CdoCmdPmAddRequirement, CdoCmdPmSetCurrentSubsystem, CdoCmdPmInitNode, CdoCmdPmFeatureCheck, CdoCmdPmIsoControl, CdoCmdPmActivateSubsystem, CdoCmdPmBisr, CdoCmdPmApplyTrim, CdoCmdPmNocClockEnable, CdoCmdPmIfNocClockEnable, CdoCmdPmSetNodeAccess, CdoCmdPmForceHc, CdoCmdCfuSetCrc32, CdoCmdCfuDecompress, CdoCmdCfuCramRW, CdoCmdCfuSeuGo, CdoCmdCfuCrc8Dis, CdoCmdCfuSsiPerSlrPr, CdoCmdCfuGsrGsc, CdoCmdCfuGcapClkEn, CdoCmdCfuCfiType, CdoCmdEmSetAction, CdoCmdLdrSetImageInfo, CdoCmdLdrCframeClearCheck, CdoCmdSemNpiTable, CdoCmdListSet, CdoCmdListWrite, CdoCmdListMaskWrite, CdoCmdListMaskPoll, CdoCmdRunProc, CdoCmdCdoSequence, /* The following line must be last */ CdoCmdLast } CdoCmdType; struct CdoCommand { LINK link_all; CdoCmdType type; uint32_t id; uint64_t dstaddr; uint64_t srcaddr; uint32_t mask; uint32_t value; uint32_t count; uint32_t period; uint32_t flags; uint32_t errorcode; void * buf; }; CdoSequence * cdocmd_create_sequence(void); void cdocmd_delete_sequence(CdoSequence * seq); CdoCommand * cdocmd_alloc(CdoCmdType type); void cdocmd_free(CdoCommand * cmd); CdoCommand * cdocmd_duplicate(CdoCommand * cmd); void cdocmd_set_default_sequence(CdoSequence * seq); void cdocmd_append_command(CdoSequence * seq, CdoCommand * newcmd); void cdocmd_insert_command(CdoCommand * cmd, CdoCommand * newcmd); void cdocmd_add_random_command(CdoSequence * seq, uint32_t * levelp); void cdocmd_add_generic_command(CdoSequence * seq, uint32_t id, void * buf, uint32_t count, uint32_t be); void cdocmd_add_comment(CdoSequence * seq, const char * comment, ...); void cdocmd_add_section(CdoSequence * seq, uint32_t secid); void cdocmd_add_include(CdoSequence * seq, const char * name); void cdocmd_add_mask_poll(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags); void cdocmd_add_mask_poll_w_err(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags, uint32_t errorcode); void cdocmd_add_mask_write(CdoSequence * seq, uint64_t addr, uint32_t mask, uint32_t value); void cdocmd_add_write(CdoSequence * seq, uint64_t addr, uint32_t value); void cdocmd_add_list_set(CdoSequence * seq, uint32_t id, uint32_t count, void * buf, uint32_t be); void cdocmd_add_list_write(CdoSequence * seq, uint32_t id, uint32_t value); void cdocmd_add_list_mask_write(CdoSequence * seq, uint32_t id, uint32_t mask, uint32_t value); void cdocmd_add_list_mask_poll(CdoSequence * seq, uint32_t id, uint32_t mask, uint32_t value, uint32_t count, uint32_t flags); void cdocmd_add_run_proc(CdoSequence * seq, uint32_t id); void cdocmd_add_delay(CdoSequence * seq, uint32_t delay); void cdocmd_add_block_write(CdoSequence * seq, uint64_t addr, uint32_t count, void * buf, uint32_t be); void cdocmd_add_keyhole_write(CdoSequence * seq, uint64_t addr, uint32_t keyhole_size, uint32_t count, void * buf, uint32_t be); void cdocmd_add_block_set(CdoSequence * seq, uint64_t addr, uint32_t count, uint32_t value); void cdocmd_add_dma_xfer(CdoSequence * seq, uint64_t srcaddr, uint64_t dstaddr, uint32_t count, uint32_t flags, void * buf, uint32_t be); void cdocmd_add_npi_seq(CdoSequence * seq, uint32_t addr, uint32_t flags); void cdocmd_add_npi_precfg(CdoSequence * seq, uint32_t addr, uint32_t flags); void cdocmd_add_npi_write(CdoSequence * seq, uint32_t addr, uint32_t flags, uint32_t count, void * buf, uint32_t be); void cdocmd_add_npi_shutdown(CdoSequence * seq, uint32_t addr, uint32_t flags); void cdocmd_add_pm_get_api_version(CdoSequence * seq); void cdocmd_add_pm_get_device_status(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_register_notifier(CdoSequence * seq, uint32_t nodeid, uint32_t mask, uint32_t arg1, uint32_t arg2); void cdocmd_add_pm_request_suspend(CdoSequence * seq, uint32_t nodeid, uint32_t ack, uint32_t latency, uint32_t state); void cdocmd_add_pm_self_suspend(CdoSequence * seq, uint32_t nodeid, uint32_t latency, uint32_t state, uint64_t addr); void cdocmd_add_pm_force_powerdown(CdoSequence * seq, uint32_t nodeid, uint32_t ack); void cdocmd_add_pm_abort_suspend(CdoSequence * seq, uint32_t reason, uint32_t nodeid); void cdocmd_add_pm_request_wakeup(CdoSequence * seq, uint32_t nodeid, uint64_t addr, uint32_t ack); void cdocmd_add_pm_set_wakeup_source(CdoSequence * seq, uint32_t target, uint32_t source, uint32_t enable); void cdocmd_add_pm_system_shutdown(CdoSequence * seq, uint32_t type, uint32_t subtype); void cdocmd_add_pm_request_device(CdoSequence * seq, uint32_t nodeid, uint32_t capabilities, uint32_t qos, uint32_t ack); void cdocmd_add_pm_release_device(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_set_requirement(CdoSequence * seq, uint32_t nodeid, uint32_t capabilities, uint32_t qos, uint32_t ack); void cdocmd_add_pm_set_max_latency(CdoSequence * seq, uint32_t nodeid, uint32_t latency); void cdocmd_add_pm_reset_assert(CdoSequence * seq, uint32_t nodeid, uint32_t action); void cdocmd_add_pm_reset_get_status(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_pinctrl_request(CdoSequence * seq, uint32_t pinid); void cdocmd_add_pm_pinctrl_release(CdoSequence * seq, uint32_t pinid); void cdocmd_add_pm_pinctrl_get_function(CdoSequence * seq, uint32_t pinid); void cdocmd_add_pm_pinctrl_set_function(CdoSequence * seq, uint32_t pinid, uint32_t funcid); void cdocmd_add_pm_pinctrl_config_param_get(CdoSequence * seq, uint32_t pinid, uint32_t param); void cdocmd_add_pm_pinctrl_config_param_set(CdoSequence * seq, uint32_t pinid, uint32_t param, uint32_t value); void cdocmd_add_pm_ioctl(CdoSequence * seq, uint32_t nodeid, uint32_t ioctlid, void * buf, uint32_t count, uint32_t be); void cdocmd_add_pm_query_data(CdoSequence * seq, uint32_t id, void * buf, uint32_t count, uint32_t be); void cdocmd_add_pm_clock_enable(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_clock_disable(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_clock_getstate(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_clock_setdivider(CdoSequence * seq, uint32_t nodeid, uint32_t div); void cdocmd_add_pm_clock_getdivider(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_clock_setrate(CdoSequence * seq, uint32_t nodeid, uint32_t rate); void cdocmd_add_pm_clock_getrate(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_clock_setparent(CdoSequence * seq, uint32_t nodeid, uint32_t parentid); void cdocmd_add_pm_clock_getparent(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_pll_set_parameter(CdoSequence * seq, uint32_t nodeid, uint32_t param, uint32_t value); void cdocmd_add_pm_pll_get_parameter(CdoSequence * seq, uint32_t nodeid, uint32_t param); void cdocmd_add_pm_pll_set_mode(CdoSequence * seq, uint32_t nodeid, uint32_t val); void cdocmd_add_pm_pll_get_mode(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_pm_add_subsystem(CdoSequence * seq, uint32_t ssid); void cdocmd_add_pm_destroy_subsystem(CdoSequence * seq, uint32_t ssid); void cdocmd_add_pm_describe_nodes(CdoSequence * seq, void * buf, uint32_t count, uint32_t be); void cdocmd_add_pm_add_node(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_add_node_parent(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_add_node_name(CdoSequence * seq, uint32_t nodeid, const char * name); void cdocmd_add_pm_add_requirement(CdoSequence * seq, uint32_t ssid, uint32_t nodeid, uint32_t flags, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_set_current_subsystem(CdoSequence * seq, uint32_t ssid); void cdocmd_add_pm_init_node(CdoSequence * seq, uint32_t nodeid, uint32_t function, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_feature_check(CdoSequence * seq, uint32_t id); void cdocmd_add_pm_iso_control(CdoSequence * seq, uint32_t nodeid, uint32_t value); void cdocmd_add_pm_activate_subsystem(CdoSequence * seq, uint32_t ssid); void cdocmd_add_pm_set_node_access(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_bisr(CdoSequence * seq, uint32_t tagid); void cdocmd_add_pm_apply_trim(CdoSequence * seq, uint32_t trimtype); void cdocmd_add_pm_noc_clock_enable(CdoSequence * seq, uint32_t nodeid, uint32_t count, void * buf, uint32_t be); void cdocmd_add_pm_if_noc_clock_enable(CdoSequence * seq, uint32_t index, uint32_t state, uint32_t break_level); void cdocmd_add_pm_force_hc(CdoSequence * seq, uint32_t nodeid); void cdocmd_add_cfu_set_crc32(CdoSequence * seq, uint32_t type, uint32_t value); void cdocmd_add_cfu_decompress(CdoSequence * seq, uint32_t type); void cdocmd_add_cfu_cram_rw(CdoSequence * seq, uint32_t value); void cdocmd_add_cfu_seu_go(CdoSequence * seq, uint32_t value); void cdocmd_add_cfu_crc8_dis(CdoSequence * seq, uint32_t type); void cdocmd_add_cfu_ssi_per_slr_pr(CdoSequence * seq, uint32_t value); void cdocmd_add_cfu_gsr_gsc(CdoSequence * seq, uint32_t value); void cdocmd_add_cfu_gcap_clk_en(CdoSequence * seq, uint32_t value); void cdocmd_add_cfu_cfi_type(CdoSequence * seq, uint32_t value); void cdocmd_add_cframe_read(CdoSequence * seq, uint32_t param, uint64_t addr, uint32_t read_count, uint32_t count, void * buf, uint32_t be); void cdocmd_add_ssit_sync_master(CdoSequence * seq); void cdocmd_add_ssit_sync_slaves(CdoSequence * seq, uint32_t mask, uint32_t count); void cdocmd_add_ssit_wait_slaves(CdoSequence * seq, uint32_t mask, uint32_t count); void cdocmd_add_nop(CdoSequence * seq, uint32_t count, void * buf, uint32_t be); void cdocmd_add_event_logging(CdoSequence * seq, uint32_t subcmd, uint32_t count, void * buf, uint32_t be); void cdocmd_add_set_board(CdoSequence * seq, const char * name); void cdocmd_add_set_plm_wdt(CdoSequence * seq, uint32_t nodeid, uint32_t periodicity); void cdocmd_add_log_string(CdoSequence * seq, const char * str); void cdocmd_add_log_address(CdoSequence * seq, uint64_t srcaddr); void cdocmd_add_marker(CdoSequence * seq, uint32_t value, const char * str); void cdocmd_add_proc(CdoSequence * seq, uint32_t value); void cdocmd_add_begin(CdoSequence * seq, const char * str); void cdocmd_add_end(CdoSequence * seq); void cdocmd_add_break(CdoSequence * seq, uint32_t value); void cdocmd_add_ot_check(CdoSequence * seq, uint32_t value); void cdocmd_add_psm_sequence(CdoSequence * seq); void cdocmd_add_cdo_sequence(CdoSequence * seq, uint64_t addr, uint32_t keyhole_size); void cdocmd_add_scatter_write(CdoSequence * seq, uint32_t value, uint32_t count, void * buf, uint32_t be); void cdocmd_add_scatter_write2(CdoSequence * seq, uint32_t value1, uint32_t value2, uint32_t count, void * buf, uint32_t be); void cdocmd_add_tamper_trigger(CdoSequence * seq, uint32_t value); void cdocmd_add_set_ipi_access(CdoSequence * seq, uint32_t value, uint32_t mask); void cdocmd_add_sem_npi_table(CdoSequence * seq, uint32_t nodeid, uint32_t flags, uint32_t count, void * buf, uint32_t be); void cdocmd_add_ldr_set_image_info(CdoSequence * seq, uint32_t nodeid, uint32_t uid, uint32_t puid, uint32_t funcid); void cdocmd_add_ldr_cframe_clear_check(CdoSequence * seq, uint32_t block_type); void cdocmd_add_em_set_action(CdoSequence * seq, uint32_t nodeid, uint32_t action, uint32_t mask); void cdocmd_insert_seq(CdoCommand * cmd, CdoSequence * seq); void cdocmd_concat_seq(CdoSequence * seq, CdoSequence * seq2); void cdocmd_rewrite_address(CdoSequence * seq); void cdocmd_rewrite_block(CdoSequence * seq); void cdocmd_rewrite_sequential(CdoSequence * seq); void cdocmd_rewrite_repeat(CdoSequence * seq); void cdocmd_remove_comments(CdoSequence * seq); void cdocmd_add_pm_hnicx_npi_data_xfer(CdoSequence * seq, uint32_t addr, uint32_t value); static inline uint16_t u16swap(uint16_t v) { return ((v >> 8) & 0xff) | ((v << 8) & 0xff00); } static inline uint32_t u32swap(uint32_t v) { return u16swap(v >> 16) | (u16swap(v) << 16); } #if is_be_host() static inline uint32_t u32be(uint32_t v) { return v; } static inline uint32_t u32le(uint32_t v) { return u32swap(v); } #else static inline uint32_t u32be(uint32_t v) { return u32swap(v); } static inline uint32_t u32le(uint32_t v) { return v; } #endif #endif /* D_cdo_command */ xilinx-bootgen-2024.2/cdo-driver/000077500000000000000000000000001475706442400166245ustar00rootroot00000000000000xilinx-bootgen-2024.2/cdo-driver/README.md000066400000000000000000000002711475706442400201030ustar00rootroot00000000000000cdo-driver # Overview This is a library enabling the generation of CDO files which can be read by bootgen. It can be combined with the aie-rt libraries to enable device configuration. xilinx-bootgen-2024.2/cdo-driver/cdo_driver.c000077500000000000000000000277471475706442400211340ustar00rootroot00000000000000/****************************************************************************** * Copyright 2018-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /*****************************************************************************/ /** * @file cdo_driver.c * @{ * This file contains set of APIs used to generate AIE-CDO file. * * */ /***************************** Include Files *********************************/ #include "cdo_driver.h" #include #include #include #include #include #include #include /************************** Macro Definitions *****************************/ /************************** Variable Definitions *****************************/ static bool axi_mm_debug = false; static FILE *fp = NULL; cdoHeader hdr = {.NumWords = 0x4, .IdentWord = 0x004F4443, .Version = 0x00000200, .CDOLength = 0x0, .CheckSum = 0x0 }; static bool disableNoOpInsertionForDMACmd = false; /************************** Function Definitions *****************************/ size_t (*fwrite_wrapper)(const void *ptr, size_t size, size_t count, FILE *stream); void reverseEndianness(unsigned char* buffer, size_t count) { /*Note: As per the requirement CDO is generated in little/big endain with boundary of * 4 bytes (1 word). If Address or any other value to be written is 64 bit, then it is split into * 2 words before endianness is swapped. So uint64_t Addr is always sent as Addr1,Addr0 of type unit32_t. * Because all registers are 32 bit, and LE CDOs could be used without bootgen also. */ for (int i = 0; i < count; i++) { unsigned char a = buffer[4 * i]; unsigned char b = buffer[4 * i + 1]; buffer[4 * i] = buffer[4 * i + 3]; buffer[4 * i + 1] = buffer[4 * i + 2]; buffer[4 * i + 2] = b; buffer[4 * i + 3] = a; } } size_t LEfwrite(const void *ptr, size_t size, size_t count, FILE *stream) { size_t num =0; if (size != 4) printf("Warning: It is expected to have each write of 4 bytes in CDO file. \n"); void * copy = malloc(size*count); if (copy != NULL) memcpy(copy, ptr, (size*count)); unsigned char * buffer = (unsigned char*) copy; int x = 1; if (*((char*) &x) == 1) { /* Little endian machine, fwrite directly */ num = fwrite(buffer, size, count, stream); } else { /* Big endian machine, process and fwrite in little endian */ unsigned char *buffer = (unsigned char*) ptr; reverseEndianness(buffer, count); num = fwrite(buffer, size, count, stream); } free(copy); copy=NULL; buffer=NULL; return (num); } size_t BEfwrite(const void *ptr, size_t size, size_t count, FILE *stream) { size_t num =0; if (size != 4) printf("Warning: It is expected to have each write of 4 bytes in CDO file. \n"); void * copy = malloc(size*count); if (copy != NULL) memcpy(copy, ptr, (size*count)); unsigned char * buffer = (unsigned char*) copy; int x = 1; if (*((char*) &x) == 1) { /* Little endian machine, process and fwrite in big endian */ reverseEndianness(buffer, count); num = fwrite(buffer, size, count, stream); } else { /* Big endian machine, fwrite directly*/ num = fwrite(buffer, size, count, stream); } free(copy); copy=NULL; buffer=NULL; return (num); } void EnAXIdebug() { axi_mm_debug = true; } void disableDmaCmdAlignment() { disableNoOpInsertionForDMACmd = true; } void setEndianness(bool endianness) { if(endianness == Little_Endian) /*Little Endian */ fwrite_wrapper = &LEfwrite; else /*Big Endian */ fwrite_wrapper = &BEfwrite; } void startCDOFileStream(const char* cdoFileName) { fp = fopen(cdoFileName, "wb+"); if (fp == NULL) { printf("File could not be opened, fopen Error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } printf("Generating: %s\n", cdoFileName); } void endCurrentCDOFileStream() { fclose(fp); if(fp!=NULL) { fp = NULL; } } void FileHeader() { fwrite_wrapper(&hdr.NumWords, sizeof hdr.NumWords, 1, fp); fwrite_wrapper(&hdr.IdentWord, sizeof hdr.IdentWord, 1, fp); fwrite_wrapper(&hdr.Version, sizeof hdr.Version, 1, fp); fwrite_wrapper(&hdr.CDOLength, sizeof hdr.CDOLength, 1, fp); fwrite_wrapper(&hdr.CheckSum, sizeof hdr.CheckSum, 1, fp); } void cdo_Write32(uint64_t Addr, uint32_t Data) { /* Format: Reserved[31:24] | Length[23:16] | Handler[15:8] | API-ID[7:0] */ const uint32_t Write64CmdHdr = ((0x03U << 16) | CDO_CMD_WRITE64); /* 3 Words - PLM - CMD_WRITE */ if (axi_mm_debug) printf("(Write64): Address: 0x%016lX Data: 0x%08X \n", Addr, Data); uint32_t Addr0 = (uint32_t)(Addr); uint32_t Addr1 = (uint32_t)(Addr>>32); fwrite_wrapper(&Write64CmdHdr, sizeof Write64CmdHdr, 1, fp); fwrite_wrapper(&Addr1, sizeof Addr1, 1, fp); fwrite_wrapper(&Addr0, sizeof Addr0, 1, fp); fwrite_wrapper(&Data, sizeof Data, 1, fp); } void cdo_MaskWrite32(uint64_t Addr, uint32_t Mask, uint32_t Data) { /* Format: Reserved[31:24] | Length[23:16] | Handler[15:8] | API-ID[7:0] */ const uint32_t MaskWrite64CmdHdr = ((0x04U << 16) | CDO_CMD_MASK_WRITE64); /* 4 Words - PLM - CMD_MASK_WRITE */ if (axi_mm_debug) printf("(MaskWrite64): Address: 0x%016lX Mask: 0x%08X Data: 0x%08X \n", Addr, Mask, Data); uint32_t Addr0 = (uint32_t)(Addr); uint32_t Addr1 = (uint32_t)(Addr>>32); fwrite_wrapper(&MaskWrite64CmdHdr, sizeof MaskWrite64CmdHdr, 1, fp); fwrite_wrapper(&Addr1, sizeof Addr1, 1, fp); fwrite_wrapper(&Addr0, sizeof Addr0, 1, fp); fwrite_wrapper(&Mask, sizeof Mask, 1, fp); fwrite_wrapper(&Data, sizeof Data, 1, fp); } // Determine number of bytes required for padding, and insert NOP CMD to make // source side address of DMA WRITE CMD pay-load to be 16 byte aligned. // BOOTGEN post-processes CDO partitions to make it align, but as per discussion // with "Prashant Malladi" user can disable post-processing, and they suggest // that individual CDO should take care of alignment for efficient DMA operation. unsigned int getPadBytesForDmaWrCmdAlignment(uint32_t DmaCmdLength) { size_t DmaCmdSizeExceptPayload = (3 * sizeof(uint32_t)); // Header + Addr0 + Addr1 in bytes if(DmaCmdLength > 255) { DmaCmdSizeExceptPayload += sizeof(uint32_t); // 1 word for length in long command } // Compute number of padding bytes required for DMA WRITE CMD payload alignment long int currByteOffset = ftell(fp); if(currByteOffset == -1L) { perror("ftell()"); fprintf(stderr,"INTERNAL ERROR: Failed to align DMA writes\n"); exit(EXIT_FAILURE); } unsigned int numPadBytes = 0; if(((currByteOffset + DmaCmdSizeExceptPayload ) % 16) != 0) // Only if start of payload is not already aligned numPadBytes = (16 - ((currByteOffset + DmaCmdSizeExceptPayload) % 16)); return (numPadBytes); } void insertNoOpCommand(unsigned int numPadBytes) { // Minimum padding has to be 1 word, at-least header w/o command payload if (numPadBytes < 4) return; uint32_t NoOpCmdLength = (numPadBytes - sizeof(uint32_t))/sizeof(uint32_t); uint32_t NoOpCmdHdr = ((NoOpCmdLength << 16) | CDO_CMD_NO_OPERATION); uint32_t Data = 0; if (axi_mm_debug) printf("(NOP Command): Payload Length: %d \n", NoOpCmdLength); fwrite_wrapper(&NoOpCmdHdr, sizeof(NoOpCmdHdr), 1,fp); for(uint32_t i=0; i < NoOpCmdLength; i++) { fwrite_wrapper(&Data, sizeof(Data), 1, fp); } } void insertDmaWriteCmdHdr(uint32_t DmaCmdLength) { uint32_t DmaWriteCmdHdr; if(DmaCmdLength < 255) { DmaWriteCmdHdr = ((DmaCmdLength << 16) | CDO_CMD_DMA_WRITE); fwrite_wrapper(&DmaWriteCmdHdr, sizeof DmaWriteCmdHdr, 1, fp); } else { DmaWriteCmdHdr = ((255 << 16) | CDO_CMD_DMA_WRITE); fwrite_wrapper(&DmaWriteCmdHdr, sizeof DmaWriteCmdHdr, 1, fp); fwrite_wrapper(&DmaCmdLength, sizeof(DmaCmdLength), 1, fp); } } void cdo_BlockWrite32(uint64_t Addr, uint32_t* pData, uint32_t size) { uint32_t DmaCmdLength = size + 2; // Length in words including address // Insert No Operation command if (!disableNoOpInsertionForDMACmd) { unsigned int numPadBytes = getPadBytesForDmaWrCmdAlignment(DmaCmdLength); if ((numPadBytes != 0)) insertNoOpCommand(numPadBytes); } if (axi_mm_debug) { printf("(BlockWrite-DMAWriteCmd): Start Address: 0x%016lX Size: %" PRIu32 "\n", Addr, size); for(uint32_t i = 0; i < size; i ++) { printf(" Address: 0x%016lX Data@ 0x%" PRIxPTR " is: 0x%08X \n", (Addr + 4*i), (uintptr_t)(pData + i), *(pData + i)); } printf("\n"); } insertDmaWriteCmdHdr(DmaCmdLength); uint32_t Addr0 = (uint32_t)(Addr); uint32_t Addr1 = (uint32_t)(Addr >> 32); fwrite_wrapper(&Addr1, sizeof Addr1, 1, fp); fwrite_wrapper(&Addr0, sizeof Addr0, 1, fp); // Write the block of data pointed by pData fwrite_wrapper(pData, sizeof(uint32_t), size, fp); } void cdo_BlockSet32(uint64_t Addr, uint32_t Data, uint32_t size) { uint32_t DmaCmdLength = size + 2; // Length in words including address // Insert No Operation command if (!disableNoOpInsertionForDMACmd) { unsigned int numPadBytes = getPadBytesForDmaWrCmdAlignment(DmaCmdLength); if ((numPadBytes != 0)) insertNoOpCommand(numPadBytes); } if (axi_mm_debug) { printf("(BlockSet-DMAWriteCmd):Start Address: 0x%016lX Size: %" PRIu32 "\n", Addr, size); for(uint32_t i = 0; i < size; i ++) { printf(" Address: 0x%016lX Data is: 0x%08X \n", (Addr + 4*i), Data); } printf("\n"); } insertDmaWriteCmdHdr(DmaCmdLength); uint32_t Addr0 = (uint32_t)(Addr); uint32_t Addr1 = (uint32_t)(Addr >> 32); fwrite_wrapper(&Addr1, sizeof Addr1, 1, fp); fwrite_wrapper(&Addr0, sizeof Addr0, 1, fp); // Write the specified value for initializing entire address block for(uint32_t i = 0; i < size; i++) fwrite_wrapper(&Data, sizeof Data, 1, fp); } void cdo_MaskPoll(uint64_t Addr, uint32_t Mask, uint32_t Expected_Value, uint32_t TimeoutInMS) { /* Format: Reserved[31:24] | Length[23:16] | Handler[15:8] | API-ID[7:0] */ const uint32_t MaskPoll64CmdHdr = ((0x05U << 16) | CDO_CMD_MASK_POLL64); /* 5 Words - PLM - CMD_MASK_POLL64 */ if (axi_mm_debug) printf("(MaskPoll64): Address: 0x%016lX Mask: 0x%08X Expected Value: 0x%08X Timeout(ms): 0x%08X \n", Addr, Mask, Expected_Value, TimeoutInMS); uint32_t Addr0 = (uint32_t)(Addr); uint32_t Addr1 = (uint32_t)(Addr>>32); fwrite_wrapper(&MaskPoll64CmdHdr, sizeof MaskPoll64CmdHdr, 1, fp); fwrite_wrapper(&Addr1, sizeof Addr1, 1, fp); fwrite_wrapper(&Addr0, sizeof Addr0, 1, fp); fwrite_wrapper(&Mask, sizeof Mask, 1, fp); fwrite_wrapper(&Expected_Value, sizeof Expected_Value, 1, fp); fwrite_wrapper(&TimeoutInMS, sizeof TimeoutInMS, 1, fp); } void configureHeader() { fseek(fp, 0, SEEK_SET); unsigned int numWords = 0; for (;;) { uint32_t buf; size_t n = fread(&buf, 4, 1, fp); numWords = numWords + n; if (n < 1) { break; } } hdr.CDOLength = (numWords - 5); // Length of CDO object in words excluding header length if( fseek(fp, 3 * 4, SEEK_SET) == 0) // Move ahead 3 words and update length of header in words and checksum { if (ferror(fp)) { perror("fseek()"); fprintf(stderr,"INTERNAL_ERROR: Failed to configure AIE-CDO Header \n"); exit(EXIT_FAILURE); } } fwrite_wrapper(&hdr.CDOLength, sizeof hdr.CDOLength, 1, fp); hdr.CheckSum = ~(hdr.NumWords + hdr.IdentWord + hdr.Version + hdr.CDOLength); fwrite_wrapper(&hdr.CheckSum, sizeof hdr.CheckSum, 1, fp); } xilinx-bootgen-2024.2/cdo-driver/cdo_driver.h000077500000000000000000000037521475706442400211270ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _CDO_DRIVER_H_ #define _CDO_DRIVER_H_ #include #include enum byte_ordering{Little_Endian, Big_Endian}; enum CDO_COMMAND { CDO_CMD_DMA_WRITE = 0x105U, CDO_CMD_MASK_POLL64 = 0x106U, CDO_CMD_MASK_WRITE64 = 0x107U, CDO_CMD_WRITE64 = 0x108U, CDO_CMD_NO_OPERATION = 0x111U }; typedef struct cdoHeader { /* Format: * 0x0 - No. of remaining words in header, * 0x4 - Identification Word, * 0x8 - Version, * 0xC - CDO Length, * 0x10- Checksum */ const uint32_t NumWords; const uint32_t IdentWord; const uint32_t Version; uint32_t CDOLength; // Length of CDO object in words excluding header. uint32_t CheckSum; // one's complement of sum of all fields in header i.e. ~(NumWords+IdentWord+Version+Length) } cdoHeader; void startCDOFileStream(const char* cdoFileName); void endCurrentCDOFileStream(); void FileHeader(); void EnAXIdebug(); void setEndianness(bool endianness); void SectionHeader(); void configureHeader(); unsigned int getPadBytesForDmaWrCmdAlignment(uint32_t DmaCmdLength); void insertNoOpCommand(unsigned int numPadBytes); void insertDmaWriteCmdHdr(uint32_t DmaCmdLength); void disableDmaCmdAlignment(); #endif /* _CDO_DRIVER_H_ */ xilinx-bootgen-2024.2/cdo-load.c000077500000000000000000000115311475706442400164200ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include #include "cdo-binary.h" #include "cdo-source.h" #include "cdo-raw.h" #include "cdo-load.h" #define MAX_LINE_LENGTH 100 static char slr_id_binary; char slr_id_from_binary(char ch) { if (slr_id_binary != 0) { ch = slr_id_binary; slr_id_binary = 0; } return ch; } void * file_to_buf(const char * path, size_t * sizep) { FILE * f = fopen(path, "rb"); void * buf = NULL; size_t capacity = 0; size_t size = 0; *sizep = 0; if (f == NULL) { fprintf(stderr, "cannot open file: %s\n", path); return NULL; } for (;;) { size_t len; if (size == capacity) { capacity = capacity ? capacity * 2 : 1; buf = realloc(buf, capacity); if (buf == NULL) { fprintf(stderr, "end of memory while reading file: %s\n", path); goto error; } } len = fread((char *)buf + size, 1, capacity - size, f); if (len == 0) break; size += len; } if (ferror(f)) { fprintf(stderr, "cannot read file: %s\n", path); goto error; } fclose(f); *sizep = size; return buf; error: if (buf) free(buf); fclose(f); return NULL; } CdoSequence * cdoseq_load_cdo(const char * path) { CdoSequence * seq = NULL; CdoRawInfo * raw = NULL; size_t size; void * data = file_to_buf(path, &size); if (data == NULL) goto done; raw = cdoraw_decode(data, size); if (raw != NULL) { free(data); data = raw->data; size = raw->size; } if (is_cdo_data(data, size)) { seq = decode_cdo_binary(data, size); if (seq == NULL) { fprintf(stderr, "cannot decode binary cdo file: %s\n", path); goto done; } if (raw != NULL) { cdometa_add_markers(&raw->meta, seq); } } else { FILE * infile = fopen(path, "r"); if (infile == NULL) { fprintf(stderr, "cannot open file: %s\n", path); goto done; } seq = cdoseq_from_source(infile); fclose(infile); if (seq == NULL) { fprintf(stderr, "cannot parse source cdo file: %s\n", path); goto done; } } done: if (raw != NULL) { cdoraw_delete(raw); } else { free(data); } return seq; } void cdoseq_extract_writes(CdoSequence * seq) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; switch (cmd->type) { case (CdoCmdWrite): case (CdoCmdMaskWrite): /* Ignore writes that configure frequency */ if (cmd->dstaddr == 0xf1260050 || cmd->dstaddr == 0xf1260054 || cmd->dstaddr == 0xf1260104) { cdocmd_free(cmd); } break; default: cdocmd_free(cmd); break; } } } /******************************************************************************/ CdoSequence* cdoseq_extract_cdo_till_ssit_sync_slaves(CdoSequence * seq, uint32_t sync_index) { CdoSequence* temp_seq = seq; LINK * l = temp_seq->cmds.next; uint32_t num_sync_slave_cmds = 0; uint8_t stop = 0; uint8_t start = 0; if (num_sync_slave_cmds == sync_index - 1) { start = 1; } while (l != &temp_seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; if ((cmd->type == CdoCmdSsitSyncSlaves) && (stop == 0)) { num_sync_slave_cmds++; if ((num_sync_slave_cmds == sync_index - 1) && (start == 0)) { start = 1; cdocmd_free(cmd); continue; } if (num_sync_slave_cmds == sync_index) { stop = 1; continue; } } if ((start == 0) || (stop == 1)) { cdocmd_free(cmd); } } return temp_seq; } xilinx-bootgen-2024.2/cdo-load.h000077500000000000000000000022341475706442400164250ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_load #define D_cdo_load #include #include "cdo-command.h" void * file_to_buf(const char * path, size_t * sizep); CdoSequence * cdoseq_load_cdo(const char * path); char slr_id_from_binary(char ch); void cdoseq_extract_writes(CdoSequence * seq); CdoSequence* cdoseq_extract_cdo_till_ssit_sync_slaves(CdoSequence * seq, uint32_t sync_index); #endif /* D_cdo_load */ xilinx-bootgen-2024.2/cdo-metadata.c000077500000000000000000000066561475706442400172750ustar00rootroot00000000000000/****************************************************************************** * Copyright 2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include "cdo-alloc.h" #include "cdo-metadata.h" static void copy_marker_string(char * dst, size_t dstmax, CdoCommand * cmd) { size_t len = strlen(cmd->buf); if (len >= dstmax) len = dstmax - 1; memcpy(dst, cmd->buf, len); dst[len] = '\0'; } void cdometa_extract(CdoMetadata * meta, CdoSequence * seq) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type == CdoCmdMarker) { switch (cmd->value) { case 1: if (meta->creator[0] != '\0') break; copy_marker_string(meta->creator, sizeof meta->creator, cmd); break; case 2: if (meta->design[0] != '\0') break; copy_marker_string(meta->design, sizeof meta->design, cmd); break; case 3: if (meta->arch[0] != '\0') break; copy_marker_string(meta->arch, sizeof meta->arch, cmd); break; case 4: if (meta->part[0] != '\0') break; copy_marker_string(meta->part, sizeof meta->part, cmd); break; case 5: if (meta->slr[0] != '\0') break; copy_marker_string(meta->slr, sizeof meta->slr, cmd); break; case 6: if (meta->date[0] != '\0') break; copy_marker_string(meta->date, sizeof meta->date, cmd); break; default: break; } } } } void cdometa_add_markers(CdoMetadata * meta, CdoSequence * seq) { CdoSequence * newseq = cdocmd_create_sequence(); CdoMetadata curmeta; memset(&curmeta, 0, sizeof curmeta); cdometa_extract(&curmeta, seq); if (meta->creator[0] != '\0' && curmeta.creator[0] == '\0') { cdocmd_add_marker(newseq, 1, meta->creator); } if (meta->design[0] != '\0' && curmeta.design[0] == '\0') { cdocmd_add_marker(newseq, 2, meta->design); } if (meta->arch[0] != '\0' && curmeta.arch[0] == '\0') { cdocmd_add_marker(newseq, 3, meta->arch); } if (meta->part[0] != '\0' && curmeta.part[0] == '\0') { cdocmd_add_marker(newseq, 4, meta->part); } if (meta->slr[0] != '\0' && curmeta.slr[0] == '\0') { cdocmd_add_marker(newseq, 5, meta->slr); } if (meta->date[0] != '\0' && curmeta.date[0] == '\0') { cdocmd_add_marker(newseq, 6, meta->date); } cdocmd_concat_seq(newseq, seq); cdocmd_concat_seq(seq, newseq); cdocmd_delete_sequence(newseq); } xilinx-bootgen-2024.2/cdo-metadata.h000077500000000000000000000022571475706442400172730ustar00rootroot00000000000000/****************************************************************************** * Copyright 2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_metadata #define D_cdo_metadata #include "cdo-command.h" typedef struct CdoMetadata CdoMetadata; struct CdoMetadata { char creator[256]; char design[128]; char arch[128]; char part[64]; char slr[32]; char date[32]; }; void cdometa_extract(CdoMetadata * meta, CdoSequence * seq); void cdometa_add_markers(CdoMetadata * meta, CdoSequence * seq); #endif /* D_cdo_metadata */ xilinx-bootgen-2024.2/cdo-npi.c000077500000000000000000000031561475706442400162730ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include #include #include #include "cdo-binary.h" #include "cdo-source.h" #include "cdo-npi.h" uint32_t cdocmd_post_process_cdo_seq(const void * data, size_t size, CdoSequence ** seqp) { CdoSequence * seq = decode_cdo_binary(data, size); *seqp = NULL; if (seq == NULL) return 1; *seqp = seq; return 0; } uint32_t cdocmd_post_process_cdo(const void * data, size_t size, void ** new_data, size_t * new_size) { CdoSequence * seq; *new_data = NULL; *new_size = 0; cdobinary_set_auto_align(1); if (cdocmd_post_process_cdo_seq(data, size, &seq)) return 1; if (seq == NULL) return 0; *new_data = cdoseq_to_binary(seq, new_size, 0); cdocmd_delete_sequence(seq); return 0; } xilinx-bootgen-2024.2/cdo-npi.h000077500000000000000000000036121475706442400162750ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_npi #define D_cdo_npi #include "cdo-command.h" enum { houseclean_bypass_lpd = 1, houseclean_bypass_fpd = 2, houseclean_bypass_npd = 4, houseclean_bypass_plpd = 8, houseclean_bypass_cpm = 16, }; int is_platform_spp(void); int cdocmd_post_process_mode(const char * s, uint32_t verbose); void set_cfu_stream_keyhole_size(uint64_t size); void set_platform_spp(void); void set_spp_ddr_enable(uint32_t enable); void cdocmd_post_process_start(void); uint32_t cdocmd_post_process_end_seq(CdoSequence ** seqp); void cdocmd_post_process_end(void ** new_data, size_t * new_size); uint32_t cdocmd_post_process_cdo_seq(const void * data, size_t size, CdoSequence ** seqp); uint32_t cdocmd_post_process_cfi_seq(const void * data, size_t size, uint32_t is_gsc, CdoSequence ** seqp); uint32_t cdocmd_post_process_cdo(const void * data, size_t size, void ** new_data, size_t * new_size); uint32_t cdocmd_post_process_cfi(const void * data, size_t size, uint32_t is_gsc, void ** new_data, size_t * new_size); void cdocmd_rewrite_address_filter(CdoSequence * seq, const char * address_filter_file); #endif /* D_cdo_npi */ xilinx-bootgen-2024.2/cdo-overlay.c000077500000000000000000000302001475706442400171540ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include "cdo-alloc.h" #include "cdo-overlay.h" #define OVERLAY_START 100 #define OVERLAY_END 101 #define all2action(A) list_item_type((A), OverlayAction, link_all) typedef struct OverlayAction OverlayAction; struct OverlayAction { LINK link_all; LINK children; CdoCommand * start; CdoCommand * end; char name[1]; }; static void free_action(OverlayAction * action); #ifndef PRINT_OVERLAY_ACTIONS #define PRINT_OVERLAY_ACTIONS 0 #endif #if PRINT_OVERLAY_ACTIONS static void print_overlay_actions(LINK * head, unsigned int level) { LINK * l = head->next; while (l != head) { OverlayAction * action = all2action(l); l = l->next; printf("%*s%s %p {\n", level*2, "", action->name, action->ovlentry); print_overlay_actions(&action->children, level+1); printf("%*s}\n", level*2, ""); } } #endif static void free_action_list(LINK * head) { LINK * l = head->next; while (l != head) { OverlayAction * action = all2action(l); l = l->next; free_action(action); } } static void free_action(OverlayAction * action) { free_action_list(&action->children); list_remove(&action->link_all); myfree(action); } static CdoCommand * find_matching_end(CdoCommand * start, LINK * lend) { LINK * l = start->link_all.next; while (l != lend) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type == CdoCmdMarker) { if (cmd->value == OVERLAY_START) { CdoCommand * end = find_matching_end(cmd, lend); if (end == NULL) return NULL; l = end->link_all.next; continue; } if (cmd->value == OVERLAY_END) { if (strcmp(start->buf, cmd->buf) == 0) { return cmd; } fprintf(stderr, "unexpected end marker \"%s\", expected \"%s\"\n", (char *)cmd->buf, (char *)start->buf); return NULL; } } } fprintf(stderr, "missing end marker \"%s\"\n", (char *)start->buf); return NULL; } static OverlayAction * add_overlay_action(LINK * head, CdoCommand * startmarker, CdoCommand * endmarker, const char * name, int * enter_scope) { LINK * l = head->next; OverlayAction * action = NULL; int append_action = 1; const char * s = strchr(name, '/'); if (s == NULL) s = name + strlen(name); if (s == name) { fprintf(stderr, "invalid overlay name: \"%s\"\n", (const char *)startmarker->buf); return NULL; } action = myalloc_zero(sizeof *action + (s - name)); list_init(&action->link_all); list_init(&action->children); if (*s == '/') { action->start = NULL; action->end = NULL; } else { action->start = startmarker; action->end = endmarker; } memcpy(action->name, name, s - name); while (l != head) { OverlayAction * action2 = all2action(l); l = l->next; int cmp = strcmp(action->name, action2->name); if (cmp <= 0) { if (cmp == 0) { if (action->start != NULL) { /* Use new action and free existing. */ list_add_last(&action->link_all, &action2->link_all); free_action(action2); } else { /* Use existing action and free new. */ free_action(action); action = action2; } } else { /* Insert new action before existing. */ list_add_last(&action->link_all, &action2->link_all); } append_action = 0; /* Action handled. */ break; } } if (append_action) { /* Add new action at then end of the list. */ list_add_last(&action->link_all, head); } if (*s == '\0') return action; s++; /* Skip '/' */ if (*s == '\0') { *enter_scope = 1; return action; } return add_overlay_action(&action->children, startmarker, endmarker, s, enter_scope); } /* * Build a tree of overlay actions. Actions selects a scope and can * optionally replace the content of the scope. Child actions do the * same on inner scopes. */ static int create_overlay_actions(LINK * actions, LINK * l, LINK * lend) { while (l != lend) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type == CdoCmdMarker) { if (cmd->value == OVERLAY_START) { /* Marker start */ CdoCommand * end = find_matching_end(cmd, lend); if (end == NULL) return 1; int enter_scope = 0; OverlayAction * action = add_overlay_action(actions, cmd, end, cmd->buf, &enter_scope); if (action == NULL) { return 1; } if (enter_scope) { if (create_overlay_actions(&action->children, cmd->link_all.next, &end->link_all)) { return 1; } } else { l = cmd->link_all.next; while (l != &end->link_all) { CdoCommand * cmd2 = all2cmds(l); l = l->next; if (cmd2->type == CdoCmdMarker && cmd2->value == OVERLAY_START) { const char * name = cmd2->buf; const char * s = strchr(name, '/'); if (s != NULL) { fprintf(stderr, "markers with path cannot be nested in overlay: \"%s\"\n", name); return 1; } } } } l = end->link_all.next; } else if (cmd->value == OVERLAY_END) { /* Marker end */ fprintf(stderr, "missing start marker for \"%s\"\n", (char *)cmd->buf); goto error; } } } return 0; error: return 1; } static OverlayAction * find_action(LINK * head, const char * name) { LINK * l = head->next; while (l != head) { OverlayAction * action = all2action(l); l = l->next; if (strcmp(action->name, name) == 0) return action; } return NULL; } static void remove_commands_between(CdoCommand * start, CdoCommand * end) { for (;;) { CdoCommand * cmd = all2cmds(start->link_all.next); if (cmd == end) break; cdocmd_free(cmd); } } static void insert_overlay_commands(CdoCommand * cmd, CdoCommand * start, CdoCommand * end) { CdoSequence * seq = cdocmd_create_sequence(); CdoCommand * ovlcmd = start; for (;;) { ovlcmd = all2cmds(ovlcmd->link_all.next); if (ovlcmd == end) break; cdocmd_append_command(seq, cdocmd_duplicate(ovlcmd)); } cdocmd_insert_seq(cmd, seq); cdocmd_delete_sequence(seq); } static void insert_overlay_marker(CdoCommand * cmd, const char * name) { CdoSequence * seq = cdocmd_create_sequence(); cdocmd_add_marker(seq, OVERLAY_START, name); cdocmd_add_marker(seq, OVERLAY_END, name); cdocmd_insert_seq(cmd, seq); cdocmd_delete_sequence(seq); } static int apply_nested_overlay(CdoCommand * startmarker, CdoCommand * endmarker, LINK * actions) { LINK * l = startmarker->link_all.next; LINK * lact = actions->next; while (l != &endmarker->link_all) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type == CdoCmdMarker) { if (cmd->value == OVERLAY_START) { /* Marker start */ CdoCommand * end = find_matching_end(cmd, &endmarker->link_all); if (end == NULL) return 1; l = end->link_all.next; while (lact != actions) { OverlayAction * action = all2action(lact); int cmp = strcmp(action->name, cmd->buf); if (cmp > 0) break; if (cmp < 0) { /* Insert new submarker before current marker */ insert_overlay_marker(cmd, action->name); end = all2cmds(cmd->link_all.prev); cmd = all2cmds(end->link_all.prev); if (action->start != NULL) { insert_overlay_commands(end, action->start, action->end); } } else if (action->start != NULL) { remove_commands_between(cmd, end); insert_overlay_commands(end, action->start, action->end); } if (apply_nested_overlay(cmd, end, &action->children)) goto error; l = end->link_all.next; lact = lact->next; } } else if (cmd->value == OVERLAY_END) { /* Marker end */ fprintf(stderr, "missing start marker for \"%s\"\n", (char *)cmd->buf); goto error; } } } while (lact != actions) { OverlayAction * action = all2action(lact); /* Insert new submarker before current marker */ insert_overlay_marker(endmarker, action->name); CdoCommand * end = all2cmds(endmarker->link_all.prev); CdoCommand * cmd = all2cmds(end->link_all.prev); if (action->start != NULL) { insert_overlay_commands(end, action->start, action->end); } if (apply_nested_overlay(cmd, end, &action->children)) goto error; lact = lact->next; } return 0; error: return 1; } CdoOverlayInfo * cdooverlay_open(CdoSequence * seq) { CdoOverlayInfo * info = myalloc_zero(sizeof *info); list_init(&info->actions); if (create_overlay_actions(&info->actions, seq->cmds.next, &seq->cmds)) { cdooverlay_close(info); return NULL; } #if PRINT_OVERLAY_ACTIONS print_overlay_actions(&info->actions, 0); #endif return info; } void cdooverlay_close(CdoOverlayInfo * info) { if (info->seq) cdocmd_delete_sequence(info->seq); free_action_list(&info->actions); myfree(info); } int cdooverlay_apply(CdoSequence * seq, CdoOverlayInfo * ovl) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; if (cmd->type == CdoCmdMarker) { if (cmd->value == OVERLAY_START) { /* Marker start */ CdoCommand * end = find_matching_end(cmd, &seq->cmds); if (end == NULL) return 1; OverlayAction * action = find_action(&ovl->actions, cmd->buf); if (action != NULL) { if (action->start != NULL) { remove_commands_between(cmd, end); insert_overlay_commands(end, action->start, action->end); } if (apply_nested_overlay(cmd, end, &action->children)) goto error; } l = end->link_all.next; } else if (cmd->value == OVERLAY_END) { /* Marker end */ fprintf(stderr, "missing start marker for \"%s\"\n", (char *)cmd->buf); goto error; } } } return 0; error: return 1; } xilinx-bootgen-2024.2/cdo-overlay.h000077500000000000000000000024411475706442400171670ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_overlay #define D_cdo_overlay #include "cdo-command.h" typedef struct CdoOverlayInfo CdoOverlayInfo; typedef struct CdoOverlayEntry CdoOverlayEntry; struct CdoOverlayEntry { CdoCommand * start; CdoCommand * end; unsigned int level; }; struct CdoOverlayInfo { CdoSequence * seq; LINK actions; }; CdoOverlayInfo * cdooverlay_open(CdoSequence * seq); void cdooverlay_close(CdoOverlayInfo * info); int cdooverlay_apply(CdoSequence * seq, CdoOverlayInfo * ovl); #endif /* D_cdo_overlay */ xilinx-bootgen-2024.2/cdo-raw.c000077500000000000000000000235121475706442400162740ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include "cdo-binary.h" #include "cdo-alloc.h" #include "cdo-raw.h" #define isspc(c) (c == ' ' || c == '\t') #define isnewline(c) (c == '\n' || c == '\r') #define skipsp(s) \ do { \ int c = *s; \ while (isspc(c)) c = *++s; \ } while (0) #define skipline(s, e) \ do { \ int c; \ if (s >= e) break; \ c = *s; \ if (isnewline(c)) break; \ s++; \ } while (1) #define skipnewline(s, e) \ do { \ int c; \ if (s >= e) break; \ c = *s; \ if (c == '\r') { \ s++; \ if (s >= e) break; \ c = *s; \ } \ if (c == '\n') s++; \ } while (0) static uint32_t parse_u64(char ** sp, uint64_t * valuep) { char * s = *sp; skipsp(s); errno = 0; *valuep = (uint64_t)strtoull(s, sp, 0); if (s == *sp || errno != 0) return 1; return 0; }; static uint32_t parse_hex32(char ** sp, uint32_t * valuep) { uint32_t value = 0; char * s = *sp; int i; for (i = 0; i < 8; i++) { int c = *s++; int v; if (c >= '0' && c <= '9') v = c - '0'; else if (c >= 'a' && c <= 'f') v = c - 'a' + 10; else if (c >= 'A' && c <= 'F') v = c - 'A' + 10; else return 1; value = (value << 4) | v; } *valuep = value; *sp = s; return 0; } static uint32_t parse_hex8(char ** sp, uint32_t * valuep) { uint32_t value = 0; char * s = *sp; int i; for (i = 0; i < 2; i++) { int c = *s++; int v; if (c >= '0' && c <= '9') v = c - '0'; else if (c >= 'a' && c <= 'f') v = c - 'a' + 10; else if (c >= 'A' && c <= 'F') v = c - 'A' + 10; else return 1; value = (value << 4) | v; } *valuep = value; *sp = s; return 0; } static void copy_metadata(char * dst, size_t dstmax, char * src, size_t srclen) { size_t len = srclen; if (srclen >= dstmax) len = dstmax - 1; memcpy(dst, src, len); dst[len] = '\0'; } CdoRawInfo * cdoraw_decode(void * data, size_t size) { CdoRawInfo * raw = NULL; size_t capacity = 0; size_t offset = 0; char * s = data; char * e = s + size; char * p = s; uint32_t words = 0; uint64_t bits = 0; skipline(s, e); if ((s-p == 28 && memcmp(p, "Xilinx ASCII NPI Deviceimage", s-p) == 0) || (s-p == 16 && memcmp(p, "Xilinx ASCII CDO", s-p) == 0) || (s-p == 32 && memcmp(p, "Xilinx ASCII PSAXIMM Deviceimage", s-p) == 0)) { raw = cdoraw_create(CdoRawCdo); words = 1; } else if ((s-p == 22 && memcmp(p, "Xilinx ASCII Bitstream", s-p) == 0) || (s-p == 28 && memcmp(p, "Xilinx ASCII CFI Deviceimage", s-p) == 0)) { raw = cdoraw_create(CdoRawCfi); words = 4; } else if (s-p == 2) { raw = cdoraw_create(CdoRawUnknown); s = p; while (s < e) { uint32_t value = 0; uint32_t i; for (i = 0; i < 4; i++) { uint32_t byte; if (s + 2 >= e) { fprintf(stderr, "warning: last word is incomplete %.*s\n", (int)(e-s), s); goto incomplete_word; } if (parse_hex8(&s, &byte)) goto error; value = (value << 8) | byte; if (!isnewline(*s)) goto error; skipnewline(s, e); } if (offset >= capacity) { capacity = capacity ? capacity * 2 : 1; raw->data = (uint32_t *)myrealloc(raw->data, capacity * sizeof *raw->data); } raw->data[offset++] = value; } incomplete_word: raw->size = offset * 4; if (s < e) goto error; return raw; } else { goto error; } skipnewline(s, e); while (s < e) { p = s; skipline(s, e); if (s >= e) goto error; if (s-p >= 10 && memcmp(p, "Created by", 10) == 0) { p += 10; skipsp(p); while (p < s && isspc(s[-1])) s--; /*copy_metadata(raw->meta.creator, sizeof raw->meta.creator, p, s-p);*/ } else if (s-p >= 12 && memcmp(p, "Design name:", 12) == 0) { p += 12; skipsp(p); while (p < s && isspc(s[-1])) s--; copy_metadata(raw->meta.design, sizeof raw->meta.design, p, s-p); } else if (s-p >= 13 && memcmp(p, "Architecture:", 13) == 0) { p += 13; skipsp(p); while (p < s && isspc(s[-1])) s--; copy_metadata(raw->meta.arch, sizeof raw->meta.arch, p, s-p); } else if (s-p >= 5 && memcmp(p, "Part:", 5) == 0) { p += 5; skipsp(p); while (p < s && isspc(s[-1])) s--; copy_metadata(raw->meta.part, sizeof raw->meta.part, p, s-p); } else if (s-p >= 5 && memcmp(p, "Date:", 5) == 0) { p += 5; skipsp(p); while (p < s && isspc(s[-1])) s--; /*copy_metadata(raw->meta.date, sizeof raw->meta.date, p, s-p);*/ } else if (s-p >= 5 && memcmp(p, "Bits:", 5) == 0) { p += 5; skipsp(p); if (parse_u64(&p, &bits)) goto error; skipsp(p); if (p != s) goto error; } else { char * q = p; while (q < s && *q != ':') q++; if (q == s) { /* End of raw header */ s = p; break; } fprintf(stderr, "warning: unexpected raw header: %.*s\n", (int)(s-p), p); } skipnewline(s, e); } while (s < e) { uint32_t value; p = s; skipline(s, e); if (s >= e) goto error; if (parse_hex32(&p, &value)) goto error; if (offset >= capacity) { capacity = capacity ? capacity * 2 : 1; raw->data = (uint32_t *)myrealloc(raw->data, capacity * sizeof *raw->data); } raw->data[offset++] = value; if ((offset % words) == 0) { if (p != s) goto error; skipnewline(s, e); } } if (s < e) goto error; raw->size = offset * 4; if ((uint64_t)raw->size * 8 != bits) { fprintf(stderr, "warning: invalid bits parameter in raw file %"PRIu64", expected %"PRIu64"\n", bits, (uint64_t)raw->size * 8); } return raw; error: if (raw != NULL) free(raw); return NULL; } void cdoraw_encode(CdoRawInfo * raw, FILE * f) { const char hexstr[] = "0123456789abcdef"; uint8_t * p = (uint8_t *)raw->data; size_t size = raw->size; size_t i; fprintf(f, "Xilinx ASCII NPI Deviceimage\n"); fprintf(f, "Created by %s\n", raw->meta.creator[0] ? raw->meta.creator : "CDO utility"); fprintf(f, "Design name: \t%s\n", raw->meta.design[0] ? raw->meta.design : ""); fprintf(f, "Architecture:\t%s\n", raw->meta.arch[0] ? raw->meta.arch : ""); fprintf(f, "Part: \t%s\n", raw->meta.part[0] ? raw->meta.part : ""); fprintf(f, "Date: \t%s\n", raw->meta.date[0] ? raw->meta.date : ""); fprintf(f, "Bits: \t%"PRIu64"\n", (uint64_t)size * 8); for (i = 0; i < size; i++) { uint8_t b = p[i]; putc(hexstr[(b >> 4) & 15], f); putc(hexstr[b & 15], f); if ((i & 3) == 3) putc('\n', f); } } void cdoraw_encode_seq(FILE * f, CdoSequence * seq, uint32_t be) { CdoRawInfo * raw = cdoraw_create(CdoRawCdo); cdometa_extract(&raw->meta, seq); raw->data = cdoseq_to_binary(seq, &raw->size, be); cdoraw_encode(raw, f); cdoraw_delete(raw); } CdoRawInfo * cdoraw_create(CdoRawType type) { CdoRawInfo * raw = (CdoRawInfo *)myalloc_zero(sizeof * raw); raw->type = type; return raw; } void cdoraw_delete(CdoRawInfo * raw) { if (!raw->data_free_disable) { myfree(raw->data); } myfree(raw); } CdoRawInfo * decode_raw(void * data, size_t size) { CdoRawInfo * raw = cdoraw_decode(data, size); CdoRawInfo * newraw = NULL; if (raw == NULL) return NULL; newraw = (CdoRawInfo *)myalloc(sizeof * newraw + raw->size); *newraw = *raw; newraw->data = (uint32_t *)(newraw + 1); memcpy(newraw->data, raw->data, raw->size); newraw->data_free_disable = 1; cdoraw_delete(raw); return newraw; } void encode_raw(FILE * f, void * data, size_t size) { CdoRawInfo * raw = cdoraw_create(CdoRawCdo); raw->data = data; raw->size = size; raw->data_free_disable = 1; cdoraw_encode(raw, f); cdoraw_delete(raw); } xilinx-bootgen-2024.2/cdo-raw.h000077500000000000000000000027171475706442400163050ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_raw #define D_cdo_raw #include "cdo-metadata.h" typedef struct CdoRawInfo CdoRawInfo; typedef enum { CdoRawUnknown, CdoRawCdo, CdoRawCfi } CdoRawType; struct CdoRawInfo { CdoRawType type; CdoMetadata meta; uint32_t data_free_disable:1; size_t size; uint32_t *data; }; CdoRawInfo * cdoraw_create(CdoRawType type); void cdoraw_delete(CdoRawInfo * raw); CdoRawInfo * cdoraw_decode(void * data, size_t size); void cdoraw_encode(CdoRawInfo * raw, FILE * f); void cdoraw_encode_seq(FILE * f, CdoSequence * seq, uint32_t be); CdoRawInfo * decode_raw(void * data, size_t size); void encode_raw(FILE * f, void * data, size_t size); #endif /* D_cdo_raw */ xilinx-bootgen-2024.2/cdo-source.c000077500000000000000000002255341475706442400170130ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include #include #include #include #include #include "cdo-load.h" #include "cdo-source.h" static char* slr_id_ptr; static char slr_id; uint32_t id_code_source; #if defined(_WIN32) #define strcasecmp(x,y) stricmp(x,y) #define strncasecmp(x,y,z) strnicmp(x,y,z) #endif #define isspc(c) (c == ' ' || c == '\t') #define istok(c) (c != '\0' && !isspc(c)) #define skipsp(s) \ do { \ int c = *s; \ while (isspc(c)) c = *++s; \ } while (0) #define skiptok(s) \ do { \ int c = *s; \ while (istok(c)) c = *++s; \ } while (0) typedef struct command_info command_info; struct command_info { char * name; uint32_t id; } command_list[] = { { "section", CdoCmdSection }, { "generic", CdoCmdGeneric }, { "include", CdoCmdInclude }, { "set_base_address", CdoCmdSetBaseAddress }, { "write", CdoCmdWrite }, { "set", CdoCmdSetBlock }, { "write_keyhole", CdoCmdWriteKeyhole }, { "mask_write", CdoCmdMaskWrite }, { "mask_poll", CdoCmdMaskPoll }, { "delay", CdoCmdDelay }, { "dma_xfer", CdoCmdDmaXfer }, { "cframe_read", CdoCmdCframeRead }, { "ssit_sync_master", CdoCmdSsitSyncMaster }, { "ssit_sync_slaves", CdoCmdSsitSyncSlaves }, { "ssit_wait_slaves", CdoCmdSsitWaitSlaves }, { "nop", CdoCmdNop }, { "event_logging", CdoCmdEventLogging }, { "set_board", CdoCmdSetBoard }, { "set_plm_wdt", CdoCmdSetPlmWdt }, { "log_string", CdoCmdLogString }, { "log_address", CdoCmdLogAddress }, { "marker", CdoCmdMarker }, { "proc", CdoCmdProc }, { "begin", CdoCmdBegin }, { "end", CdoCmdEnd }, { "break", CdoCmdBreak }, { "ot_check", CdoCmdOtCheck }, { "psm_sequence", CdoCmdPsmSequence }, { "cdo_sequence", CdoCmdCdoSequence }, { "scatter_write", CdoCmdScatterWrite }, { "scatter_write2", CdoCmdScatterWrite2 }, { "tamper_trigger", CdoCmdTamperTrigger }, { "set_ipi_access", CdoCmdSetIpiAccess }, { "list_set", CdoCmdListSet}, { "list_write", CdoCmdListWrite}, { "list_mask_write", CdoCmdListMaskWrite}, { "list_mask_poll", CdoCmdListMaskPoll}, { "run_proc", CdoCmdRunProc}, { "npi_seq", CdoCmdNpiSeq }, { "npi_precfg", CdoCmdNpiPreCfg }, { "npi_write", CdoCmdNpiWrite }, { "npi_shutdown", CdoCmdNpiShutdown }, { "pm_hnicx_npi_data_xfer", CdoCmdPmHnicxNpiDataXfer }, { "pm_get_api_version", CdoCmdPmGetApiVersion }, { "pm_get_device_status", CdoCmdPmGetDeviceStatus }, { "pm_register_notifier", CdoCmdPmRegisterNotifier }, { "pm_request_suspend", CdoCmdPmRequestSuspend }, { "pm_self_suspend", CdoCmdPmSelfSuspend }, { "pm_force_powerdown", CdoCmdPmForcePowerdown }, { "pm_abort_suspend", CdoCmdPmAbortSuspend }, { "pm_request_wakeup", CdoCmdPmRequestWakeup }, { "pm_set_wakeup_source", CdoCmdPmSetWakeupSource }, { "pm_system_shutdown", CdoCmdPmSystemShutdown }, { "pm_request_device", CdoCmdPmRequestDevice }, { "pm_release_device", CdoCmdPmReleaseDevice }, { "pm_set_requirement", CdoCmdPmSetRequirement }, { "pm_set_max_latency", CdoCmdPmSetMaxLatency }, { "pm_reset_assert", CdoCmdPmResetAssert }, { "pm_reset_get_status", CdoCmdPmResetGetStatus }, { "pm_pinctrl_request", CdoCmdPmPinctrlRequest }, { "pm_pinctrl_release", CdoCmdPmPinctrlRelease }, { "pm_pinctrl_get_function", CdoCmdPmPinctrlGetFunction }, { "pm_pinctrl_set_function", CdoCmdPmPinctrlSetFunction }, { "pm_pinctrl_config_param_get", CdoCmdPmPinctrlConfigParamGet }, { "pm_pinctrl_config_param_set", CdoCmdPmPinctrlConfigParamSet }, { "pm_ioctl", CdoCmdPmIoctl }, { "pm_query_data", CdoCmdPmQueryData }, { "pm_clock_enable", CdoCmdPmClockEnable }, { "pm_clock_disable", CdoCmdPmClockDisable }, { "pm_clock_get_state", CdoCmdPmClockGetState }, { "pm_clock_set_divider", CdoCmdPmClockSetDivider }, { "pm_clock_get_divider", CdoCmdPmClockGetDivider }, { "pm_clock_set_rate", CdoCmdPmClockSetRate }, { "pm_clock_get_rate", CdoCmdPmClockGetRate }, { "pm_clock_set_parent", CdoCmdPmClockSetParent }, { "pm_clock_get_parent", CdoCmdPmClockGetParent }, { "pm_pll_set_parameter", CdoCmdPmPllSetParameter }, { "pm_pll_get_parameter", CdoCmdPmPllGetParameter }, { "pm_pll_set_mode", CdoCmdPmPllSetMode }, { "pm_pll_get_mode", CdoCmdPmPllGetMode }, { "pm_add_subsystem", CdoCmdPmAddSubsystem }, { "pm_destroy_subsystem", CdoCmdPmDestroySubsystem }, { "pm_describe_nodes", CdoCmdPmDescribeNodes }, { "pm_add_node", CdoCmdPmAddNode }, { "pm_add_node_parent", CdoCmdPmAddNodeParent }, { "pm_add_node_name", CdoCmdPmAddNodeName }, { "pm_add_requirement", CdoCmdPmAddRequirement }, { "pm_set_current_subsystem", CdoCmdPmSetCurrentSubsystem }, { "pm_init_node", CdoCmdPmInitNode }, { "pm_feature_check", CdoCmdPmFeatureCheck }, { "pm_iso_control", CdoCmdPmIsoControl }, { "pm_bisr", CdoCmdPmBisr }, { "pm_apply_trim", CdoCmdPmApplyTrim }, { "pm_noc_clock_enable", CdoCmdPmNocClockEnable }, { "pm_if_noc_clock_enable", CdoCmdPmIfNocClockEnable }, { "pm_activate_subsystem", CdoCmdPmActivateSubsystem }, { "pm_set_node_access", CdoCmdPmSetNodeAccess }, { "pm_force_hc", CdoCmdPmForceHc}, { "cfu_set_crc32", CdoCmdCfuSetCrc32 }, { "cfu_decompress", CdoCmdCfuDecompress }, { "cfu_cram_rw", CdoCmdCfuCramRW }, { "cfu_seu_go", CdoCmdCfuSeuGo }, { "cfu_crc8_dis", CdoCmdCfuCrc8Dis }, { "cfu_ssi_per_slr_pr", CdoCmdCfuSsiPerSlrPr }, { "cfu_gsr_gsc", CdoCmdCfuGsrGsc }, { "cfu_gcap_clk_en", CdoCmdCfuGcapClkEn }, { "cfu_cfi_type", CdoCmdCfuCfiType }, { "em_set_action", CdoCmdEmSetAction }, { "ldr_set_image_info", CdoCmdLdrSetImageInfo }, { "cframe_clear_check", CdoCmdLdrCframeClearCheck }, { "sem_npi_table", CdoCmdSemNpiTable }, { NULL, 0 } }; char* marker_list[] = { "PMC_DATA", "LPD_DATA", "FPD_DATA", "PMC_DATA_SLR_1", "PMC_DATA_SLR_2", "PMC_DATA_SLR_3" }; int marker_count[sizeof(marker_list) / sizeof(marker_list[0])]; struct cdo_device { const char* name; uint32_t idcode; } device_list[] = { { "xcvm1402", 0x04C08093 }, { "xcvm1302", 0x04C09093 }, { "xcv20", 0x04C0F093 }, { "xcvp1052", 0x04C18093 }, { "xcvp1002", 0x04C1B093 }, { "xcvm2102", 0x04C1C093 }, { "xcvp1402", 0x04C20093 }, { "xcvp1102", 0x04C22093 }, { "xcvm2902", 0x04C23093 }, { "xcvm2302", 0x04C24093 }, { "xcvr1352", 0x04C90093 }, { "xcvr1302", 0x04C91093 }, { "xcvc1352", 0x04C93093 }, { "xcvr1402", 0x04C94093 }, { "xcvc1702", 0x04C98093 }, { "xcvm1502", 0x04C99093 }, { "xcve1752", 0x04C9A093 }, { "xcvc1502", 0x04C9B093 }, { "xcvr1702", 0x04CA0093 }, { "xcvr1502", 0x04CA2093 }, { "xcvr1602", 0x04CA3093 }, { "xcvr1802", 0x04CA5093 }, { "xcvc1802", 0x14CA9093 }, { "xcvm1802", 0x14CAA093 }, { "xcv65", 0x14CAF093 }, { "xcve2102", 0x04CC0093 }, { "xcve2002", 0x04CC1093 }, { "xcve2302", 0x14CC8093 }, { "xcve2202", 0x14CC9093 }, { "xcvm1102", 0x14CCA093 }, { "xcvc2802", 0x14CD0093 }, { "xcvc2602", 0x14CD1093 }, { "xcve2602", 0x14CD2093 }, { "xcve2802", 0x14CD3093 }, { "xcvm2202", 0x14CD4093 }, { "xcv70", 0x14CD7093 }, { "xcvp1202", 0x14D00093 }, { "xcvm2502", 0x14D01093 }, { "xcvp1502", 0x14D08093 }, { "xcvp1702", 0x14D10093 }, { "xcvp1802", 0x14D14093 }, { "xcvp2502", 0x14D1C093 }, { "xcvp2802", 0x14D20093 }, { "xcvh1582", 0x14D28093 }, { "xcvh1542", 0x14D29093 }, { "xcvh1522", 0x14D2A093 }, { "xcvh1782", 0x14D2C093 }, { "xcvh1742", 0x14D2D093 }, { "xcv80", 0x14D2F093 }, { "xcvp1552", 0x14D34093 }, { "xcvp1752", 0x14D38093 }, { "xcvn3716", 0x14D80093 }, { "xcvn3516", 0x14D81093 }, { "xcvn3408", 0x14D82093 }, { "xcvn3708", 0x14D83093 }, { "xcvc1902", 0x14CA8093 }, { NULL, 0 } }; static uint32_t iseol(char ** sp) { char * s = *sp; skipsp(s); *sp = s; return !istok(*s) || *s == '#'; } static command_info * find_command(char * name, uint32_t len) { command_info * cmd = command_list; while (cmd->name != NULL) { if (strncasecmp(cmd->name, name, len) == 0 && cmd->name[len] == '\0') return cmd; cmd++; } return NULL; } static uint32_t find_device(char * name) { struct cdo_device * device = device_list; while (device->name != NULL) { if (strncmp(device->name, name, sizeof(char*)) == 0) break; device++; } return device->idcode; } static uint32_t parse_u32(char ** sp, uint32_t * valuep) { char * s = *sp; skipsp(s); errno = 0; *valuep = (uint32_t)strtoull(s, sp, 0); if (s == *sp || errno != 0 || istok(**sp)) return 1; return 0; }; static uint32_t parse_u64(char ** sp, uint64_t * valuep) { char * s = *sp; skipsp(s); errno = 0; *valuep = (uint64_t)strtoull(s, sp, 0); if (s == *sp || errno != 0 || istok(**sp)) return 1; return 0; }; static uint32_t parse_buf(char ** sp, uint32_t ** bufp, uint32_t * countp) { char * s = *sp; uint32_t * buf = NULL; uint32_t count = 0; uint32_t capacity = 0; for (;;) { uint32_t value; if (iseol(&s)) break; if (parse_u32(&s, &value)) goto error; if (count == capacity) { capacity = capacity ? capacity*2 : 1; buf = (uint32_t *)realloc(buf, capacity * sizeof *buf); if (buf == NULL) goto error; } buf[count++] = value; } *sp = s; *bufp = buf; *countp = count; return 0; error: free(buf); *bufp = NULL; *countp = 0; return 1; } static uint32_t parse_string(char ** sp, char ** strp) { char * s = *sp; char * str = NULL; uint32_t count = 0; uint32_t capacity = 0; int quote = 0; int c; skipsp(s); if (*s == '"') { quote = 1; s++; } while ((c = *s) != '\0') { if (quote && c == '"') break; s++; if (c == '\\') { if ((c = *s) == '\0') break; s++; } if (count == capacity) { capacity = capacity ? capacity*2 : 1; str = (char *)realloc(str, capacity * sizeof *str); if (str == NULL) goto error; } str[count++] = c; } if (quote) { if (c != '"') goto error; s++; } if (count == capacity) { capacity++; str = (char *)realloc(str, capacity * sizeof *str); if (str == NULL) goto error; } str[count] = '\0'; *sp = s; *strp = str; return 0; error: free(str); *strp = NULL; return 1; } char slr_id_from_source(char ch) { if (slr_id != 0) { ch = slr_id; slr_id = 0; } return ch; } uint32_t idcode_from_source(uint32_t id) { if (id_code_source != 0) { id = id_code_source; id_code_source = 0; } return id; } static void check_redundant_markers(char * marker_string) { bool same_marker_found = false; int i = 0; for (; i < (sizeof(marker_list) / sizeof(marker_list[0])); i++) { if (strcasecmp(marker_string, marker_list[i]) == 0) { if (marker_count[i]++ > 2) { same_marker_found = true; } } } if (same_marker_found == true) { printf("[WARNING]: The marker %s is found more than once.\n", marker_string); } } CdoSequence * cdoseq_from_source(FILE * f) { CdoSequence * seq = cdocmd_create_sequence(); uint32_t cap = 2; char * line = (char *)malloc(cap * sizeof *line); uint32_t first = 1; uint32_t level = 0; for (;;) { char * s; char * p; uint32_t len = 0; command_info * cmdinfo; for (;;) { if (len + 1 >= cap) { cap *= 2; line = (char *)realloc(line, cap * sizeof *line); } if (fgets(line + len, cap - len, f) == NULL) break; len += strlen(line + len); if (len == 0 || line[len-1] == '\n') break; } if (len == 0) break; if (line[len-1] == '\n') len--; if (len > 0 && line[len-1] == '\r') len--; line[len] = '\0'; s = line; if (iseol(&s)) { if (*s == '#') { s++; skipsp(s); cdocmd_add_comment(seq, "%s", s); } continue; } p = s; skiptok(s); cmdinfo = find_command(p, s - p); if (cmdinfo == NULL) { if (s - p == 7 && strncasecmp(p, "version", s - p) == 0) { unsigned long major; unsigned long minor = 0; skipsp(s); errno = 0; major = strtoul(s, &p, 10); if (s != p && errno == 0 && *p == '.') { s = p + 1; minor = strtoul(s, &p, 10); } if (s == p || errno != 0) goto syntax_error; if (!iseol(&p)) goto syntax_error; if (!first) goto syntax_error; if (major > 0xff) goto syntax_error; if (minor > 0xff) goto syntax_error; seq->version = (major << 8) | minor; } else { goto syntax_error; } first = 0; continue; } switch(cmdinfo->id) { case CdoCmdSection: { uint32_t id; if (seq->version >= CDO_VERSION_1_50) goto syntax_error; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_section(seq, id); break; } case CdoCmdGeneric: { uint32_t id; uint32_t * buf; uint32_t count; if (parse_u32(&s, &id)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_generic_command(seq, id, buf, count, is_be_host()); free(buf); break; } case CdoCmdInclude: { CdoSequence * seq2; char * name; if (iseol(&s)) goto syntax_error; if (parse_string(&s, &name)) goto syntax_error; seq2 = cdoseq_load_cdo(name); free(name); if (seq2 == NULL) goto error; cdocmd_concat_seq(seq, seq2); cdocmd_delete_sequence(seq2); break; } #if 0 case CdoCmdSetBaseAddress: cdocmd_(seq, u32be(p[i+0]), u32be(p[i+1]), u32be(p[i+2]), 0, u32be(p[i+3])*1000); fprintf(f, "set_base_address "); print_x64(f, cmd->dstaddr); fprintf(f, "\n"); break; #endif case CdoCmdWrite: { uint64_t addr; uint32_t * buf; uint32_t count; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_block_write(seq, addr, count, buf, is_be_host()); free(buf); break; } case CdoCmdListSet: { uint32_t id; uint32_t * buf; uint32_t count; if (parse_u32(&s, &id)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_list_set(seq, id, count, buf, is_be_host()); free(buf); break; } case CdoCmdListWrite: { uint32_t id; uint32_t value; if (parse_u32(&s, &id)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_list_write(seq, id, value); break; } case CdoCmdListMaskWrite: { uint32_t id; uint32_t mask; uint32_t value; if (parse_u32(&s, &id)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_list_mask_write(seq, id, mask, value); break; } case CdoCmdListMaskPoll: { uint32_t id; uint32_t mask; uint32_t value; uint32_t count = 0; uint32_t flags = 0; if (parse_u32(&s, &id)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &count)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &flags)) goto syntax_error; skipsp(s); cdocmd_add_list_mask_poll(seq, id, mask, value, count, flags); break; } case CdoCmdRunProc: { uint32_t id; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_run_proc(seq, id); break; } case CdoCmdSetBlock: { uint64_t addr; uint32_t count; uint32_t value; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &count)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_block_set(seq, addr, count, value); break; } case CdoCmdWriteKeyhole: { uint64_t addr; uint32_t value; uint32_t * buf; uint32_t count; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_keyhole_write(seq, addr, value, count, buf, is_be_host()); free(buf); break; } case CdoCmdMaskWrite: { uint64_t addr; uint32_t mask; uint32_t value; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_mask_write(seq, addr, mask, value); break; } case CdoCmdMaskPoll: { uint64_t addr; uint32_t mask; uint32_t value; uint32_t count = 0; uint32_t flags = 0; uint32_t errorcode = 0; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &count)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &flags)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &errorcode)) goto syntax_error; if (errorcode) cdocmd_add_mask_poll_w_err(seq, addr, mask, value, count, flags, errorcode); else cdocmd_add_mask_poll(seq, addr, mask, value, count, flags); break; } case CdoCmdDelay: { uint32_t value; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_delay(seq, value); break; } case CdoCmdDmaXfer: { uint64_t srcaddr; uint64_t dstaddr; uint32_t count; uint32_t flags; uint32_t * buf = NULL; if (parse_u64(&s, &srcaddr)) goto syntax_error; if (parse_u64(&s, &dstaddr)) goto syntax_error; if (parse_u32(&s, &count)) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (seq->version < CDO_VERSION_2_00 && srcaddr == 0) { uint32_t count2 = 0; if (parse_buf(&s, &buf, &count2)) goto syntax_error; if (count != count2) { free(buf); goto syntax_error; } } cdocmd_add_dma_xfer(seq, srcaddr, dstaddr, count, flags, buf, is_be_host()); free(buf); break; } case CdoCmdCframeRead: { uint32_t param; uint64_t addr; uint32_t read_count; uint32_t * buf; uint32_t count; if (parse_u32(&s, ¶m)) goto syntax_error; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &read_count)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_cframe_read(seq, param, addr, read_count, count, buf, is_be_host()); free(buf); if (seq->version < CDO_VERSION_2_00 && count != 16) goto syntax_error; break; } case CdoCmdSsitSyncMaster: { cdocmd_add_ssit_sync_master(seq); break; } case CdoCmdSsitSyncSlaves: { uint32_t mask; uint32_t count; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &count)) goto syntax_error; cdocmd_add_ssit_sync_slaves(seq, mask, count); break; } case CdoCmdSsitWaitSlaves: { uint32_t mask; uint32_t count; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &count)) goto syntax_error; cdocmd_add_ssit_wait_slaves(seq, mask, count); break; } case CdoCmdNop: { uint32_t * buf; uint32_t count; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_nop(seq, count, buf, is_be_host()); free(buf); break; } case CdoCmdEventLogging: { uint32_t * buf; uint32_t count; uint32_t subcmd; if (parse_u32(&s, &subcmd)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_event_logging(seq, subcmd, count, buf, is_be_host()); free(buf); break; } case CdoCmdSetBoard: { char * name; if (iseol(&s)) goto syntax_error; if (parse_string(&s, &name)) goto syntax_error; cdocmd_add_set_board(seq, name); free(name); break; } case CdoCmdSetPlmWdt: { uint32_t nodeid; uint32_t periodicity; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &periodicity)) goto syntax_error; cdocmd_add_set_plm_wdt(seq, nodeid, periodicity); break; } case CdoCmdLogString: { char * name; if (iseol(&s)) goto syntax_error; if (parse_string(&s, &name)) goto syntax_error; cdocmd_add_log_string(seq, name); free(name); break; } case CdoCmdLogAddress: { uint64_t addr; if (parse_u64(&s, &addr)) goto syntax_error; cdocmd_add_log_address(seq, addr); break; } case CdoCmdMarker: { uint32_t value; char * name; if (parse_u32(&s, &value)) goto syntax_error; if (iseol(&s)) goto syntax_error; if (parse_string(&s, &name)) goto syntax_error; check_redundant_markers(name); if (value == MARKER_DEVICE || value == MARKER_DATE) { break; } if (value == MARKER_SLRID) { slr_id_ptr = name; slr_id = *slr_id_ptr; } if (value == MARKER_PART) { id_code_source = find_device(name); } cdocmd_add_marker(seq, value, name); free(name); break; } case CdoCmdProc: { uint32_t value; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_proc(seq, value); level++; break; } case CdoCmdBegin: { char * name; if (parse_string(&s, &name)) goto syntax_error; cdocmd_add_begin(seq, name); free(name); level++; break; } case CdoCmdEnd: { if (level == 0) goto syntax_error; cdocmd_add_end(seq); level--; break; } case CdoCmdBreak: { uint32_t value = 1; skipsp(s); if (istok(*s)) { if (parse_u32(&s, &value)) goto syntax_error; if (value < 1 || value > level) goto syntax_error; } cdocmd_add_break(seq, value); break; } case CdoCmdOtCheck: { uint32_t value; skipsp(s); if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_ot_check(seq, value); break; } case CdoCmdPsmSequence: cdocmd_add_psm_sequence(seq); level++; break; case CdoCmdCdoSequence: { uint64_t addr; uint32_t value; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cdo_sequence(seq, addr, value); level++; break; } case CdoCmdScatterWrite: { uint32_t * buf; uint32_t count; uint32_t value; if (parse_u32(&s, &value)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_scatter_write(seq, value, count, buf, is_be_host()); free(buf); break; } case CdoCmdScatterWrite2: { uint32_t * buf; uint32_t count; uint32_t value1; uint32_t value2; if (parse_u32(&s, &value1)) goto syntax_error; if (parse_u32(&s, &value2)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_scatter_write2(seq, value1, value2, count, buf, is_be_host()); free(buf); break; } case CdoCmdTamperTrigger: { uint32_t value; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_tamper_trigger(seq, value); break; } case CdoCmdSetIpiAccess: { uint32_t value; uint32_t mask; if (parse_u32(&s, &value)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; cdocmd_add_set_ipi_access(seq, value, mask); break; } case CdoCmdNpiSeq: case CdoCmdNpiPreCfg: case CdoCmdNpiShutdown: { uint32_t addr; uint32_t flags; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &addr)) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (cmdinfo->id == CdoCmdNpiSeq) { cdocmd_add_npi_seq(seq, addr, flags); } else if (cmdinfo->id == CdoCmdNpiPreCfg) { cdocmd_add_npi_precfg(seq, addr, flags); } else { cdocmd_add_npi_shutdown(seq, addr, flags); } break; } case CdoCmdNpiWrite: { uint32_t addr; uint32_t flags; uint32_t count; uint32_t * buf; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &addr)) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_npi_write(seq, addr, flags, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmHnicxNpiDataXfer: { uint32_t addr; uint32_t value; if (parse_u32(&s, &addr)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_pm_hnicx_npi_data_xfer(seq, addr, value); break; } case CdoCmdPmGetApiVersion: { cdocmd_add_pm_get_api_version(seq); break; } case CdoCmdPmGetDeviceStatus: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_get_device_status(seq, nodeid); break; } case CdoCmdPmRegisterNotifier: { uint32_t nodeid; uint32_t mask; uint32_t arg1; uint32_t arg2; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; if (parse_u32(&s, &arg1)) goto syntax_error; if (parse_u32(&s, &arg2)) goto syntax_error; cdocmd_add_pm_register_notifier(seq, nodeid, mask, arg1, arg2); break; } case CdoCmdPmRequestSuspend: { uint32_t nodeid; uint32_t ack; uint32_t latency; uint32_t state; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &ack)) goto syntax_error; if (parse_u32(&s, &latency)) goto syntax_error; if (parse_u32(&s, &state)) goto syntax_error; cdocmd_add_pm_request_suspend(seq, nodeid, ack, latency, state); break; } case CdoCmdPmSelfSuspend: { uint32_t nodeid; uint32_t latency; uint32_t state; uint64_t addr; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &latency)) goto syntax_error; if (parse_u32(&s, &state)) goto syntax_error; if (parse_u64(&s, &addr)) goto syntax_error; cdocmd_add_pm_self_suspend(seq, nodeid, latency, state, addr); break; } case CdoCmdPmForcePowerdown: { uint32_t nodeid; uint32_t ack; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &ack)) goto syntax_error; cdocmd_add_pm_force_powerdown(seq, nodeid, ack); break; } case CdoCmdPmAbortSuspend: { uint32_t nodeid; uint32_t reason; if (parse_u32(&s, &reason)) goto syntax_error; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_abort_suspend(seq, reason, nodeid); break; } case CdoCmdPmRequestWakeup: { uint32_t nodeid; uint64_t addr; uint32_t ack; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u64(&s, &addr)) goto syntax_error; if (parse_u32(&s, &ack)) goto syntax_error; cdocmd_add_pm_request_wakeup(seq, nodeid, addr, ack); break; } case CdoCmdPmSetWakeupSource: { uint32_t target; uint32_t source; uint32_t enable; if (parse_u32(&s, &target)) goto syntax_error; if (parse_u32(&s, &source)) goto syntax_error; if (parse_u32(&s, &enable)) goto syntax_error; cdocmd_add_pm_set_wakeup_source(seq, target, source, enable); break; } case CdoCmdPmSystemShutdown: { uint32_t type; uint32_t subtype; if (parse_u32(&s, &type)) goto syntax_error; if (parse_u32(&s, &subtype)) goto syntax_error; cdocmd_add_pm_system_shutdown(seq, type, subtype); break; } case CdoCmdPmRequestDevice: { uint32_t nodeid; uint32_t capabilities; uint32_t qos; uint32_t ack; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &capabilities)) goto syntax_error; if (parse_u32(&s, &qos)) goto syntax_error; if (parse_u32(&s, &ack)) goto syntax_error; cdocmd_add_pm_request_device(seq, nodeid, capabilities, qos, ack); break; } case CdoCmdPmReleaseDevice: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_release_device(seq, nodeid); break; } case CdoCmdPmSetRequirement: { uint32_t nodeid; uint32_t capabilities; uint32_t qos; uint32_t ack; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &capabilities)) goto syntax_error; if (parse_u32(&s, &qos)) goto syntax_error; if (parse_u32(&s, &ack)) goto syntax_error; cdocmd_add_pm_set_requirement(seq, nodeid, capabilities, qos, ack); break; } case CdoCmdPmSetMaxLatency: { uint32_t nodeid; uint32_t latency; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &latency)) goto syntax_error; cdocmd_add_pm_set_max_latency(seq, nodeid, latency); break; } case CdoCmdPmResetAssert: { uint32_t nodeid; uint32_t action; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &action)) goto syntax_error; cdocmd_add_pm_reset_assert(seq, nodeid, action); break; } case CdoCmdPmResetGetStatus: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_reset_get_status(seq, nodeid); break; } case CdoCmdPmPinctrlRequest: { uint32_t pinid; if (parse_u32(&s, &pinid)) goto syntax_error; cdocmd_add_pm_pinctrl_request(seq, pinid); break; } case CdoCmdPmPinctrlRelease: { uint32_t pinid; if (parse_u32(&s, &pinid)) goto syntax_error; cdocmd_add_pm_pinctrl_release(seq, pinid); break; } case CdoCmdPmPinctrlGetFunction: { uint32_t pinid; if (parse_u32(&s, &pinid)) goto syntax_error; cdocmd_add_pm_pinctrl_get_function(seq, pinid); break; } case CdoCmdPmPinctrlSetFunction: { uint32_t pinid; uint32_t funcid; if (parse_u32(&s, &pinid)) goto syntax_error; if (parse_u32(&s, &funcid)) goto syntax_error; cdocmd_add_pm_pinctrl_set_function(seq, pinid, funcid); break; } case CdoCmdPmPinctrlConfigParamGet: { uint32_t pinid; uint32_t param; if (parse_u32(&s, &pinid)) goto syntax_error; if (parse_u32(&s, ¶m)) goto syntax_error; cdocmd_add_pm_pinctrl_config_param_get(seq, pinid, param); break; } case CdoCmdPmPinctrlConfigParamSet: { uint32_t pinid; uint32_t param; uint32_t value; if (parse_u32(&s, &pinid)) goto syntax_error; if (parse_u32(&s, ¶m)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_pm_pinctrl_config_param_set(seq, pinid, param, value); break; } case CdoCmdPmIoctl: { uint32_t nodeid; uint32_t ioctlid; uint32_t * buf; uint32_t count; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &ioctlid)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_ioctl(seq, nodeid, ioctlid, buf, count, is_be_host()); free(buf); break; } case CdoCmdPmQueryData: { uint32_t nodeid; uint32_t * buf; uint32_t count; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_query_data(seq, nodeid, buf, count, is_be_host()); free(buf); break; } case CdoCmdPmClockEnable: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_enable(seq, nodeid); break; } case CdoCmdPmClockDisable: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_disable(seq, nodeid); break; } case CdoCmdPmClockGetState: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_getstate(seq, nodeid); break; } case CdoCmdPmClockSetDivider: { uint32_t nodeid; uint32_t div; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &div)) goto syntax_error; cdocmd_add_pm_clock_setdivider(seq, nodeid, div); break; } case CdoCmdPmClockGetDivider: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_getdivider(seq, nodeid); break; } case CdoCmdPmClockSetRate: { uint32_t nodeid; uint32_t rate; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &rate)) goto syntax_error; cdocmd_add_pm_clock_setrate(seq, nodeid, rate); break; } case CdoCmdPmClockGetRate: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_getrate(seq, nodeid); break; } case CdoCmdPmClockSetParent: { uint32_t nodeid; uint32_t parentid; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &parentid)) goto syntax_error; cdocmd_add_pm_clock_setparent(seq, nodeid, parentid); break; } case CdoCmdPmClockGetParent: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_clock_getparent(seq, nodeid); break; } case CdoCmdPmPllSetParameter: { uint32_t nodeid; uint32_t param; uint32_t value; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, ¶m)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_pm_pll_set_parameter(seq, nodeid, param, value); break; } case CdoCmdPmPllGetParameter: { uint32_t nodeid; uint32_t param; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, ¶m)) goto syntax_error; cdocmd_add_pm_pll_get_parameter(seq, nodeid, param); break; } case CdoCmdPmPllSetMode: { uint32_t nodeid; uint32_t value; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_pm_pll_set_mode(seq, nodeid, value); break; } case CdoCmdPmPllGetMode: { uint32_t nodeid; if (parse_u32(&s, &nodeid)) goto syntax_error; cdocmd_add_pm_pll_get_mode(seq, nodeid); break; } case CdoCmdPmAddSubsystem: { uint32_t ssid; if (parse_u32(&s, &ssid)) goto syntax_error; cdocmd_add_pm_add_subsystem(seq, ssid); break; } case CdoCmdPmDestroySubsystem: { uint32_t ssid; if (parse_u32(&s, &ssid)) goto syntax_error; cdocmd_add_pm_destroy_subsystem(seq, ssid); break; } case CdoCmdPmDescribeNodes: { uint32_t count; uint32_t * buf; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_describe_nodes(seq, buf, count, is_be_host()); break; } case CdoCmdPmAddNode: { uint32_t id; uint32_t count; uint32_t * buf; if (parse_u32(&s, &id)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_add_node(seq, id, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmAddNodeParent: { uint32_t id; uint32_t count; uint32_t * buf; if (parse_u32(&s, &id)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; if (count < 1) goto syntax_error; cdocmd_add_pm_add_node_parent(seq, id, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmAddNodeName: { uint32_t id; char * name; if (parse_u32(&s, &id)) goto syntax_error; if (iseol(&s)) goto syntax_error; if (parse_string(&s, &name)) goto syntax_error; cdocmd_add_pm_add_node_name(seq, id, name); free(name); break; } case CdoCmdPmAddRequirement: { uint32_t ssid; uint32_t nodeid; uint32_t flags; uint32_t count; uint32_t * buf; if (parse_u32(&s, &ssid)) goto syntax_error; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_add_requirement(seq, ssid, nodeid, flags, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmSetCurrentSubsystem: { uint32_t ssid; if (parse_u32(&s, &ssid)) goto syntax_error; cdocmd_add_pm_set_current_subsystem(seq, ssid); break; } case CdoCmdPmInitNode: { uint32_t id; uint32_t function; uint32_t count; uint32_t * buf; if (parse_u32(&s, &id)) goto syntax_error; if (parse_u32(&s, &function)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_init_node(seq, id, function, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmFeatureCheck: { uint32_t id; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_pm_feature_check(seq, id); break; } case CdoCmdPmIsoControl: { uint32_t nodeid; uint32_t value; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_pm_iso_control(seq, nodeid, value); break; } case CdoCmdPmBisr: { uint32_t tagid; if (parse_u32(&s, &tagid)) goto syntax_error; cdocmd_add_pm_bisr(seq, tagid); break; } case CdoCmdPmApplyTrim: { uint32_t trimtype; if (parse_u32(&s, &trimtype)) goto syntax_error; cdocmd_add_pm_apply_trim(seq, trimtype); break; } case CdoCmdPmNocClockEnable: { uint32_t nodeid; uint32_t count; uint32_t * buf; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_noc_clock_enable(seq, nodeid, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmIfNocClockEnable: { uint32_t index; uint32_t state; uint32_t level = 1; if (parse_u32(&s, &index)) goto syntax_error; if (parse_u32(&s, &state)) goto syntax_error; skipsp(s); if (istok(*s) && parse_u32(&s, &level)) goto syntax_error; cdocmd_add_pm_if_noc_clock_enable(seq, index, state, level); break; } case CdoCmdPmActivateSubsystem: { uint32_t id; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_pm_activate_subsystem(seq, id); break; } case CdoCmdPmSetNodeAccess: { uint32_t id; uint32_t count; uint32_t * buf; if (parse_u32(&s, &id)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_pm_set_node_access(seq, id, count, buf, is_be_host()); free(buf); break; } case CdoCmdPmForceHc: { uint32_t id; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_pm_force_hc(seq, id); break; } case CdoCmdCfuSetCrc32: { uint32_t flags; uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (flags != 0) { if (parse_u32(&s, &value)) goto syntax_error; } else { value = 0; } cdocmd_add_cfu_set_crc32(seq, flags, value); break; } case CdoCmdCfuDecompress: { uint32_t flags; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; cdocmd_add_cfu_decompress(seq, flags); break; } case CdoCmdCfuCramRW: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_cram_rw(seq, value); break; } case CdoCmdCfuSeuGo: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_seu_go(seq, value); break; } case CdoCmdCfuCrc8Dis: { uint32_t flags; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; cdocmd_add_cfu_crc8_dis(seq, flags); break; } case CdoCmdCfuSsiPerSlrPr: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_ssi_per_slr_pr(seq, value); break; } case CdoCmdCfuGsrGsc: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_gsr_gsc(seq, value); break; } case CdoCmdCfuGcapClkEn: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_gcap_clk_en(seq, value); break; } case CdoCmdCfuCfiType: { uint32_t value; if (seq->version >= CDO_VERSION_2_00) goto syntax_error; if (parse_u32(&s, &value)) goto syntax_error; cdocmd_add_cfu_cfi_type(seq, value); break; } case CdoCmdEmSetAction: { uint32_t nodeid; uint32_t action; uint32_t mask; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &action)) goto syntax_error; if (parse_u32(&s, &mask)) goto syntax_error; cdocmd_add_em_set_action(seq, nodeid, action, mask); break; } case CdoCmdLdrSetImageInfo: { uint32_t nodeid; uint32_t uid; uint32_t puid; uint32_t funcid; if (parse_u32(&s, &nodeid)) goto syntax_error; if (parse_u32(&s, &uid)) goto syntax_error; if (parse_u32(&s, &puid)) goto syntax_error; if (parse_u32(&s, &funcid)) goto syntax_error; cdocmd_add_ldr_set_image_info(seq, nodeid, uid, puid, funcid); break; } case CdoCmdLdrCframeClearCheck: { uint32_t id; if (parse_u32(&s, &id)) goto syntax_error; cdocmd_add_ldr_cframe_clear_check(seq, id); break; } case CdoCmdSemNpiTable: { uint32_t id; uint32_t flags; uint32_t count; uint32_t * buf; if (parse_u32(&s, &id)) goto syntax_error; if (parse_u32(&s, &flags)) goto syntax_error; if (parse_buf(&s, &buf, &count)) goto syntax_error; cdocmd_add_sem_npi_table(seq, id, flags, count, buf, is_be_host()); free(buf); break; } default: goto syntax_error; } if (!iseol(&s)) goto syntax_error; first = 0; } if (level > 0) { fprintf(stderr, "missing one or more end statements\n"); goto error; } free(line); return seq; syntax_error: fprintf(stderr, "syntax error: %s\n", line); error: cdocmd_delete_sequence(seq); free(line); return NULL; } static void print_x32(FILE * f, uint32_t v) { if (v == 0) { fprintf(f, "0"); } else { fprintf(f, "%#"PRIx32, v); } } static void print_x64(FILE * f, uint64_t v) { if (v == 0) { fprintf(f, "0"); } else { fprintf(f, "%#"PRIx64, v); } } static void print_buf(FILE * f, void * buf, uint32_t count) { uint32_t * p = (uint32_t *)buf; while (count > 0) { uint32_t v = *p++; fprintf(f, " "); print_x64(f, v); count--; } } static void print_string(FILE * f, char * str) { char * s = str; fputc('"', f); for (;;) { int c = *s++; if (c == '\0') break; if (c == '\\' || c == '"') { fputc('\\', f); } fputc(c, f); } fputc('"', f); } void cdoseq_to_source(FILE * f, CdoSequence * seq) { LINK * l = seq->cmds.next; uint32_t level = 0; fprintf(f, "version %"PRIu32".%"PRIu32"\n", seq->version >> 8, seq->version & (uint32_t)0xff); while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; if (level > 0 && cmd->type == CdoCmdEnd) level--; fprintf(f, "%*s", level*2, ""); switch (cmd->type) { case CdoCmdSection: fprintf(f, "section "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdGeneric: fprintf(f, "generic "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdComment: fprintf(f, "# %s\n", (char *)cmd->buf); break; case CdoCmdInclude: { fprintf(f, "include "); print_string(f, (char *)cmd->buf); fprintf(f, "\n"); break; } case CdoCmdSetBaseAddress: fprintf(f, "set_base_address "); print_x64(f, cmd->dstaddr); fprintf(f, "\n"); break; case CdoCmdWrite: fprintf(f, "write "); print_x64(f, cmd->dstaddr); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdSetBlock: fprintf(f, "set "); print_x64(f, cmd->dstaddr); fprintf(f, " %"PRIu32" ", cmd->count); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdWriteKeyhole: fprintf(f, "write_keyhole "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->value); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdMaskWrite: fprintf(f, "mask_write "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdMaskPoll: fprintf(f, "mask_poll "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->count); if (cmd->flags != 0 || cmd->errorcode != 0) { fprintf(f, " "); print_x64(f, cmd->flags); } if (cmd->errorcode != 0) { fprintf(f, " "); print_x64(f, cmd->errorcode); } fprintf(f, "\n"); break; case CdoCmdDelay: fprintf(f, "delay %"PRIu32"\n", cmd->value); break; case CdoCmdDmaXfer: fprintf(f, "dma_xfer "); print_x64(f, cmd->srcaddr); fprintf(f, " "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, " "); print_x64(f, cmd->flags); if (seq->version < CDO_VERSION_2_00 && cmd->buf) { print_buf(f, cmd->buf, cmd->count); } fprintf(f, "\n"); break; case CdoCmdCframeRead: fprintf(f, "cframe_read "); print_x64(f, cmd->flags); fprintf(f, " "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->value); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdSsitSyncMaster: fprintf(f, "ssit_sync_master"); fprintf(f, "\n"); break; case CdoCmdSsitSyncSlaves: fprintf(f, "ssit_sync_slaves "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, "\n"); break; case CdoCmdSsitWaitSlaves: fprintf(f, "ssit_wait_slaves "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, "\n"); break; case CdoCmdNop: fprintf(f, "nop"); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdEventLogging: fprintf(f, "event_logging "); print_x64(f, cmd->value); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdSetBoard: fprintf(f, "set_board "); print_string(f, (char *)cmd->buf); fprintf(f, "\n"); break; case CdoCmdSetPlmWdt: fprintf(f, "set_plm_wdt "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdLogString: fprintf(f, "log_string "); print_string(f, (char *)cmd->buf); fprintf(f, "\n"); break; case CdoCmdLogAddress: fprintf(f, "log_address "); print_x64(f, cmd->srcaddr); fprintf(f, "\n"); break; case CdoCmdMarker: fprintf(f, "marker "); print_x64(f, cmd->value); fprintf(f, " "); print_string(f, (char *)cmd->buf); fprintf(f, "\n"); break; case CdoCmdProc: fprintf(f, "proc "); print_x64(f, cmd->value); fprintf(f, "\n"); level++; break; case CdoCmdBegin: fprintf(f, "begin"); if (strlen(cmd->buf) != 0) { fprintf(f, " "); print_string(f, (char *)cmd->buf); } fprintf(f, "\n"); level++; break; case CdoCmdEnd: fprintf(f, "end\n"); break; case CdoCmdBreak: fprintf(f, "break"); if (cmd->value != 1) { fprintf(f, " "); print_x64(f, cmd->value); } fprintf(f, "\n"); break; case CdoCmdOtCheck: fprintf(f, "ot_check"); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPsmSequence: fprintf(f, "psm_sequence\n"); level++; break; case CdoCmdCdoSequence: fprintf(f, "cdo_sequence "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); level++; break; case CdoCmdScatterWrite: fprintf(f, "scatter_write "); print_x64(f, cmd->value); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdScatterWrite2: fprintf(f, "scatter_write2 "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->mask); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdTamperTrigger: fprintf(f, "tamper_trigger "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdSetIpiAccess: fprintf(f, "set_ipi_access "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, "\n"); break; case CdoCmdNpiSeq: fprintf(f, "npi_seq "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdNpiPreCfg: fprintf(f, "npi_precfg "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdNpiWrite: fprintf(f, "npi_write "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->flags); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdNpiShutdown: fprintf(f, "npi_shutdown "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmHnicxNpiDataXfer: fprintf(f, "pm_hnicx_npi_data_xfer "); print_x32(f, cmd->dstaddr); fprintf(f, " "); print_x32(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmGetApiVersion: fprintf(f, "pm_get_api_version"); fprintf(f, "\n"); break; case CdoCmdPmGetDeviceStatus: fprintf(f, "pm_get_device_status "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmRegisterNotifier: fprintf(f, "pm_register_notifier "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmRequestSuspend: fprintf(f, "pm_request_suspend "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmSelfSuspend: fprintf(f, "pm_self_suspend "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->dstaddr); fprintf(f, "\n"); break; case CdoCmdPmForcePowerdown: fprintf(f, "pm_force_powerdown "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmAbortSuspend: fprintf(f, "pm_abort_suspend "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmRequestWakeup: fprintf(f, "pm_request_wakeup "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->dstaddr); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmSetWakeupSource: fprintf(f, "pm_set_wakeup_source "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmSystemShutdown: fprintf(f, "pm_system_shutdown "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmRequestDevice: fprintf(f, "pm_request_device "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmReleaseDevice: fprintf(f, "pm_release_device "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmSetRequirement: fprintf(f, "pm_set_requirement "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmSetMaxLatency: fprintf(f, "pm_set_max_latency "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmResetAssert: fprintf(f, "pm_reset_assert "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmResetGetStatus: fprintf(f, "pm_reset_get_status "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmPinctrlRequest: fprintf(f, "pm_pinctrl_request "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmPinctrlRelease: fprintf(f, "pm_pinctrl_release "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmPinctrlGetFunction: fprintf(f, "pm_pinctrl_get_function "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmPinctrlSetFunction: fprintf(f, "pm_pinctrl_set_function "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmPinctrlConfigParamGet: fprintf(f, "pm_pinctrl_config_param_get "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmPinctrlConfigParamSet: fprintf(f, "pm_pinctrl_config_param_set "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmIoctl: fprintf(f, "pm_ioctl "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmQueryData: fprintf(f, "pm_query_data "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmClockEnable: fprintf(f, "pm_clock_enable "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmClockDisable: fprintf(f, "pm_clock_disable "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmClockGetState: fprintf(f, "pm_clock_get_state "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmClockSetDivider: fprintf(f, "pm_clock_set_divider "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmClockGetDivider: fprintf(f, "pm_clock_get_divider "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmClockSetRate: fprintf(f, "pm_clock_set_rate "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmClockGetRate: fprintf(f, "pm_clock_get_rate "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmClockSetParent: fprintf(f, "pm_clock_set_parent "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmClockGetParent: fprintf(f, "pm_clock_get_parent "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmPllSetParameter: fprintf(f, "pm_pll_set_parameter "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmPllGetParameter: fprintf(f, "pm_pll_get_parameter "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdPmPllSetMode: fprintf(f, "pm_pll_set_mode "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmPllGetMode: fprintf(f, "pm_pll_get_mode "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmAddSubsystem: fprintf(f, "pm_add_subsystem "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmDestroySubsystem: fprintf(f, "pm_destroy_subsystem "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmDescribeNodes: fprintf(f, "pm_describe_nodes"); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmAddNode: fprintf(f, "pm_add_node "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmAddNodeParent: fprintf(f, "pm_add_node_parent "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmAddNodeName: fprintf(f, "pm_add_node_name "); print_x64(f, cmd->id); fprintf(f, " "); print_string(f, (char *)cmd->buf); fprintf(f, "\n"); break; case CdoCmdPmAddRequirement: fprintf(f, "pm_add_requirement "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->flags); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmSetCurrentSubsystem: fprintf(f, "pm_set_current_subsystem "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmInitNode: fprintf(f, "pm_init_node "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmFeatureCheck: fprintf(f, "pm_feature_check "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmIsoControl: fprintf(f, "pm_iso_control "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdPmBisr: fprintf(f, "pm_bisr "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmApplyTrim: fprintf(f, "pm_apply_trim "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmNocClockEnable: fprintf(f, "pm_noc_clock_enable "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmIfNocClockEnable: fprintf(f, "pm_if_noc_clock_enable "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); if (cmd->flags != 1) { fprintf(f, " "); print_x64(f, cmd->flags); } fprintf(f, "\n"); break; case CdoCmdPmActivateSubsystem: fprintf(f, "pm_activate_subsystem "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdPmSetNodeAccess: fprintf(f, "pm_set_node_access "); print_x64(f, cmd->id); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdPmForceHc: fprintf(f, "pm_force_hc "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdCfuSetCrc32: fprintf(f, "cfu_set_crc32 "); print_x64(f, cmd->flags); if (cmd->flags != 0) { fprintf(f, " "); print_x64(f, cmd->value); } fprintf(f, "\n"); break; case CdoCmdCfuDecompress: fprintf(f, "cfu_decompress "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuCramRW: fprintf(f, "cfu_cram_rw "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdCfuSeuGo: fprintf(f, "cfu_seu_go "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuCrc8Dis: fprintf(f, "cfu_crc8_dis "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuSsiPerSlrPr: fprintf(f, "cfu_ssi_per_slr_pr "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuGsrGsc: fprintf(f, "cfu_gsr_gsc "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuGcapClkEn: fprintf(f, "cfu_gcap_clk_en "); print_x64(f, cmd->flags); fprintf(f, "\n"); break; case CdoCmdCfuCfiType: fprintf(f, "cfu_cfi_type "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdEmSetAction: fprintf(f, "em_set_action "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, "\n"); break; case CdoCmdLdrSetImageInfo: fprintf(f, "ldr_set_image_info "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->count); fprintf(f, "\n"); break; case CdoCmdLdrCframeClearCheck: fprintf(f, "cframe_clear_check "); print_x64(f, cmd->id); fprintf(f, "\n"); break; case CdoCmdSemNpiTable: fprintf(f, "sem_npi_table "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->flags); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdListSet: fprintf(f, "list_set "); print_x64(f, cmd->id); fprintf(f, " "); print_buf(f, cmd->buf, cmd->count); fprintf(f, "\n"); break; case CdoCmdListWrite: fprintf(f, "list_write "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdListMaskWrite: fprintf(f, "list_mask_write "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, "\n"); break; case CdoCmdListMaskPoll: fprintf(f, "list_mask_poll "); print_x64(f, cmd->id); fprintf(f, " "); print_x64(f, cmd->mask); fprintf(f, " "); print_x64(f, cmd->value); fprintf(f, " "); print_x64(f, cmd->count); if (cmd->flags != 0) { fprintf(f, " "); print_x64(f, cmd->flags); } fprintf(f, "\n"); break; case CdoCmdRunProc: fprintf(f, "run_proc "); print_x64(f, cmd->id); fprintf(f, "\n"); break; default: fprintf(f, "unknown command (%u)\n", cmd->type); break; } } } xilinx-bootgen-2024.2/cdo-source.h000077500000000000000000000020631475706442400170060ustar00rootroot00000000000000/****************************************************************************** * Copyright 2019-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef D_cdo_source #define D_cdo_source #include #include "cdo-command.h" CdoSequence * cdoseq_from_source(FILE * f); void cdoseq_to_source(FILE * f, CdoSequence * seq); char slr_id_from_source(char ch); uint32_t idcode_from_source(uint32_t id); #endif /* D_cdo_source */ xilinx-bootgen-2024.2/checksum-versal.cpp000077500000000000000000000143541475706442400204000ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include "checksum-versal.h" #include "bootimage.h" #include "binary.h" #include "Keccak-compact-versal.h" #ifdef USE_ISE_OPENSSL #include "OpenSSL/export/opensslconf.h" #include "OpenSSL/export/md5.h" #else #include #include #include #endif /******************************************************************************/ Section* VersalSHA3ChecksumContext::Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) { Section* section = new Section("sha3checksum", Size()); if (section != NULL) { cache.Sections.push_back(section); } return section; } /******************************************************************************/ Section* VersalSHA3ChecksumContext::Build(std::string name) { Section* section = new Section(name + ".sha3checksum", Size()); return section; } /******************************************************************************/ void VersalSHA3ChecksumContext::Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section) { uint32_t size = Size(); uint8_t* cksum_data = new uint8_t[size]; Versalcrypto_hash(cksum_data, data, length, !bootloader); if (bootloader) { memcpy(section->Data + length, cksum_data, size); } else { memcpy(section->Data, cksum_data, size); } delete[] cksum_data; } /******************************************************************************/ void VersalChecksumTable::Build(BootImage& bi, Binary& cache) { // allocate space for checksum data for (std::list::iterator i = bi.imageList.begin(); i != bi.imageList.end(); i++) { ImageHeader hdr(**i); std::list pHList = hdr.GetPartitionHeaderList(); for (std::list::iterator j = pHList.begin(); j != pHList.end(); j++) { PartitionHeader& partHdr(**j); /* Do not calculate checksum on entire partition for VersalNet bootloader - hashing is calculated on the first chunk + hash of previous chunk in VersalNet This is handled while doing the chunking of the partition. So need need to calculate again */ if (partHdr.IsBootloader()) { if (!bi.options.IsVersalNetSeries()) { // For FSBL, checksum should be like Bootimage Integrity, the checksum should be attached right at the end of the FSBL partHdr.partition->section->IncreaseLengthAndPadTo(partHdr.partition->section->Length + hdr.GetChecksumContext()->Size(), 0); } } else { // For other partitions, a new checksum section is created and added at the end of image. Section* s = hdr.GetChecksumContext()->Build(partHdr.partition->section->Name); partHdr.checksumSection = s; } } } } /******************************************************************************/ void VersalChecksumTable::Link(BootImage& bi) { for (std::list::iterator i = bi.imageList.begin(); i != bi.imageList.end(); i++) { ImageHeader hdr(**i); std::list pHList = hdr.GetPartitionHeaderList(); for (std::list::iterator j = pHList.begin(); j != pHList.end(); j++) { PartitionHeader& partHdr(**j); /* Do not calculate checksum on entire partition for VersalNet bootloader - hashing is calculated on the first chunk + hash of previous chunk in VersalNet This is handled while doing the chunking of the partition. So need need to calculate again */ if (partHdr.IsBootloader()) { if (!bi.options.IsVersalNetSeries()) { hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), partHdr.partition->section->Data, partHdr.partition->section->Length - hdr.GetChecksumContext()->Size(), partHdr.partition->section); } } else { for (std::list::iterator acs = partHdr.ac.begin(); acs != partHdr.ac.end(); acs++) { uint32_t len = 0; if ((*acs) && (*acs)->section) { len = partHdr.partition->section->Length + (*acs)->section->Length; uint8_t* buffer = new uint8_t[len]; memcpy(buffer, partHdr.partition->section->Data, partHdr.partition->section->Length); memcpy(buffer + partHdr.partition->section->Length, (*acs)->section->Data, (*acs)->section->Length); hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), buffer, len, partHdr.checksumSection); delete[] buffer; } else { if (partHdr.firstChunkSize != 0) { len = partHdr.firstChunkSize + SHA3_LENGTH_BYTES; } else { len = partHdr.partition->section->Length; } hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), partHdr.partition->section->Data, len, partHdr.checksumSection); } } } } } } xilinx-bootgen-2024.2/checksum-versal.h000077500000000000000000000046711475706442400200460ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootgenenum.h" #include "binary.h" #include "bootimage.h" #include "checksum.h" class BootImage; class Section; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MD5_LENGTH_BYTES 16 #define SHA2_LENGTH_BYTES 32 #define SHA3_LENGTH_BYTES 48 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalSHA3ChecksumContext : public ChecksumContext { public: Checksum::Type Type() { return Checksum::SHA3; } uint8_t Size() { return SHA3_LENGTH_BYTES; } Section* Build(Binary& cache, const uint8_t* data, const Binary::Length_t length); Section* Build(std::string name); void Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section); }; /******************************************************************************/ class VersalChecksumTable : public ChecksumTable { public: void Build(BootImage& bi, Binary& cache); void Link(BootImage& bi); }; xilinx-bootgen-2024.2/checksum.cpp000077500000000000000000000162011475706442400170770ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "checksum.h" #include "binary.h" #include "Keccak-compact.h" #ifdef USE_ISE_OPENSSL #include "OpenSSL/export/opensslconf.h" #include "OpenSSL/export/md5.h" #else #include #include #include #endif /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ Section* MD5ChecksumContext::Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) { Section* section = new Section("md5checksum", Size()); if(section != NULL) { cache.Sections.push_back(section); } return section; } /******************************************************************************/ void MD5ChecksumContext::Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section) { uint32_t size = Size(); uint8_t* cksum_data = new uint8_t [size]; MD5( data, length, cksum_data); if(bootloader) { memcpy(section->Data + length, cksum_data, size); } else { memcpy(section->Data, cksum_data, size); } delete [] cksum_data; } /******************************************************************************/ Section* SHA2ChecksumContext::Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) { Section* section = new Section("sha2checksum", Size()); if(section != NULL) { cache.Sections.push_back(section); } return section; } /******************************************************************************/ void SHA2ChecksumContext::Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section) { uint32_t size = Size(); uint8_t* cksum_data = new uint8_t [size]; SHA256(data, length, cksum_data); if(bootloader) { memcpy(section->Data + length, cksum_data, size); } else { memcpy(section->Data, cksum_data, size); } delete [] cksum_data; } /******************************************************************************/ Section* SHA3ChecksumContext::Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) { Section* section = new Section("sha3checksum", Size()); if(section != NULL) { cache.Sections.push_back(section); } return section; } /******************************************************************************/ void SHA3ChecksumContext::Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section) { uint32_t size = Size(); uint8_t* cksum_data = new uint8_t [size]; if(bootloader) { crypto_hash(cksum_data, data, length); memcpy(section->Data + length, cksum_data, size); } else { crypto_hash_NIST_SHA3(cksum_data, data, length); memcpy(section->Data, cksum_data, size); } delete [] cksum_data; } /******************************************************************************/ void ChecksumTable::Build(BootImage& bi, Binary& cache) { for(std::list::iterator i = bi.imageList.begin(); i!= bi.imageList.end(); i++) { ImageHeader hdr(**i); std::list pHList = hdr.GetPartitionHeaderList(); for(std::list::iterator j = pHList.begin(); j != pHList.end(); j++) { PartitionHeader& partHdr(**j); if(partHdr.IsBootloader()) { /* For FSBL, checksum should be like Bootimage Integrity, the checksum should be attached right at the end of the FSBL */ partHdr.partition->section->IncreaseLengthAndPadTo(partHdr.partition->section->Length + hdr.GetChecksumContext()->Size(), 0); } else { /* For other partitions, a new checksum section is created and added at the end of image. */ Section* s = hdr.GetChecksumContext()->Build(cache, partHdr.partition->section->Data, partHdr.partition->section->Length); partHdr.checksumSection = s; } } } } /******************************************************************************/ void ChecksumTable::Link(BootImage& bi) { for(std::list::iterator i = bi.imageList.begin(); i!= bi.imageList.end(); i++) { ImageHeader hdr(**i); std::list pHList = hdr.GetPartitionHeaderList(); for(std::list::iterator j = pHList.begin(); j != pHList.end(); j++) { PartitionHeader& partHdr(**j); if(partHdr.IsBootloader()) { hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), partHdr.partition->section->Data, partHdr.partition->section->Length - hdr.GetChecksumContext()->Size(), partHdr.partition->section); } else { for (std::list::iterator acs = partHdr.ac.begin(); acs != partHdr.ac.end(); acs++) { if ((*acs) && (*acs)->section) { uint32_t len = partHdr.partition->section->Length + (*acs)->section->Length; uint8_t* buffer = new uint8_t[len]; memcpy(buffer, partHdr.partition->section->Data, partHdr.partition->section->Length); memcpy(buffer + partHdr.partition->section->Length, (*acs)->section->Data, (*acs)->section->Length); hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), buffer, len, partHdr.checksumSection); delete[] buffer; } else { hdr.GetChecksumContext()->Link(partHdr.IsBootloader(), partHdr.partition->section->Data, partHdr.partition->section->Length, partHdr.checksumSection); } } } } } } xilinx-bootgen-2024.2/checksum.h000077500000000000000000000107561475706442400165550ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _CHECKSUM_H_ #define _CHECKSUM_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootgenenum.h" #include "binary.h" /* Forward Class References */ class BootImage; class Section; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MD5_LENGTH_BYTES 16 #define SHA2_LENGTH_BYTES 32 #define SHA3_LENGTH_BYTES 48 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ChecksumTable { public: ChecksumTable() {} virtual ~ChecksumTable() {} virtual void Build(BootImage& bi, Binary& cache); virtual void Link(BootImage& bi); }; /******************************************************************************/ class ChecksumContext { public: ChecksumContext() {} virtual ~ChecksumContext() {} virtual Checksum::Type Type() = 0; virtual uint8_t Size() { return 0; } virtual Section* Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) { return NULL; } virtual Section* Build(std::string name) { return NULL; } virtual void Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section) { } }; /******************************************************************************/ class NoneChecksumContext : public ChecksumContext { public: virtual Checksum::Type Type() { return Checksum::None; } }; /******************************************************************************/ class MD5ChecksumContext : public ChecksumContext { public: MD5ChecksumContext() {} ~MD5ChecksumContext() {} Checksum::Type Type() { return Checksum::MD5; } uint8_t Size() { return MD5_LENGTH_BYTES; } Section* Build(Binary& cache, const uint8_t* data, const Binary::Length_t length); void Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section); }; /******************************************************************************/ class SHA2ChecksumContext : public ChecksumContext { public: SHA2ChecksumContext() {} ~SHA2ChecksumContext() {} Checksum::Type Type() { return Checksum::SHA2; } uint8_t Size() { return SHA2_LENGTH_BYTES; } Section* Build(Binary& cache, const uint8_t* data, const Binary::Length_t length); void Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section); }; /******************************************************************************/ class SHA3ChecksumContext : public ChecksumContext { public: SHA3ChecksumContext() {} ~SHA3ChecksumContext() {} Checksum::Type Type() { return Checksum::SHA3; } uint8_t Size() { return SHA3_LENGTH_BYTES; } virtual Section* Build(Binary& cache, const uint8_t* data, const Binary::Length_t length) ; virtual Section* Build(std::string name) { return NULL; } virtual void Link(bool bootloader, const uint8_t* data, const Binary::Length_t length, Section* section); }; #endif xilinx-bootgen-2024.2/cmdoptions.l000077500000000000000000000267041475706442400171360ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the register initialization file */ /* Run the cmdoptions.y file first through bison to generate the regidit.tab.hpp file, which is included herein */ /* Then run this file through flex to generate the cmdoptions.yy.c source code */ %{ #include #include "cmdoptionsscanner.h" #include "cmdoptions.tab.hpp" typedef CO::BisonParser::token tok; %} %option nodefault yyclass="FlexScanner" noyywrap c++ noyywrap nounput batch debug %{ # define YY_USER_ACTION yylloc->columns (yyleng); %} %% %{ yylloc->step (); %} "/*" { comment(); } \/\/.*?\n /* ignore */; 0[xX][0-9A-Fa-f]+ yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; \-image return tok::_IMAGE; \-fill return tok::_FILL; \-o return tok::_O_TOK; \i return tok::I; \-p return tok::_P_TOK; \-w return tok::_W; on return tok::ON; off return tok::OFF; \-log return tok::_LOG; error return tok::ERROR; warning return tok::WARNING; info return tok::INFO; debug return tok::DEBUG; trace return tok::TRACE; \-bif_help return tok::_BIF_HELP; \-encrypt return tok::_ENCRYPT; bbram return tok::BBRAM; efuse return tok::EFUSE; HMAC return tok::HMAC; hmac return tok::HMAC; StartCBC return tok::STARTCBC; startcbc return tok::STARTCBC; Key0 return tok::KEY0; key0 return tok::KEY0; \-split return tok::_SPLIT; \-process_bitstream return tok::_PROCESS_BITSTREAM; mcs return tok::MCS; bin return tok::BIN; \-dual_qspi_mode return tok::_DUAL_QSPI_MODE; \-dual_ospi_mode return tok::_DUAL_OSPI_MODE; parallel return tok::PARALLEL; stacked return tok::STACKED; = return tok::EQUALS; , return tok::COMMA; \-debug return tok::_DEBUG_TOK; \-dump return tok::_DUMP; plm return tok::DUMP_PLM; pmc_cdo return tok::DUMP_PMC_CDO; boot_files return tok::DUMP_BOOT_FILES; slave_pdis return tok::DUMP_SLAVE_PDIS; \-dump_dir return tok::_DUMP_DIR; \-legacy return tok::_LEGACY; \-padimageheader return tok::_PADIMAGEHEADER; \-efuseppkbits return tok::_EFUSEPPKBITS; \-generate_hashes return tok::_GENERATE_HASHES; \-securedebugimage return tok::_SECUREDEBUG; \-authenticatedjtag return tok::_AUTHJTAG; \-generate_keys return tok::_GENERATE_KEYS; auth return tok::AUTH; pem return tok::PEM; rsa return tok::RSA; obfuscatedkey return tok::GREY; familykey return tok::METAL; ecdsa return tok::ECDSA; ecdsa-p384 return tok::ECDSA; ecdsa-p521 return tok::ECDSAP521; \-nonbooting return tok::_NONBOOTING; \-spksignature return tok::_SPKSIGNATURE; \-packagename return tok::_PACKAGENAME; \-arch return tok::_ARCH; zynq return tok::ZYNQ; zynqmp return tok::ZYNQMP; versal return tok::VERSAL; fpga return tok::FPGA; versalnet return tok::VERSALNET; \-r return tok::_R; \-read return tok::_READ; bh return tok::READ_BH; iht return tok::READ_IHT; ih return tok::READ_IH; pht return tok::READ_PHT; ac return tok::READ_AC; -enable_auth_opt return tok::_AUTH_OPTIMIZATION; \-verify_kdf return tok::_VERIFYKDF; \-verify return tok::_VERIFY; \-encryption_dump return tok::_ZYNQMPENCRDUMP; \-noauthblocks return tok::_NOAUTHBLOCKS; \-zynqmpes1 return tok::_ZYNQMPES1; \-overlay_cdo return tok::_OVERLAYCDO; \-out_type return tok::_OUT_TYPE; \-h return tok::_H; \-help return tok::_H; bif_help return tok::HBIFHELP; arch return tok::HARCH; enable_auth_opt return tok::HAUTHOPT; image return tok::HIMAGE; fill return tok::HFILL; o return tok::HO; p return tok::HP; w return tok::HW; efuseppkbits return tok::HEFUSEPPKBITS; generate_hashes return tok::HGENHASHES; legacy return tok::HLEGACY; padimageheader return tok::HPADHDR; spksignature return tok::H_SPKSIGN; packagename return tok::HPACKAGE; encrypt return tok::HENCRYPT; generate_keys return tok::HGENKEYS; dual_qspi_mode return tok::HDQSPI; log return tok::HLOG; zynqmpes1 return tok::HZYNQMPES1; process_bitstream return tok::HPROCESSBIT; nonbooting return tok::HNONBOOTING; encryption_dump return tok::HENCRDUMP; verify return tok::HVERIFY; verify_kdf return tok::HVERIFYKDF; securedebugimage return tok::HSECUREDEBUG; authenticatedjtag return tok::HSECUREDEBUG; read return tok::HREAD; dump return tok::HDUMP; dump_dir return tok::HDUMPDIR; overlay_cdo return tok::HOVLCDO; out_type return tok::HOUTTYPE; aarch32_mode return tok::H_BIF_AARCH32; big_endian return tok::H_BIF_BIGENDIAN; boot_config return tok::H_BIF_BOOTCONFIG; copy return tok::H_BIF_COPY; core return tok::H_BIF_CORE; delay_handoff return tok::H_BIF_DELAY_HANDOFF; delay_load return tok::H_BIF_DELAY_LOAD; file return tok::H_BIF_FILE; id return tok::H_BIF_ID; image return tok::H_BIF_IMAGE; metaheader return tok::H_BIF_METAHDR; name return tok::H_BIF_NAME; partition return tok::H_BIF_PARTITION; parent_id return tok::H_BIF_PARENTID; slr return tok::H_BIF_SLR; type return tok::H_BIF_TYPE; keysrc return tok::H_BIF_KEYSRC; init return tok::H_BIF_INIT; udf_bh return tok::H_BIF_UDFBH; aeskeyfile return tok::H_BIF_AES; ppkfile return tok::H_BIF_PPK; pskfile return tok::H_BIF_PSK; spkfile return tok::H_BIF_SPK; sskfile return tok::H_BIF_SSK; spksignature return tok::H_BIF_SPKSIGN; headersignature return tok::H_BIF_HDRSIGN; bootimage return tok::H_BIF_BOOTIMAGE; bootloader return tok::H_BIF_BL; encryption return tok::H_BIF_ENCR; pid return tok::H_BIF_PID; authentication return tok::H_BIF_AUTH; tcmboot return tok::H_BIF_TCMBOOT; optionaldata return tok::H_BIF_OPTIONALDATA; checksum return tok::H_BIF_CHKSM; owner return tok::H_BIF_POWNER; partition_owner return tok::H_BIF_POWNER; presign return tok::H_BIF_PRESIGN; udf_data return tok::H_BIF_UDF; xip_mode return tok::H_BIF_XIP; alignment return tok::H_BIF_ALIGN; offset return tok::H_BIF_OFFSET; reserve return tok::H_BIF_RES; load return tok::H_BIF_LOAD; startup return tok::H_BIF_STARTUP; keysrc_encryption return tok::H_BIF_KEYSRCENCR; fsbl_config return tok::H_BIF_FSBLCFG; boot_device return tok::H_BIF_BOOTDEV; destination_cpu return tok::H_BIF_DESTCPU; destination_device return tok::H_BIF_DESTDEV; exception_level return tok::H_BIF_EL; trustzone return tok::H_BIF_TZ; auth_params return tok::H_BIF_AUTHPARAM; bh_keyfile return tok::H_BIF_BHKEY; pmufw_image return tok::H_BIF_PFW; blocks return tok::H_BIF_BLOCKS; bh_key_iv return tok::H_BIF_BHIV; familykey return tok::H_BIF_METAL; early_handoff return tok::H_BIF_ELYHNDOFF; hivec return tok::H_BIF_HIVEC; bhsignature return tok::H_BIF_BHSIGN; split return tok::H_SPLIT; bootvectors return tok::H_BIF_BOOTVEC; puf_file return tok::H_BIF_PUFDATA; dpacm_enable return tok::H_DPACM_ENABLE; userkeys return tok::H_BIF_USERKEYS; pcr return tok::HVN_BIF_PCR; pcr_mindex return tok::HVN_BIF_PCR_MINDEX; imagestore return tok::HV_BIF_IMAGESTORE; [a-fA-F0-9]+ yylval->cstring=strdup(yytext); return tok::HEXSTRING; [0-9]?[a-zA-Z0-9.,_-]+ yylval->cstring=strdup(yytext); return tok::IDENTIFIER; ([a-zA-Z]:[\/\\])?[a-zA-Z0-9\/\\\\(\)@!#$%^&+._-]+ yylval->cstring=strdup(yytext); return tok::FILENAME; \"([a-zA-Z]:[\/\\])?[a-zA-Z0-9\/\\\\(\)@!#$%^&+._ -]+\" yylval->cstring=strdup(yytext+1); yylval->cstring[strlen(yytext)-2]=0; return tok::QFILENAME; [ \t]+ yylloc->step (); [\n]+ yylloc->lines (yyleng); yylloc->step (); . LOG_ERROR("Unknown option on command line: %s\n",yytext); %% void CO::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/cmdoptions.tab.cpp000077500000000000000000002626621475706442400202370ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton implementation for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* First part of user declarations. */ /* Line 279 of lalr1.cc */ #line 49 "../../s/cmdoptions.y" #include #include #include "cmdoptionsscanner.h" #include "version.h" void ShowHelp(); void ShowCmdHelp(int); void ShowBifHelp(int); void ShowCommonHelp(int,bool); /* Line 279 of lalr1.cc */ #line 49 "cmdoptions.tab.cpp" #include "cmdoptions.tab.hpp" /* User implementation prologue. */ /* Line 285 of lalr1.cc */ #line 57 "cmdoptions.tab.cpp" /* Unqualified %code blocks. */ /* Line 286 of lalr1.cc */ #line 45 "../../s/cmdoptions.y" static int yylex(CO::BisonParser::semantic_type * yylval, CO::BisonParser::location_type* loc, CO::FlexScanner &scanner); /* Line 286 of lalr1.cc */ #line 66 "cmdoptions.tab.cpp" # ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULL nullptr # else # define YY_NULL 0 # endif # endif #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* FIXME: INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ # ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (N) \ { \ (Current).begin = YYRHSLOC (Rhs, 1).begin; \ (Current).end = YYRHSLOC (Rhs, N).end; \ } \ else \ { \ (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ } \ while (/*CONSTCOND*/ false) # endif /* Suppress unused-variable warnings by "using" E. */ #define YYUSE(e) ((void) (e)) /* Enable debugging if requested. */ #if YYDEBUG /* A pseudo ostream that takes yydebug_ into account. */ # define YYCDEBUG if (yydebug_) (*yycdebug_) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug_) \ { \ *yycdebug_ << Title << ' '; \ yy_symbol_print_ ((Type), (Value), (Location)); \ *yycdebug_ << std::endl; \ } \ } while (false) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug_) \ yy_reduce_print_ (Rule); \ } while (false) # define YY_STACK_PRINT() \ do { \ if (yydebug_) \ yystack_print_ (); \ } while (false) #else /* !YYDEBUG */ # define YYCDEBUG if (false) std::cerr # define YY_SYMBOL_PRINT(Title, Type, Value, Location) YYUSE(Type) # define YY_REDUCE_PRINT(Rule) static_cast(0) # define YY_STACK_PRINT() static_cast(0) #endif /* !YYDEBUG */ #define yyerrok (yyerrstatus_ = 0) #define yyclearin (yychar = yyempty_) #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus_) /* Line 353 of lalr1.cc */ #line 24 "../../s/cmdoptions.y" namespace CO { /* Line 353 of lalr1.cc */ #line 162 "cmdoptions.tab.cpp" /// Build a parser object. BisonParser::BisonParser (CO::FlexScanner& scanner_yyarg, Options& options_yyarg) : #if YYDEBUG yydebug_ (false), yycdebug_ (&std::cerr), #endif scanner (scanner_yyarg), options (options_yyarg) { } BisonParser::~BisonParser () { } #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ inline void BisonParser::yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yyvaluep); std::ostream& yyo = debug_stream (); std::ostream& yyoutput = yyo; YYUSE (yyoutput); switch (yytype) { default: break; } } void BisonParser::yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm") << ' ' << yytname_[yytype] << " (" << *yylocationp << ": "; yy_symbol_value_print_ (yytype, yyvaluep, yylocationp); *yycdebug_ << ')'; } #endif void BisonParser::yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yymsg); YYUSE (yyvaluep); if (yymsg) YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } void BisonParser::yypop_ (unsigned int n) { yystate_stack_.pop (n); yysemantic_stack_.pop (n); yylocation_stack_.pop (n); } #if YYDEBUG std::ostream& BisonParser::debug_stream () const { return *yycdebug_; } void BisonParser::set_debug_stream (std::ostream& o) { yycdebug_ = &o; } BisonParser::debug_level_type BisonParser::debug_level () const { return yydebug_; } void BisonParser::set_debug_level (debug_level_type l) { yydebug_ = l; } #endif inline bool BisonParser::yy_pact_value_is_default_ (int yyvalue) { return yyvalue == yypact_ninf_; } inline bool BisonParser::yy_table_value_is_error_ (int yyvalue) { return yyvalue == yytable_ninf_; } int BisonParser::parse () { /// Lookahead and lookahead in internal form. int yychar = yyempty_; int yytoken = 0; // State. int yyn; int yylen = 0; int yystate = 0; // Error handling. int yynerrs_ = 0; int yyerrstatus_ = 0; /// Semantic value of the lookahead. static semantic_type yyval_default; semantic_type yylval = yyval_default; /// Location of the lookahead. location_type yylloc; /// The locations where the error started and ended. location_type yyerror_range[3]; /// $$. semantic_type yyval; /// @$. location_type yyloc; int yyresult; // FIXME: This shoud be completely indented. It is not yet to // avoid gratuitous conflicts when merging into the master branch. try { YYCDEBUG << "Starting parse" << std::endl; /* Initialize the stacks. The initial state will be pushed in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ yystate_stack_ = state_stack_type (0); yysemantic_stack_ = semantic_stack_type (0); yylocation_stack_ = location_stack_type (0); yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* New state. */ yynewstate: yystate_stack_.push (yystate); YYCDEBUG << "Entering state " << yystate << std::endl; /* Accept? */ if (yystate == yyfinal_) goto yyacceptlab; goto yybackup; /* Backup. */ yybackup: /* Try to take a decision without lookahead. */ yyn = yypact_[yystate]; if (yy_pact_value_is_default_ (yyn)) goto yydefault; /* Read a lookahead token. */ if (yychar == yyempty_) { YYCDEBUG << "Reading a token: "; yychar = yylex (&yylval, &yylloc, scanner); } /* Convert token to internal form. */ if (yychar <= yyeof_) { yychar = yytoken = yyeof_; YYCDEBUG << "Now at end of input." << std::endl; } else { yytoken = yytranslate_ (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) goto yydefault; /* Reduce or error. */ yyn = yytable_[yyn]; if (yyn <= 0) { if (yy_table_value_is_error_ (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted. */ yychar = yyempty_; yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus_) --yyerrstatus_; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact_[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: yylen = yyr2_[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. */ if (yylen) yyval = yysemantic_stack_[yylen - 1]; else yyval = yysemantic_stack_[0]; // Compute the default @$. { BIF::slice slice (yylocation_stack_, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen); } // Perform the reduction. YY_REDUCE_PRINT (yyn); switch (yyn) { case 5: /* Line 670 of lalr1.cc */ #line 111 "../../s/cmdoptions.y" { options.SetBifFilename((yysemantic_stack_[(2) - (2)].cstring)); } break; case 8: /* Line 670 of lalr1.cc */ #line 114 "../../s/cmdoptions.y" { options.GetOutputFileNames().push_back((yysemantic_stack_[(3) - (3)].cstring)); } break; case 9: /* Line 670 of lalr1.cc */ #line 115 "../../s/cmdoptions.y" { options.GetOutputFileNames().push_back((yysemantic_stack_[(2) - (2)].cstring)); } break; case 10: /* Line 670 of lalr1.cc */ #line 116 "../../s/cmdoptions.y" { options.SetDevicePartName((yysemantic_stack_[(2) - (2)].cstring)); } break; case 16: /* Line 670 of lalr1.cc */ #line 122 "../../s/cmdoptions.y" { options.SetEfuseHashFileName((yysemantic_stack_[(2) - (2)].cstring)); } break; case 17: /* Line 670 of lalr1.cc */ #line 123 "../../s/cmdoptions.y" { options.SetGenerateHashes(true); } break; case 18: /* Line 670 of lalr1.cc */ #line 124 "../../s/cmdoptions.y" { options.SetNonBootingFlag(true); } break; case 19: /* Line 670 of lalr1.cc */ #line 125 "../../s/cmdoptions.y" { options.SetLegacyFlag(true); } break; case 20: /* Line 670 of lalr1.cc */ #line 126 "../../s/cmdoptions.y" { options.SetPadHeaderTable(true); } break; case 21: /* Line 670 of lalr1.cc */ #line 127 "../../s/cmdoptions.y" { options.SetPadHeaderTable((bool)(strcmp((yysemantic_stack_[(3) - (3)].cstring),"0"))); } break; case 22: /* Line 670 of lalr1.cc */ #line 128 "../../s/cmdoptions.y" { options.SetPadHeaderTable((bool)(strcmp((yysemantic_stack_[(2) - (2)].cstring),"0"))); } break; case 26: /* Line 670 of lalr1.cc */ #line 132 "../../s/cmdoptions.y" { options.SetSpkSigFileName((yysemantic_stack_[(2) - (2)].cstring)); } break; case 27: /* Line 670 of lalr1.cc */ #line 133 "../../s/cmdoptions.y" { options.SetDevicePackageName((yysemantic_stack_[(2) - (2)].cstring)); } break; case 29: /* Line 670 of lalr1.cc */ #line 135 "../../s/cmdoptions.y" { options.SetArchType(Arch::ZYNQMP); } break; case 30: /* Line 670 of lalr1.cc */ #line 136 "../../s/cmdoptions.y" { options.SetNoAuthBlocksFlag(true); } break; case 32: /* Line 670 of lalr1.cc */ #line 138 "../../s/cmdoptions.y" { LOG_ERROR("'-debug' option is no more supported. Please use '-log' option"); } break; case 34: /* Line 670 of lalr1.cc */ #line 140 "../../s/cmdoptions.y" { options.SetZynqmpes1Flag(true); } break; case 35: /* Line 670 of lalr1.cc */ #line 141 "../../s/cmdoptions.y" { LOG_ERROR("The option '-securedebugimage' is deprecated. Use '-authenticatedjtag' instead."); } break; case 40: /* Line 670 of lalr1.cc */ #line 146 "../../s/cmdoptions.y" { options.SetDumpDirectory((yysemantic_stack_[(2) - (2)].cstring)); } break; case 41: /* Line 670 of lalr1.cc */ #line 147 "../../s/cmdoptions.y" { options.SetKDFTestVectorFile((yysemantic_stack_[(2) - (2)].cstring)); } break; case 42: /* Line 670 of lalr1.cc */ #line 148 "../../s/cmdoptions.y" { options.SetAuthOptimization();} break; case 43: /* Line 670 of lalr1.cc */ #line 149 "../../s/cmdoptions.y" { options.SetOverlayCDOFileName((yysemantic_stack_[(2) - (2)].cstring)); } break; case 49: /* Line 670 of lalr1.cc */ #line 157 "../../s/cmdoptions.y" { options.SetSplitType(File::MCS); } break; case 50: /* Line 670 of lalr1.cc */ #line 158 "../../s/cmdoptions.y" { options.SetSplitType(File::BIN); } break; case 51: /* Line 670 of lalr1.cc */ #line 161 "../../s/cmdoptions.y" { options.SetDoFill(true); } break; case 52: /* Line 670 of lalr1.cc */ #line 162 "../../s/cmdoptions.y" { options.SetDoFill(true); if ((yysemantic_stack_[(2) - (2)].number) >= 0 && (yysemantic_stack_[(2) - (2)].number) <= 255) options.SetOutputFillByte((uint8_t)(yysemantic_stack_[(2) - (2)].number)); else LOG_ERROR("'-fill' - Fill byte must be 8 bits"); } break; case 53: /* Line 670 of lalr1.cc */ #line 169 "../../s/cmdoptions.y" { options.SetOutType(File::MCS); } break; case 54: /* Line 670 of lalr1.cc */ #line 170 "../../s/cmdoptions.y" { options.SetOutType(File::BIN); } break; case 55: /* Line 670 of lalr1.cc */ #line 173 "../../s/cmdoptions.y" { ShowHelp(); exit(0); } break; case 56: /* Line 670 of lalr1.cc */ #line 174 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HBIFHELP); exit(0); } break; case 57: /* Line 670 of lalr1.cc */ #line 175 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HARCH); exit(0); } break; case 58: /* Line 670 of lalr1.cc */ #line 176 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HAUTHOPT); exit(0); } break; case 59: /* Line 670 of lalr1.cc */ #line 177 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HIMAGE); exit(0); } break; case 60: /* Line 670 of lalr1.cc */ #line 178 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HFILL); exit(0); } break; case 61: /* Line 670 of lalr1.cc */ #line 179 "../../s/cmdoptions.y" { ShowCommonHelp(CO::BisonParser::token::H_SPLIT,true); exit(0); } break; case 62: /* Line 670 of lalr1.cc */ #line 180 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HO); exit(0); } break; case 63: /* Line 670 of lalr1.cc */ #line 181 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HP); exit(0); } break; case 64: /* Line 670 of lalr1.cc */ #line 182 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HW); exit(0); } break; case 65: /* Line 670 of lalr1.cc */ #line 183 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HEFUSEPPKBITS); exit(0); } break; case 66: /* Line 670 of lalr1.cc */ #line 184 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HGENHASHES); exit(0); } break; case 67: /* Line 670 of lalr1.cc */ #line 185 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HLEGACY); exit(0); } break; case 68: /* Line 670 of lalr1.cc */ #line 186 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HPADHDR); exit(0); } break; case 69: /* Line 670 of lalr1.cc */ #line 187 "../../s/cmdoptions.y" { ShowCommonHelp(CO::BisonParser::token::H_SPKSIGN,true); exit(0); } break; case 70: /* Line 670 of lalr1.cc */ #line 188 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HPACKAGE); exit(0); } break; case 71: /* Line 670 of lalr1.cc */ #line 189 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HENCRYPT); exit(0); } break; case 72: /* Line 670 of lalr1.cc */ #line 190 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HGENKEYS); exit(0); } break; case 73: /* Line 670 of lalr1.cc */ #line 191 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HDQSPI); exit(0); } break; case 74: /* Line 670 of lalr1.cc */ #line 192 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HLOG); exit(0); } break; case 75: /* Line 670 of lalr1.cc */ #line 193 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HZYNQMPES1); exit(0); } break; case 76: /* Line 670 of lalr1.cc */ #line 194 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HPROCESSBIT); exit(0); } break; case 77: /* Line 670 of lalr1.cc */ #line 195 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HNONBOOTING); exit(0); } break; case 78: /* Line 670 of lalr1.cc */ #line 196 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HENCRDUMP); exit(0); } break; case 79: /* Line 670 of lalr1.cc */ #line 197 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HVERIFY); exit(0); } break; case 80: /* Line 670 of lalr1.cc */ #line 198 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HVERIFYKDF); exit(0); } break; case 81: /* Line 670 of lalr1.cc */ #line 199 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HREAD); exit(0); } break; case 82: /* Line 670 of lalr1.cc */ #line 200 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HSECUREDEBUG); exit(0); } break; case 83: /* Line 670 of lalr1.cc */ #line 201 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HDUMP); exit(0); } break; case 84: /* Line 670 of lalr1.cc */ #line 202 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HDUMPDIR); exit(0); } break; case 85: /* Line 670 of lalr1.cc */ #line 203 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HOVLCDO); exit(0); } break; case 86: /* Line 670 of lalr1.cc */ #line 204 "../../s/cmdoptions.y" { ShowCmdHelp(CO::BisonParser::token::HOUTTYPE); exit(0); } break; case 87: /* Line 670 of lalr1.cc */ #line 207 "../../s/cmdoptions.y" { ShowBifHelp(0); exit(0); } break; case 88: /* Line 670 of lalr1.cc */ #line 208 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_INIT); exit(0); } break; case 89: /* Line 670 of lalr1.cc */ #line 209 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_UDFBH); exit(0); } break; case 90: /* Line 670 of lalr1.cc */ #line 210 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_AES); exit(0); } break; case 91: /* Line 670 of lalr1.cc */ #line 211 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PPK); exit(0); } break; case 92: /* Line 670 of lalr1.cc */ #line 212 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PSK); exit(0); } break; case 93: /* Line 670 of lalr1.cc */ #line 213 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_SPK); exit(0); } break; case 94: /* Line 670 of lalr1.cc */ #line 214 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_SSK); exit(0); } break; case 95: /* Line 670 of lalr1.cc */ #line 215 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_SPKSIGN); exit(0); } break; case 96: /* Line 670 of lalr1.cc */ #line 216 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_HDRSIGN); exit(0); } break; case 97: /* Line 670 of lalr1.cc */ #line 217 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTIMAGE); exit(0); } break; case 98: /* Line 670 of lalr1.cc */ #line 218 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BL); exit(0); } break; case 99: /* Line 670 of lalr1.cc */ #line 219 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_ENCR); exit(0); } break; case 100: /* Line 670 of lalr1.cc */ #line 220 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PID); exit(0); } break; case 101: /* Line 670 of lalr1.cc */ #line 221 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_AUTH); exit(0); } break; case 102: /* Line 670 of lalr1.cc */ #line 222 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_TCMBOOT); exit(0); } break; case 103: /* Line 670 of lalr1.cc */ #line 223 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_OPTIONALDATA); exit(0); } break; case 104: /* Line 670 of lalr1.cc */ #line 224 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_CHKSM); exit(0); } break; case 105: /* Line 670 of lalr1.cc */ #line 225 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_POWNER); exit(0); } break; case 106: /* Line 670 of lalr1.cc */ #line 226 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PRESIGN); exit(0); } break; case 107: /* Line 670 of lalr1.cc */ #line 227 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_UDF); exit(0); } break; case 108: /* Line 670 of lalr1.cc */ #line 228 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_XIP); exit(0); } break; case 109: /* Line 670 of lalr1.cc */ #line 229 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_ALIGN); exit(0); } break; case 110: /* Line 670 of lalr1.cc */ #line 230 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_OFFSET); exit(0); } break; case 111: /* Line 670 of lalr1.cc */ #line 231 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_RES); exit(0); } break; case 112: /* Line 670 of lalr1.cc */ #line 232 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_LOAD); exit(0); } break; case 113: /* Line 670 of lalr1.cc */ #line 233 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_STARTUP); exit(0); } break; case 114: /* Line 670 of lalr1.cc */ #line 234 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_KEYSRC); exit(0); } break; case 115: /* Line 670 of lalr1.cc */ #line 235 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_FSBLCFG); exit(0); } break; case 116: /* Line 670 of lalr1.cc */ #line 236 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTDEV); exit(0); } break; case 117: /* Line 670 of lalr1.cc */ #line 237 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_DESTCPU); exit(0); } break; case 118: /* Line 670 of lalr1.cc */ #line 238 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_DESTDEV); exit(0); } break; case 119: /* Line 670 of lalr1.cc */ #line 239 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_EL); exit(0); } break; case 120: /* Line 670 of lalr1.cc */ #line 240 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_TZ); exit(0); } break; case 121: /* Line 670 of lalr1.cc */ #line 241 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_AUTHPARAM); exit(0); } break; case 122: /* Line 670 of lalr1.cc */ #line 242 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BHKEY); exit(0); } break; case 123: /* Line 670 of lalr1.cc */ #line 243 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PFW); exit(0); } break; case 124: /* Line 670 of lalr1.cc */ #line 244 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BLOCKS); exit(0); } break; case 125: /* Line 670 of lalr1.cc */ #line 245 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BHIV); exit(0); } break; case 126: /* Line 670 of lalr1.cc */ #line 246 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_METAL); exit(0); } break; case 127: /* Line 670 of lalr1.cc */ #line 247 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_ELYHNDOFF); exit(0); } break; case 128: /* Line 670 of lalr1.cc */ #line 248 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_HIVEC); exit(0); } break; case 129: /* Line 670 of lalr1.cc */ #line 249 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BHSIGN); exit(0); } break; case 130: /* Line 670 of lalr1.cc */ #line 250 "../../s/cmdoptions.y" { ShowCommonHelp(CO::BisonParser::token::H_SPLIT,false); exit(0); } break; case 131: /* Line 670 of lalr1.cc */ #line 251 "../../s/cmdoptions.y" { ShowCommonHelp(CO::BisonParser::token::H_SPKSIGN,false); exit(0); } break; case 132: /* Line 670 of lalr1.cc */ #line 252 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTVEC); exit(0); } break; case 133: /* Line 670 of lalr1.cc */ #line 253 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PUFDATA); exit(0); } break; case 134: /* Line 670 of lalr1.cc */ #line 254 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_AARCH32); exit(0); } break; case 135: /* Line 670 of lalr1.cc */ #line 255 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BIGENDIAN); exit(0); } break; case 136: /* Line 670 of lalr1.cc */ #line 256 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTCONFIG); exit(0); } break; case 137: /* Line 670 of lalr1.cc */ #line 257 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_COPY); exit(0); } break; case 138: /* Line 670 of lalr1.cc */ #line 258 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_CORE); exit(0); } break; case 139: /* Line 670 of lalr1.cc */ #line 259 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_DELAY_HANDOFF); exit(0); } break; case 140: /* Line 670 of lalr1.cc */ #line 260 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_DELAY_LOAD); exit(0); } break; case 141: /* Line 670 of lalr1.cc */ #line 261 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_FILE); exit(0); } break; case 142: /* Line 670 of lalr1.cc */ #line 262 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_ID); exit(0); } break; case 143: /* Line 670 of lalr1.cc */ #line 263 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_IMAGE); exit(0); } break; case 144: /* Line 670 of lalr1.cc */ #line 264 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_METAHDR); exit(0); } break; case 145: /* Line 670 of lalr1.cc */ #line 265 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_NAME); exit(0); } break; case 146: /* Line 670 of lalr1.cc */ #line 266 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PARENTID); exit(0); } break; case 147: /* Line 670 of lalr1.cc */ #line 267 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_PARTITION); exit(0); } break; case 148: /* Line 670 of lalr1.cc */ #line 268 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_SLR); exit(0); } break; case 149: /* Line 670 of lalr1.cc */ #line 269 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_TYPE); exit(0); } break; case 150: /* Line 670 of lalr1.cc */ #line 270 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_KEYSRCENCR); exit(0); } break; case 151: /* Line 670 of lalr1.cc */ #line 271 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_DPACM_ENABLE); exit(0); } break; case 152: /* Line 670 of lalr1.cc */ #line 272 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::H_BIF_USERKEYS); exit(0); } break; case 153: /* Line 670 of lalr1.cc */ #line 273 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::HVN_BIF_PCR); exit(0); } break; case 154: /* Line 670 of lalr1.cc */ #line 274 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::HVN_BIF_PCR_MINDEX); exit(0); } break; case 155: /* Line 670 of lalr1.cc */ #line 275 "../../s/cmdoptions.y" { ShowBifHelp(CO::BisonParser::token::HV_BIF_IMAGESTORE); exit(0); } break; case 156: /* Line 670 of lalr1.cc */ #line 278 "../../s/cmdoptions.y" { options.SetOverwrite(true); } break; case 157: /* Line 670 of lalr1.cc */ #line 279 "../../s/cmdoptions.y" { options.SetOverwrite(true); } break; case 158: /* Line 670 of lalr1.cc */ #line 280 "../../s/cmdoptions.y" { options.SetOverwrite(false); } break; case 160: /* Line 670 of lalr1.cc */ #line 284 "../../s/cmdoptions.y" { options.SetLogLevel(LogLevel::ERROR); } break; case 161: /* Line 670 of lalr1.cc */ #line 285 "../../s/cmdoptions.y" { options.SetLogLevel(LogLevel::WARNING); } break; case 162: /* Line 670 of lalr1.cc */ #line 286 "../../s/cmdoptions.y" { options.SetLogLevel(LogLevel::INFO); } break; case 163: /* Line 670 of lalr1.cc */ #line 287 "../../s/cmdoptions.y" { options.SetLogLevel(LogLevel::DEBUG); } break; case 164: /* Line 670 of lalr1.cc */ #line 288 "../../s/cmdoptions.y" { options.SetLogLevel(LogLevel::TRACE); } break; case 165: /* Line 670 of lalr1.cc */ #line 291 "../../s/cmdoptions.y" { options.SetEncryptedKeySource(KeySource::BbramRedKey); } break; case 166: /* Line 670 of lalr1.cc */ #line 292 "../../s/cmdoptions.y" { options.SetEncryptedKeySource(KeySource::EfuseRedKey); } break; case 168: /* Line 670 of lalr1.cc */ #line 295 "../../s/cmdoptions.y" { options.SetStartCbc((yysemantic_stack_[(3) - (3)].cstring));} break; case 170: /* Line 670 of lalr1.cc */ #line 296 "../../s/cmdoptions.y" { options.SetKey0((yysemantic_stack_[(3) - (3)].cstring));} break; case 172: /* Line 670 of lalr1.cc */ #line 297 "../../s/cmdoptions.y" { options.SetHmac((yysemantic_stack_[(3) - (3)].cstring));} break; case 174: /* Line 670 of lalr1.cc */ #line 298 "../../s/cmdoptions.y" { options.SetEncryptionKeyFile((yysemantic_stack_[(1) - (1)].cstring));} break; case 176: /* Line 670 of lalr1.cc */ #line 302 "../../s/cmdoptions.y" { options.SetProcessBitstreamType(File::MCS); } break; case 177: /* Line 670 of lalr1.cc */ #line 303 "../../s/cmdoptions.y" { options.SetProcessBitstreamType(File::BIN); } break; case 178: /* Line 670 of lalr1.cc */ #line 306 "../../s/cmdoptions.y" { options.SetDualQspiMode(QspiMode::PARALLEL_LQSPI); } break; case 179: /* Line 670 of lalr1.cc */ #line 307 "../../s/cmdoptions.y" { options.SetDualQspiMode(QspiMode::STACKED); } break; case 180: /* Line 670 of lalr1.cc */ #line 310 "../../s/cmdoptions.y" { LOG_ERROR("'parallel' option is not supported with '-dual_ospi_mode'."); } break; case 181: /* Line 670 of lalr1.cc */ #line 311 "../../s/cmdoptions.y" { options.SetDualQspiMode(QspiMode::STACKED); } break; case 182: /* Line 670 of lalr1.cc */ #line 314 "../../s/cmdoptions.y" { options.SetQspiSize((uint16_t)(yysemantic_stack_[(1) - (1)].number)); } break; case 183: /* Line 670 of lalr1.cc */ #line 315 "../../s/cmdoptions.y" { options.SetQspiSize((uint16_t)atoi((yysemantic_stack_[(1) - (1)].cstring))); } break; case 184: /* Line 670 of lalr1.cc */ #line 318 "../../s/cmdoptions.y" { options.SetOspiSize((uint16_t)(yysemantic_stack_[(1) - (1)].number)); } break; case 185: /* Line 670 of lalr1.cc */ #line 319 "../../s/cmdoptions.y" { options.SetOspiSize((uint16_t)atoi((yysemantic_stack_[(1) - (1)].cstring))); } break; case 186: /* Line 670 of lalr1.cc */ #line 322 "../../s/cmdoptions.y" { options.SetArchType(Arch::ZYNQ); } break; case 187: /* Line 670 of lalr1.cc */ #line 323 "../../s/cmdoptions.y" { options.SetArchType(Arch::ZYNQMP); } break; case 188: /* Line 670 of lalr1.cc */ #line 324 "../../s/cmdoptions.y" { options.SetArchType(Arch::VERSAL); } break; case 189: /* Line 670 of lalr1.cc */ #line 325 "../../s/cmdoptions.y" { options.SetArchType(Arch::FPGA); } break; case 190: /* Line 670 of lalr1.cc */ #line 326 "../../s/cmdoptions.y" { options.SetArchType(Arch::VERSALNET); } break; case 192: /* Line 670 of lalr1.cc */ #line 330 "../../s/cmdoptions.y" { options.SetGreyKeyGeneration(true); } break; case 193: /* Line 670 of lalr1.cc */ #line 331 "../../s/cmdoptions.y" { options.SetMetalKeyGeneration(true); } break; case 194: /* Line 670 of lalr1.cc */ #line 332 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::PEM); } break; case 195: /* Line 670 of lalr1.cc */ #line 333 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::RSA); } break; case 196: /* Line 670 of lalr1.cc */ #line 334 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::ECDSA); } break; case 197: /* Line 670 of lalr1.cc */ #line 335 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::ECDSAP521); } break; case 198: /* Line 670 of lalr1.cc */ #line 338 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::PEM); } break; case 199: /* Line 670 of lalr1.cc */ #line 339 "../../s/cmdoptions.y" { options.SetAuthKeyGeneration(GenAuthKeys::RSA); } break; case 200: /* Line 670 of lalr1.cc */ #line 342 "../../s/cmdoptions.y" { options.SetSecureDebugAuthType(Authentication::ECDSA); options.SetSecureDebugImageFile("secureDebugImage-ecdsa.bin"); } break; case 201: /* Line 670 of lalr1.cc */ #line 344 "../../s/cmdoptions.y" { options.SetSecureDebugAuthType(Authentication::RSA); options.SetSecureDebugImageFile("secureDebugImage-rsa.bin"); } break; case 202: /* Line 670 of lalr1.cc */ #line 347 "../../s/cmdoptions.y" { options.SetSecureDebugImageFile((yysemantic_stack_[(2) - (2)].cstring)); } break; case 204: /* Line 670 of lalr1.cc */ #line 350 "../../s/cmdoptions.y" { options.SetSecureDebugAuthType(Authentication::ECDSA); options.SetSecureDebugImageFile("authenticatedJtagImage-ecdsa.bin"); } break; case 205: /* Line 670 of lalr1.cc */ #line 352 "../../s/cmdoptions.y" { options.SetSecureDebugAuthType(Authentication::RSA); options.SetSecureDebugImageFile("authenticatedJtagImage-rsa.bin"); } break; case 206: /* Line 670 of lalr1.cc */ #line 356 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(1) - (1)].cstring)); options.SetVerifyImageOption(true); } break; case 207: /* Line 670 of lalr1.cc */ #line 359 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(1) - (1)].cstring)); options.SetReadImageOption(ReadImageOption::ALL); } break; case 208: /* Line 670 of lalr1.cc */ #line 361 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (1)].cstring)); } break; case 209: /* Line 670 of lalr1.cc */ #line 364 "../../s/cmdoptions.y" { options.SetReadImageOption(ReadImageOption::BH); } break; case 210: /* Line 670 of lalr1.cc */ #line 365 "../../s/cmdoptions.y" { options.SetReadImageOption(ReadImageOption::IHT); } break; case 211: /* Line 670 of lalr1.cc */ #line 366 "../../s/cmdoptions.y" { options.SetReadImageOption(ReadImageOption::IH); } break; case 212: /* Line 670 of lalr1.cc */ #line 367 "../../s/cmdoptions.y" { options.SetReadImageOption(ReadImageOption::PHT); } break; case 213: /* Line 670 of lalr1.cc */ #line 368 "../../s/cmdoptions.y" { options.SetReadImageOption(ReadImageOption::AC); } break; case 214: /* Line 670 of lalr1.cc */ #line 371 "../../s/cmdoptions.y" { options.SetDumpOption(DumpOption::BH); } break; case 215: /* Line 670 of lalr1.cc */ #line 372 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (1)].cstring)); options.SetDumpOption(DumpOption::BH); } break; case 216: /* Line 670 of lalr1.cc */ #line 374 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (2)].cstring)); options.SetDumpOption(DumpOption::BH); } break; case 217: /* Line 670 of lalr1.cc */ #line 376 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(1) - (1)].cstring)); options.SetDumpOption(DumpOption::PARTITIONS); } break; case 218: /* Line 670 of lalr1.cc */ #line 378 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (1)].cstring)); options.SetDumpOption(DumpOption::PLM); } break; case 219: /* Line 670 of lalr1.cc */ #line 380 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (1)].cstring)); options.SetDumpOption(DumpOption::PMC_CDO); } break; case 220: /* Line 670 of lalr1.cc */ #line 382 "../../s/cmdoptions.y" { options.SetReadImageFile((yysemantic_stack_[(2) - (1)].cstring)); options.SetDumpOption(DumpOption::BOOT_FILES); } break; case 221: /* Line 670 of lalr1.cc */ #line 384 "../../s/cmdoptions.y" { options.SetDumpOption(DumpOption::SLAVE_PDIS); } break; case 222: /* Line 670 of lalr1.cc */ #line 387 "../../s/cmdoptions.y" { options.SetEncryptionDump(true,"aes_log.txt"); } break; case 223: /* Line 670 of lalr1.cc */ #line 388 "../../s/cmdoptions.y" { options.SetEncryptionDump(true,(yysemantic_stack_[(1) - (1)].cstring)); } break; /* Line 670 of lalr1.cc */ #line 1586 "cmdoptions.tab.cpp" default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc); yypop_ (yylen); yylen = 0; YY_STACK_PRINT (); yysemantic_stack_.push (yyval); yylocation_stack_.push (yyloc); /* Shift the result of the reduction. */ yyn = yyr1_[yyn]; yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0]; if (0 <= yystate && yystate <= yylast_ && yycheck_[yystate] == yystate_stack_[0]) yystate = yytable_[yystate]; else yystate = yydefgoto_[yyn - yyntokens_]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus_) { ++yynerrs_; if (yychar == yyempty_) yytoken = yyempty_; error (yylloc, yysyntax_error_ (yystate, yytoken)); } yyerror_range[1] = yylloc; if (yyerrstatus_ == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= yyeof_) { /* Return failure if at end of input. */ if (yychar == yyeof_) YYABORT; } else { yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); yychar = yyempty_; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (false) goto yyerrorlab; yyerror_range[1] = yylocation_stack_[yylen - 1]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ yypop_ (yylen); yylen = 0; yystate = yystate_stack_[0]; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus_ = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact_[yystate]; if (!yy_pact_value_is_default_ (yyn)) { yyn += yyterror_; if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_) { yyn = yytable_[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yystate_stack_.height () == 1) YYABORT; yyerror_range[1] = yylocation_stack_[0]; yydestruct_ ("Error: popping", yystos_[yystate], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); yystate = yystate_stack_[0]; YY_STACK_PRINT (); } yyerror_range[2] = yylloc; // Using YYLLOC is tempting, but would change the location of // the lookahead. YYLOC is available though. YYLLOC_DEFAULT (yyloc, yyerror_range, 2); yysemantic_stack_.push (yylval); yylocation_stack_.push (yyloc); /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos_[yyn], &yysemantic_stack_[0], &yylocation_stack_[0]); yystate = yyn; goto yynewstate; /* Accept. */ yyacceptlab: yyresult = 0; goto yyreturn; /* Abort. */ yyabortlab: yyresult = 1; goto yyreturn; yyreturn: if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ yypop_ (yylen); while (1 < yystate_stack_.height ()) { yydestruct_ ("Cleanup: popping", yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } return yyresult; } catch (...) { YYCDEBUG << "Exception caught: cleaning lookahead and stack" << std::endl; // Do not try to display the values of the reclaimed symbols, // as their printer might throw an exception. if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc); } while (1 < yystate_stack_.height ()) { yydestruct_ (YY_NULL, yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } throw; } } // Generate an error message. std::string BisonParser::yysyntax_error_ (int, int) { return YY_("syntax error"); } /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ const signed char BisonParser::yypact_ninf_ = -79; const short int BisonParser::yypact_[] = { -79, 19, 125, -79, -57, -59, 32, 115, -79, -79, -79, -50, -78, 176, -5, 20, 69, 94, -57, 4, -79, 85, 87, 104, -79, -79, -57, -57, -79, 64, -57, -51, -46, -44, 98, -40, -57, -57, -57, -79, -57, -79, -79, -79, -79, -79, -79, -79, -79, -79, -57, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -57, 95, -79, -79, -79, -79, -79, -79, -79, -79, -79, -72, -79, -79, -64, -79, -79, -79, -79, -79, -79, -79, 6, -79, -79, -79, -79, 105, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -57, -79, -79, 30, -79, 66, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, 44, 62, -79, -79, -79, -79, -79, -79, 68, 78, 93, -79, 70, 97, -57, -79, 96, -79, -79, -79 }; /* YYDEFACT[S] -- default reduction number in state S. Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ const unsigned char BisonParser::yydefact_[] = { 3, 0, 2, 1, 0, 51, 0, 55, 32, 19, 18, 0, 87, 159, 0, 0, 0, 0, 0, 0, 29, 0, 0, 156, 30, 34, 0, 0, 17, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 222, 4, 7, 46, 47, 48, 45, 5, 175, 52, 0, 9, 56, 57, 59, 60, 62, 63, 64, 65, 66, 67, 68, 69, 58, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 82, 81, 80, 83, 84, 85, 86, 61, 13, 27, 131, 88, 89, 90, 91, 92, 93, 94, 95, 128, 96, 97, 98, 100, 99, 101, 104, 127, 129, 102, 103, 105, 106, 107, 108, 109, 110, 111, 112, 120, 113, 114, 115, 116, 117, 118, 119, 130, 121, 122, 123, 124, 126, 125, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 147, 148, 149, 150, 146, 151, 152, 153, 154, 155, 14, 160, 161, 162, 163, 164, 12, 49, 50, 6, 176, 177, 23, 53, 54, 44, 221, 214, 217, 39, 40, 186, 187, 188, 189, 190, 28, 178, 0, 24, 180, 0, 25, 157, 158, 11, 43, 16, 22, 0, 26, 194, 195, 197, 0, 192, 193, 196, 31, 201, 200, 35, 205, 204, 36, 203, 165, 166, 167, 10, 207, 37, 206, 38, 41, 223, 33, 8, 216, 218, 219, 220, 215, 182, 183, 179, 184, 185, 181, 21, 198, 199, 191, 202, 0, 169, 209, 210, 211, 212, 213, 208, 0, 0, 171, 168, 0, 0, 173, 170, 0, 174, 15, 172 }; /* YYPGOTO[NTERM-NUM]. */ const signed char BisonParser::yypgoto_[] = { -79, -79, -79, -79, -6, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, -79 }; /* YYDEFGOTO[NTERM-NUM]. */ const short int BisonParser::yydefgoto_[] = { -1, 1, 2, 41, 47, 162, 42, 168, 83, 153, 188, 159, 211, 238, 247, 251, 255, 49, 165, 182, 185, 228, 231, 179, 201, 235, 204, 207, 208, 216, 214, 244, 172, 219 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF_, syntax error. */ const signed char BisonParser::yytable_ninf_ = -1; const unsigned short int BisonParser::yytable_[] = { 51, 194, 195, 196, 197, 198, 199, 202, 200, 205, 226, 171, 173, 203, 227, 206, 160, 161, 229, 3, 189, 190, 230, 48, 193, 85, 43, 44, 45, 46, 213, 215, 217, 84, 218, 174, 175, 176, 50, 177, 178, 163, 164, 212, 220, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 166, 167, 232, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 43, 44, 45, 46, 237, 222, 223, 224, 169, 180, 181, 183, 184, 4, 5, 6, 245, 7, 8, 9, 10, 11, 12, 13, 239, 240, 241, 242, 243, 14, 15, 186, 187, 16, 17, 191, 192, 246, 18, 248, 19, 252, 233, 234, 20, 209, 210, 21, 22, 221, 249, 23, 170, 225, 24, 25, 26, 27, 28, 29, 30, 31, 43, 44, 45, 46, 250, 256, 32, 253, 33, 34, 0, 0, 35, 154, 155, 156, 157, 158, 0, 0, 36, 0, 0, 0, 0, 236, 37, 38, 39, 40, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82 }; /* YYCHECK. */ const short int BisonParser::yycheck_[] = { 6, 52, 53, 54, 55, 56, 57, 53, 59, 53, 82, 17, 18, 59, 86, 59, 21, 22, 82, 0, 26, 27, 86, 82, 30, 103, 83, 84, 85, 86, 36, 37, 38, 83, 40, 31, 32, 33, 6, 35, 36, 21, 22, 83, 50, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 21, 22, 86, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 83, 84, 85, 86, 89, 25, 26, 27, 29, 39, 40, 39, 40, 3, 4, 5, 87, 7, 8, 9, 10, 11, 12, 13, 73, 74, 75, 76, 77, 19, 20, 42, 43, 23, 24, 86, 87, 90, 28, 86, 30, 86, 52, 53, 34, 62, 63, 37, 38, 170, 87, 41, 73, 73, 44, 45, 46, 47, 48, 49, 50, 51, 83, 84, 85, 86, 88, 86, 58, 87, 60, 61, -1, -1, 64, 14, 15, 16, 17, 18, -1, -1, 72, -1, -1, -1, -1, 208, 78, 79, 80, 81, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -1, 115, 116, 117, 118, 119, 120, 121, 122, -1, -1, -1, -1, -1, -1, -1, 251, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 }; /* STOS_[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ const unsigned char BisonParser::yystos_[] = { 0, 194, 195, 0, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 19, 20, 23, 24, 28, 30, 34, 37, 38, 41, 44, 45, 46, 47, 48, 49, 50, 51, 58, 60, 61, 64, 72, 78, 79, 80, 81, 196, 199, 83, 84, 85, 86, 197, 82, 210, 6, 197, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, 121, 122, 159, 201, 83, 103, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 202, 14, 15, 16, 17, 18, 204, 21, 22, 198, 21, 22, 211, 21, 22, 200, 29, 73, 197, 225, 197, 31, 32, 33, 35, 36, 216, 39, 40, 212, 39, 40, 213, 42, 43, 203, 197, 197, 86, 87, 197, 52, 53, 54, 55, 56, 57, 59, 217, 53, 59, 219, 53, 59, 220, 221, 62, 63, 205, 83, 197, 223, 197, 222, 197, 197, 226, 197, 197, 25, 26, 27, 73, 82, 86, 214, 82, 86, 215, 86, 52, 53, 218, 197, 89, 206, 73, 74, 75, 76, 77, 224, 87, 90, 207, 86, 87, 88, 208, 86, 87, 197, 209, 86 }; #if YYDEBUG /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding to YYLEX-NUM. */ const unsigned short int BisonParser::yytoken_number_[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ const unsigned char BisonParser::yyr1_[] = { 0, 193, 194, 195, 195, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 203, 203, 203, 204, 204, 204, 204, 204, 204, 205, 205, 206, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 223, 223, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 225, 225, 226, 226 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ const unsigned char BisonParser::yyr2_[] = { 0, 2, 1, 0, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 6, 2, 1, 1, 1, 1, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 0, 3, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 0, 1 }; #if YYDEBUG /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at \a yyntokens_, nonterminals. */ const char* const BisonParser::yytname_[] = { "$end", "error", "$undefined", "_IMAGE", "_FILL", "_O_TOK", "I", "_H", "_DEBUG_TOK", "_LEGACY", "_NONBOOTING", "_PACKAGENAME", "_BIF_HELP", "_LOG", "ERROR", "WARNING", "INFO", "DEBUG", "TRACE", "_SPLIT", "_PROCESS_BITSTREAM", "MCS", "BIN", "_OUT_TYPE", "_DUMP", "DUMP_PLM", "DUMP_PMC_CDO", "DUMP_BOOT_FILES", "_DUMP_DIR", "DUMP_SLAVE_PDIS", "_ARCH", "ZYNQ", "ZYNQMP", "VERSAL", "_R", "FPGA", "VERSALNET", "_DUAL_QSPI_MODE", "_DUAL_OSPI_MODE", "PARALLEL", "STACKED", "_W", "ON", "OFF", "_NOAUTHBLOCKS", "_ZYNQMPES1", "_OVERLAYCDO", "_EFUSEPPKBITS", "_GENERATE_HASHES", "_PADIMAGEHEADER", "_SPKSIGNATURE", "_GENERATE_KEYS", "PEM", "RSA", "ECDSAP521", "AUTH", "GREY", "METAL", "_SECUREDEBUG", "ECDSA", "_AUTHJTAG", "_ENCRYPT", "BBRAM", "EFUSE", "_P_TOK", "_INTERFACE", "SMAPx8", "SMAPx16", "SMAPx32", "SPI", "BPIx8", "BPIx16", "_READ", "READ_BH", "READ_IHT", "READ_IH", "READ_PHT", "READ_AC", "_VERIFY", "_VERIFYKDF", "_AUTH_OPTIMIZATION", "_ZYNQMPENCRDUMP", "HEXVALUE", "IDENTIFIER", "FILENAME", "QFILENAME", "HEXSTRING", "EQUALS", "HMAC", "STARTCBC", "KEY0", "COMMA", "HBIFHELP", "HARCH", "HIMAGE", "HFILL", "HO", "HP", "HW", "HEFUSEPPKBITS", "HGENHASHES", "HLEGACY", "HPADHDR", "H_SPKSIGN", "HAUTHOPT", "HPACKAGE", "HENCRYPT", "HGENKEYS", "HDQSPI", "HLOG", "HZYNQMPES1", "HPROCESSBIT", "HNONBOOTING", "HENCRDUMP", "HPOSTPROCESS", "HVERIFY", "HSECUREDEBUG", "HREAD", "HVERIFYKDF", "HDUMP", "HDUMPDIR", "HOVLCDO", "HOUTTYPE", "H_BIF_INIT", "H_BIF_UDFBH", "H_BIF_AES", "H_BIF_PPK", "H_BIF_PSK", "H_BIF_SPK", "H_BIF_SSK", "H_BIF_SPKSIGN", "H_BIF_HIVEC", "H_BIF_HDRSIGN", "H_BIF_BOOTIMAGE", "H_BIF_BL", "H_BIF_PID", "H_BIF_ENCR", "H_BIF_AUTH", "H_BIF_CHKSM", "H_BIF_ELYHNDOFF", "H_BIF_BHSIGN", "H_BIF_TCMBOOT", "H_BIF_OPTIONALDATA", "H_BIF_POWNER", "H_BIF_PRESIGN", "H_BIF_UDF", "H_BIF_XIP", "H_BIF_ALIGN", "H_BIF_OFFSET", "H_BIF_RES", "H_BIF_LOAD", "H_BIF_TZ", "H_BIF_STARTUP", "H_BIF_KEYSRC", "H_BIF_FSBLCFG", "H_BIF_BOOTDEV", "H_BIF_DESTCPU", "H_BIF_DESTDEV", "H_BIF_EL", "H_SPLIT", "H_BIF_AUTHPARAM", "H_BIF_BHKEY", "H_BIF_PFW", "H_BIF_BLOCKS", "H_BIF_METAL", "H_BIF_BHIV", "H_BIF_BOOTVEC", "H_BIF_PUFDATA", "H_BIF_PTYPE", "H_BIF_IMAGECFG", "H_BIF_PMCCONFIG", "H_BIF_AARCH32", "H_BIF_BIGENDIAN", "H_BIF_BOOTCONFIG", "H_BIF_COPY", "H_BIF_CORE", "H_BIF_DELAY_HANDOFF", "H_BIF_DELAY_LOAD", "H_BIF_FILE", "H_BIF_ID", "H_BIF_IMAGE", "H_BIF_METAHDR", "H_BIF_NAME", "H_BIF_PARTITION", "H_BIF_SLR", "H_BIF_TYPE", "H_BIF_KEYSRCENCR", "H_BIF_PARENTID", "H_DPACM_ENABLE", "H_BIF_USERKEYS", "HVN_BIF_PCR", "HVN_BIF_PCR_MINDEX", "HV_BIF_IMAGESTORE", "$accept", "top", "option_list", "option", "filename", "memsplit", "filloption", "outputType", "helpoption", "bifhelpoption", "wopt", "loglevel", "keysource", "startcbc", "key0", "hmac", "keyfile", "number", "bitfile_type", "qpsi_mode", "opsi_mode", "qspi_size", "ospi_size", "archOptions", "key_type", "auth_key_options", "auth_type", "authJtagOptions", "authJtagType", "verifyImageOptions", "readImageOptions", "readType", "dumpOptions", "encrDumpOptions", YY_NULL }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ const BisonParser::rhs_number_type BisonParser::yyrhs_[] = { 194, 0, -1, 195, -1, -1, 195, 196, -1, 3, 197, -1, 19, 198, -1, 199, -1, 5, 6, 197, -1, 5, 197, -1, 64, 83, -1, 41, 203, -1, 13, 204, -1, 7, 201, -1, 12, 202, -1, 61, 205, 206, 207, 208, 209, -1, 47, 197, -1, 48, -1, 10, -1, 9, -1, 49, -1, 49, 87, 86, -1, 49, 86, -1, 20, 211, -1, 37, 212, -1, 38, 213, -1, 50, 197, -1, 11, 83, -1, 30, 216, -1, 34, -1, 44, -1, 51, 217, -1, 8, -1, 81, 226, -1, 45, -1, 58, 219, -1, 60, 220, -1, 72, 223, -1, 78, 222, -1, 24, 225, -1, 28, 197, -1, 79, 197, -1, 80, -1, 46, 197, -1, 23, 200, -1, 86, -1, 83, -1, 84, -1, 85, -1, 21, -1, 22, -1, 4, -1, 4, 210, -1, 21, -1, 22, -1, -1, 92, -1, 93, -1, 104, -1, 94, -1, 95, -1, 159, -1, 96, -1, 97, -1, 98, -1, 99, -1, 100, -1, 101, -1, 102, -1, 103, -1, 105, -1, 106, -1, 107, -1, 108, -1, 109, -1, 110, -1, 111, -1, 112, -1, 113, -1, 115, -1, 118, -1, 117, -1, 116, -1, 119, -1, 120, -1, 121, -1, 122, -1, -1, 123, -1, 124, -1, 125, -1, 126, -1, 127, -1, 128, -1, 129, -1, 130, -1, 132, -1, 133, -1, 134, -1, 136, -1, 135, -1, 137, -1, 141, -1, 142, -1, 138, -1, 143, -1, 144, -1, 145, -1, 146, -1, 147, -1, 148, -1, 149, -1, 150, -1, 152, -1, 153, -1, 154, -1, 155, -1, 156, -1, 157, -1, 158, -1, 151, -1, 160, -1, 161, -1, 162, -1, 163, -1, 165, -1, 164, -1, 139, -1, 131, -1, 140, -1, 159, -1, 103, -1, 166, -1, 167, -1, 171, -1, 172, -1, 173, -1, 174, -1, 175, -1, 176, -1, 177, -1, 178, -1, 179, -1, 180, -1, 181, -1, 182, -1, 187, -1, 183, -1, 184, -1, 185, -1, 186, -1, 188, -1, 189, -1, 190, -1, 191, -1, 192, -1, -1, 42, -1, 43, -1, -1, 14, -1, 15, -1, 16, -1, 17, -1, 18, -1, 62, -1, 63, -1, -1, 89, 87, 86, -1, -1, 90, 87, 86, -1, -1, 88, 87, 86, -1, -1, 197, -1, 82, -1, 21, -1, 22, -1, 39, -1, 40, 214, -1, 39, -1, 40, 215, -1, 82, -1, 86, -1, 82, -1, 86, -1, 31, -1, 32, -1, 33, -1, 35, -1, 36, -1, 55, 218, -1, 56, -1, 57, -1, 52, -1, 53, -1, 59, -1, 54, -1, 52, -1, 53, -1, 59, -1, 53, -1, 221, 197, -1, 221, -1, 59, -1, 53, -1, 197, -1, 197, -1, 197, 224, -1, 73, -1, 74, -1, 75, -1, 76, -1, 77, -1, 73, -1, 197, 73, -1, 73, 197, -1, 197, -1, 197, 25, -1, 197, 26, -1, 197, 27, -1, 29, -1, -1, 197, -1 }; /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ const unsigned short int BisonParser::yyprhs_[] = { 0, 0, 3, 5, 6, 9, 12, 15, 17, 21, 24, 27, 30, 33, 36, 39, 46, 49, 51, 53, 55, 57, 61, 64, 67, 70, 73, 76, 79, 82, 84, 86, 89, 91, 94, 96, 99, 102, 105, 108, 111, 114, 117, 119, 122, 125, 127, 129, 131, 133, 135, 137, 139, 142, 144, 146, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 347, 349, 351, 352, 354, 356, 358, 360, 362, 364, 366, 367, 371, 372, 376, 377, 381, 382, 384, 386, 388, 390, 392, 395, 397, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 444, 446, 448, 450, 452, 454, 457, 459, 461, 463, 465, 467, 469, 472, 475, 477, 480, 483, 486, 488, 489 }; /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ const unsigned short int BisonParser::yyrline_[] = { 0, 105, 105, 107, 108, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 155, 155, 155, 155, 157, 158, 161, 162, 169, 170, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 278, 279, 280, 283, 284, 285, 286, 287, 288, 291, 292, 295, 295, 296, 296, 297, 297, 298, 298, 300, 302, 303, 306, 307, 310, 311, 314, 315, 318, 319, 322, 323, 324, 325, 326, 329, 330, 331, 332, 333, 334, 335, 338, 339, 342, 344, 347, 348, 350, 352, 356, 359, 361, 364, 365, 366, 367, 368, 371, 372, 374, 376, 378, 380, 382, 384, 387, 388 }; // Print the state stack on the debug stream. void BisonParser::yystack_print_ () { *yycdebug_ << "Stack now"; for (state_stack_type::const_iterator i = yystate_stack_.begin (); i != yystate_stack_.end (); ++i) *yycdebug_ << ' ' << *i; *yycdebug_ << std::endl; } // Report on the debug stream that the rule \a yyrule is going to be reduced. void BisonParser::yy_reduce_print_ (int yyrule) { unsigned int yylno = yyrline_[yyrule]; int yynrhs = yyr2_[yyrule]; /* Print the symbols being reduced, and their result. */ *yycdebug_ << "Reducing stack by rule " << yyrule - 1 << " (line " << yylno << "):" << std::endl; /* The symbols being reduced. */ for (int yyi = 0; yyi < yynrhs; yyi++) YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", yyrhs_[yyprhs_[yyrule] + yyi], &(yysemantic_stack_[(yynrhs) - (yyi + 1)]), &(yylocation_stack_[(yynrhs) - (yyi + 1)])); } #endif // YYDEBUG /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ BisonParser::token_number_type BisonParser::yytranslate_ (int t) { static const token_number_type translate_table[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 }; if ((unsigned int) t <= yyuser_token_number_max_) return translate_table[t]; else return yyundef_token_; } const int BisonParser::yyeof_ = 0; const int BisonParser::yylast_ = 274; const int BisonParser::yynnts_ = 34; const int BisonParser::yyempty_ = -2; const int BisonParser::yyfinal_ = 3; const int BisonParser::yyterror_ = 1; const int BisonParser::yyerrcode_ = 256; const int BisonParser::yyntokens_ = 193; const unsigned int BisonParser::yyuser_token_number_max_ = 447; const BisonParser::token_number_type BisonParser::yyundef_token_ = 2; /* Line 1141 of lalr1.cc */ #line 24 "../../s/cmdoptions.y" } // CO /* Line 1141 of lalr1.cc */ #line 2348 "cmdoptions.tab.cpp" /* Line 1142 of lalr1.cc */ #line 391 "../../s/cmdoptions.y" // int outputByteWidth; // Binary::Address_t baseAddress; // uint32_t defaultAlignment; void ShowHelp() { std::cout << HELP << std::endl; } void ShowCommonHelp(int a, bool cmdhelp) { switch(a) { case CO::BisonParser::token::H_SPLIT: if(cmdhelp) std::cout << SPLITHELP << std::endl; else std::cout << H_BIF_SPLIT_H << std::endl; break; case CO::BisonParser::token::H_SPKSIGN: if(cmdhelp) std::cout << SPKSIGNHELP << std::endl; else std::cout << H_BIF_SPKSIGN_H << std::endl; break; case 0: std::cout << HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void ShowCmdHelp(int a) { switch (a) { case CO::BisonParser::token::HARCH: std::cout << ARCHHELP << std::endl; break; case CO::BisonParser::token::HAUTHOPT: std::cout << ENABLEAUTHOPTHELP << std::endl; break; case CO::BisonParser::token::HIMAGE: std::cout << IMAGEHELP << std::endl; break; case CO::BisonParser::token::HFILL: std::cout << FILLHELP << std::endl; break; case CO::BisonParser::token::HO: std::cout << OHELP << std::endl; break; case CO::BisonParser::token::HP: std::cout << PHELP << std::endl; break; case CO::BisonParser::token::HW: std::cout << WHELP << std::endl; break; case CO::BisonParser::token::HEFUSEPPKBITS: std::cout << EFUSEPPKBITSHELP << std::endl; break; case CO::BisonParser::token::HZYNQMPES1: std::cout << ZYNQMPES1HELP << std::endl; break; case CO::BisonParser::token::HGENHASHES: std::cout << GENERATEHASHESHELP << std::endl; break; case CO::BisonParser::token::HPADHDR: std::cout << PADHDRHELP << std::endl; break; case CO::BisonParser::token::HENCRYPT: std::cout << ENCRYPTHELP << std::endl; break; case CO::BisonParser::token::HGENKEYS: std::cout << GENKEYSHELP << std::endl; break; case CO::BisonParser::token::HDQSPI: std::cout << DQSPIHELP << std::endl; break; case CO::BisonParser::token::HLOG: std::cout << LOGHELP << std::endl; break; case CO::BisonParser::token::HBIFHELP: std::cout << BIFHELP << std::endl; break; case CO::BisonParser::token::HPROCESSBIT: std::cout << PROCESSBITHELP << std::endl; break; case CO::BisonParser::token::HNONBOOTING: std::cout << NONBOOTINGHELP << std::endl; break; case CO::BisonParser::token::HENCRDUMP: std::cout << ENCRDUMPHELP << std::endl; break; case CO::BisonParser::token::HVERIFY: std::cout << VERIFYHELP << std::endl; break; case CO::BisonParser::token::HPOSTPROCESS: std::cout << POSTPROCESSHELP << std::endl; break; case CO::BisonParser::token::HVERIFYKDF: std::cout << VERIFYKDFHELP << std::endl; break; case CO::BisonParser::token::HREAD: std::cout << READHELP << std::endl; break; case CO::BisonParser::token::HSECUREDEBUG: std::cout << SECUREDEBUGHELP << std::endl; break; case CO::BisonParser::token::HDUMP: std::cout << DUMPHELP << std::endl; break; case CO::BisonParser::token::HDUMPDIR: std::cout << DUMPDIRHELP << std::endl; break; case CO::BisonParser::token::HOVLCDO: std::cout << OVERLAYCDO << std::endl; break; case CO::BisonParser::token::HOUTTYPE: std::cout << OUTTYPEHELP << std::endl; break; case 0: std::cout << HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void ShowBifHelp(int a) { switch (a) { case CO::BisonParser::token::H_BIF_INIT: std::cout << H_BIF_INIT_H << std::endl; break; case CO::BisonParser::token::H_BIF_UDFBH: std::cout << H_BIF_UDFBH_H << std::endl; break; case CO::BisonParser::token::H_BIF_AES: std::cout << H_BIF_AES_H << std::endl; break; case CO::BisonParser::token::H_BIF_PPK: case CO::BisonParser::token::H_BIF_PSK: case CO::BisonParser::token::H_BIF_SPK: case CO::BisonParser::token::H_BIF_SSK: std::cout << H_BIF_PPK_H << std::endl; break; case CO::BisonParser::token::H_BIF_SPKSIGN: std::cout << H_BIF_SPKSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_HDRSIGN: std::cout << H_BIF_HDRSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTIMAGE: std::cout << H_BIF_BOOTIMAGE_H << std::endl; break; case CO::BisonParser::token::H_BIF_BL: std::cout << H_BIF_BL_H << std::endl; break; case CO::BisonParser::token::H_BIF_ENCR: std::cout << H_BIF_ENCR_H << std::endl; break; case CO::BisonParser::token::H_BIF_PID: std::cout << H_BIF_PID_H << std::endl; break; case CO::BisonParser::token::H_BIF_AUTH: std::cout << H_BIF_AUTH_H << std::endl; break; case CO::BisonParser::token::H_BIF_TCMBOOT: std::cout << H_BIF_TCMBOOT_H << std::endl; break; case CO::BisonParser::token::H_BIF_OPTIONALDATA: std::cout << H_BIF_OPTIONALDATA_H << std::endl; break; case CO::BisonParser::token::H_BIF_CHKSM: std::cout << H_BIF_CHKSM_H << std::endl; break; case CO::BisonParser::token::H_BIF_POWNER: std::cout << H_BIF_POWNER_H << std::endl; break; case CO::BisonParser::token::H_BIF_PRESIGN: std::cout << H_BIF_PRESIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_UDF: std::cout << H_BIF_UDF_H << std::endl; break; case CO::BisonParser::token::H_BIF_XIP: std::cout << H_BIF_XIP_H << std::endl; break; case CO::BisonParser::token::H_BIF_ALIGN: std::cout << H_BIF_ALIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_OFFSET: std::cout << H_BIF_OFFSET_H << std::endl; break; case CO::BisonParser::token::H_BIF_RES: std::cout << H_BIF_RES_H << std::endl; break; case CO::BisonParser::token::H_BIF_LOAD: std::cout << H_BIF_LOAD_H << std::endl; break; case CO::BisonParser::token::H_BIF_STARTUP: std::cout << H_BIF_STARTUP_H << std::endl; break; case CO::BisonParser::token::H_BIF_KEYSRC: std::cout << H_BIF_KEYSRC_H << std::endl; break; case CO::BisonParser::token::H_BIF_FSBLCFG: std::cout << H_BIF_FSBLCFG_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTDEV: std::cout << H_BIF_BOOTDEV_H << std::endl; break; case CO::BisonParser::token::H_BIF_DESTCPU: std::cout << H_BIF_DESTCPU_H << std::endl; break; case CO::BisonParser::token::H_BIF_DESTDEV: std::cout << H_BIF_DESTDEV_H << std::endl; break; case CO::BisonParser::token::H_BIF_EL: std::cout << H_BIF_EL_H << std::endl; break; case CO::BisonParser::token::H_BIF_TZ: std::cout << H_BIF_TZ_H << std::endl; break; case CO::BisonParser::token::H_BIF_AUTHPARAM: std::cout << H_BIF_AUTHPARAM_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHKEY: std::cout << H_BIF_BHKEY_H << std::endl; break; case CO::BisonParser::token::H_BIF_PFW: std::cout << H_BIF_PFW_H << std::endl; break; case CO::BisonParser::token::H_BIF_BLOCKS: std::cout << H_BIF_BLOCKS_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHIV: std::cout << H_BIF_BHIV_H << std::endl; break; case CO::BisonParser::token::H_BIF_METAL: std::cout << H_BIF_METAL_H << std::endl; break; case CO::BisonParser::token::H_BIF_ELYHNDOFF: std::cout << H_BIF_ELYHNDOFF_H << std::endl; break; case CO::BisonParser::token::H_BIF_HIVEC: std::cout << H_BIF_HIVEC_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHSIGN: std::cout << H_BIF_BHSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTVEC: std::cout << H_BIF_BOOTVEC_H << std::endl; break; case CO::BisonParser::token::H_BIF_PUFDATA: std::cout << H_BIF_PUFDATA_H << std::endl; break; case CO::BisonParser::token::H_BIF_AARCH32: std::cout << H_BIF_AARCH32_H << std::endl; break; case CO::BisonParser::token::H_BIF_BIGENDIAN: std::cout << H_BIF_BIGENDIAN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTCONFIG: std::cout << H_BIF_BOOTCONFIG_H << std::endl; break; case CO::BisonParser::token::H_BIF_COPY: std::cout << H_BIF_COPY_H << std::endl; break; case CO::BisonParser::token::H_BIF_CORE: std::cout << H_BIF_CORE_H << std::endl; break; case CO::BisonParser::token::H_BIF_DELAY_HANDOFF: std::cout << H_BIF_DELAY_HANDOFF_H << std::endl; break; case CO::BisonParser::token::H_BIF_DELAY_LOAD: std::cout << H_BIF_DELAY_LOAD_H << std::endl; break; case CO::BisonParser::token::H_BIF_FILE: std::cout << H_BIF_FILE_H << std::endl; break; case CO::BisonParser::token::H_BIF_ID: std::cout << H_BIF_ID_H << std::endl; break; case CO::BisonParser::token::H_BIF_IMAGE: std::cout << H_BIF_IMAGE_H << std::endl; break; case CO::BisonParser::token::H_BIF_METAHDR: std::cout << H_BIF_METAHDR_H << std::endl; break; case CO::BisonParser::token::H_BIF_NAME: std::cout << H_BIF_NAME_H << std::endl; break; case CO::BisonParser::token::H_BIF_PARENTID: std::cout << H_BIF_PARENTID_H << std::endl; break; case CO::BisonParser::token::H_BIF_PARTITION: std::cout << H_BIF_PARTITION_H << std::endl; break; case CO::BisonParser::token::H_BIF_SLR: std::cout << H_BIF_SLR_H << std::endl; break; case CO::BisonParser::token::H_BIF_TYPE: std::cout << H_BIF_TYPE_H << std::endl; break; case CO::BisonParser::token::H_BIF_KEYSRCENCR: std::cout << H_BIF_KEYSRCENCR_H << std::endl; break; case CO::BisonParser::token::H_DPACM_ENABLE: std::cout << H_DPACM_ENABLE_H << std::endl; break; case CO::BisonParser::token::H_BIF_USERKEYS: std::cout << H_BIF_USERKEYS_H << std::endl; break; case CO::BisonParser::token::HVN_BIF_PCR_MINDEX: std::cout << HVN_BIF_PCR_MINDEX_H << std::endl; break; case CO::BisonParser::token::HVN_BIF_PCR: std::cout << HVN_BIF_PCR_H << std::endl; break; case CO::BisonParser::token::HV_BIF_IMAGESTORE: std::cout << HV_BIF_IMAGESTORE_H << std::endl; break; case 0: std::cout << BIF_HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void CO::BisonParser::error(const CO::BisonParser::location_type &loc, const std::string &msg) { scanner.ReportError(loc, msg); } static int yylex(CO::BisonParser::semantic_type * yylval, CO::BisonParser::location_type* loc, CO::FlexScanner &scanner) { return scanner.yylex(yylval, loc); } xilinx-bootgen-2024.2/cmdoptions.tab.hpp000077500000000000000000000314341475706442400202330ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton interface for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file cmdoptions.tab.hpp ** Define the CO::parser class. */ /* C++ LALR(1) parser skeleton written by Akim Demaille. */ #ifndef YY_YY_CMDOPTIONS_TAB_HPP_INCLUDED # define YY_YY_CMDOPTIONS_TAB_HPP_INCLUDED /* "%code requires" blocks. */ /* Line 33 of lalr1.cc */ #line 34 "../../s/cmdoptions.y" namespace CO { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "help.h" #include "location.hh" /* Line 33 of lalr1.cc */ #line 59 "cmdoptions.tab.hpp" #include #include #include "stack.hh" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Line 33 of lalr1.cc */ #line 24 "../../s/cmdoptions.y" namespace CO { /* Line 33 of lalr1.cc */ #line 76 "cmdoptions.tab.hpp" /// A Bison parser. class BisonParser { public: /// Symbol semantic values. #ifndef YYSTYPE union semantic_type { /* Line 33 of lalr1.cc */ #line 64 "../../s/cmdoptions.y" uint64_t number; char* cstring; /* Line 33 of lalr1.cc */ #line 94 "cmdoptions.tab.hpp" }; #else typedef YYSTYPE semantic_type; #endif /// Symbol locations. typedef BIF::location location_type; /// Tokens. struct token { /* Tokens. */ enum yytokentype { _IMAGE = 258, _FILL = 259, _O_TOK = 260, I = 261, _H = 262, _DEBUG_TOK = 263, _LEGACY = 264, _NONBOOTING = 265, _PACKAGENAME = 266, _BIF_HELP = 267, _LOG = 268, ERROR = 269, WARNING = 270, INFO = 271, DEBUG = 272, TRACE = 273, _SPLIT = 274, _PROCESS_BITSTREAM = 275, MCS = 276, BIN = 277, _OUT_TYPE = 278, _DUMP = 279, DUMP_PLM = 280, DUMP_PMC_CDO = 281, DUMP_BOOT_FILES = 282, _DUMP_DIR = 283, DUMP_SLAVE_PDIS = 284, _ARCH = 285, ZYNQ = 286, ZYNQMP = 287, VERSAL = 288, _R = 289, FPGA = 290, VERSALNET = 291, _DUAL_QSPI_MODE = 292, _DUAL_OSPI_MODE = 293, PARALLEL = 294, STACKED = 295, _W = 296, ON = 297, OFF = 298, _NOAUTHBLOCKS = 299, _ZYNQMPES1 = 300, _OVERLAYCDO = 301, _EFUSEPPKBITS = 302, _GENERATE_HASHES = 303, _PADIMAGEHEADER = 304, _SPKSIGNATURE = 305, _GENERATE_KEYS = 306, PEM = 307, RSA = 308, ECDSAP521 = 309, AUTH = 310, GREY = 311, METAL = 312, _SECUREDEBUG = 313, ECDSA = 314, _AUTHJTAG = 315, _ENCRYPT = 316, BBRAM = 317, EFUSE = 318, _P_TOK = 319, _INTERFACE = 320, SMAPx8 = 321, SMAPx16 = 322, SMAPx32 = 323, SPI = 324, BPIx8 = 325, BPIx16 = 326, _READ = 327, READ_BH = 328, READ_IHT = 329, READ_IH = 330, READ_PHT = 331, READ_AC = 332, _VERIFY = 333, _VERIFYKDF = 334, _AUTH_OPTIMIZATION = 335, _ZYNQMPENCRDUMP = 336, HEXVALUE = 337, IDENTIFIER = 338, FILENAME = 339, QFILENAME = 340, HEXSTRING = 341, EQUALS = 342, HMAC = 343, STARTCBC = 344, KEY0 = 345, COMMA = 346, HBIFHELP = 347, HARCH = 348, HIMAGE = 349, HFILL = 350, HO = 351, HP = 352, HW = 353, HEFUSEPPKBITS = 354, HGENHASHES = 355, HLEGACY = 356, HPADHDR = 357, H_SPKSIGN = 358, HAUTHOPT = 359, HPACKAGE = 360, HENCRYPT = 361, HGENKEYS = 362, HDQSPI = 363, HLOG = 364, HZYNQMPES1 = 365, HPROCESSBIT = 366, HNONBOOTING = 367, HENCRDUMP = 368, HPOSTPROCESS = 369, HVERIFY = 370, HSECUREDEBUG = 371, HREAD = 372, HVERIFYKDF = 373, HDUMP = 374, HDUMPDIR = 375, HOVLCDO = 376, HOUTTYPE = 377, H_BIF_INIT = 378, H_BIF_UDFBH = 379, H_BIF_AES = 380, H_BIF_PPK = 381, H_BIF_PSK = 382, H_BIF_SPK = 383, H_BIF_SSK = 384, H_BIF_SPKSIGN = 385, H_BIF_HIVEC = 386, H_BIF_HDRSIGN = 387, H_BIF_BOOTIMAGE = 388, H_BIF_BL = 389, H_BIF_PID = 390, H_BIF_ENCR = 391, H_BIF_AUTH = 392, H_BIF_CHKSM = 393, H_BIF_ELYHNDOFF = 394, H_BIF_BHSIGN = 395, H_BIF_TCMBOOT = 396, H_BIF_OPTIONALDATA = 397, H_BIF_POWNER = 398, H_BIF_PRESIGN = 399, H_BIF_UDF = 400, H_BIF_XIP = 401, H_BIF_ALIGN = 402, H_BIF_OFFSET = 403, H_BIF_RES = 404, H_BIF_LOAD = 405, H_BIF_TZ = 406, H_BIF_STARTUP = 407, H_BIF_KEYSRC = 408, H_BIF_FSBLCFG = 409, H_BIF_BOOTDEV = 410, H_BIF_DESTCPU = 411, H_BIF_DESTDEV = 412, H_BIF_EL = 413, H_SPLIT = 414, H_BIF_AUTHPARAM = 415, H_BIF_BHKEY = 416, H_BIF_PFW = 417, H_BIF_BLOCKS = 418, H_BIF_METAL = 419, H_BIF_BHIV = 420, H_BIF_BOOTVEC = 421, H_BIF_PUFDATA = 422, H_BIF_PTYPE = 423, H_BIF_IMAGECFG = 424, H_BIF_PMCCONFIG = 425, H_BIF_AARCH32 = 426, H_BIF_BIGENDIAN = 427, H_BIF_BOOTCONFIG = 428, H_BIF_COPY = 429, H_BIF_CORE = 430, H_BIF_DELAY_HANDOFF = 431, H_BIF_DELAY_LOAD = 432, H_BIF_FILE = 433, H_BIF_ID = 434, H_BIF_IMAGE = 435, H_BIF_METAHDR = 436, H_BIF_NAME = 437, H_BIF_PARTITION = 438, H_BIF_SLR = 439, H_BIF_TYPE = 440, H_BIF_KEYSRCENCR = 441, H_BIF_PARENTID = 442, H_DPACM_ENABLE = 443, H_BIF_USERKEYS = 444, HVN_BIF_PCR = 445, HVN_BIF_PCR_MINDEX = 446, HV_BIF_IMAGESTORE = 447 }; }; /// Token type. typedef token::yytokentype token_type; /// Build a parser object. BisonParser (CO::FlexScanner& scanner_yyarg, Options& options_yyarg); virtual ~BisonParser (); /// Parse. /// \returns 0 iff parsing succeeded. virtual int parse (); #if YYDEBUG /// The current debugging stream. std::ostream& debug_stream () const; /// Set the current debugging stream. void set_debug_stream (std::ostream &); /// Type for debugging levels. typedef int debug_level_type; /// The current debugging level. debug_level_type debug_level () const; /// Set the current debugging level. void set_debug_level (debug_level_type l); #endif private: /// Report a syntax error. /// \param loc where the syntax error is found. /// \param msg a description of the syntax error. virtual void error (const location_type& loc, const std::string& msg); /// Generate an error message. /// \param state the state where the error occurred. /// \param tok the lookahead token. virtual std::string yysyntax_error_ (int yystate, int tok); #if YYDEBUG /// \brief Report a symbol value on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); /// \brief Report a symbol on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); #endif /// State numbers. typedef int state_type; /// State stack type. typedef BIF::stack state_stack_type; /// Semantic value stack type. typedef BIF::stack semantic_stack_type; /// location stack type. typedef BIF::stack location_stack_type; /// The state stack. state_stack_type yystate_stack_; /// The semantic value stack. semantic_stack_type yysemantic_stack_; /// The location stack. location_stack_type yylocation_stack_; /// Whether the given \c yypact_ value indicates a defaulted state. /// \param yyvalue the value to check static bool yy_pact_value_is_default_ (int yyvalue); /// Whether the given \c yytable_ value indicates a syntax error. /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); /// Internal symbol numbers. typedef unsigned char token_number_type; /* Tables. */ /// For a state, the index in \a yytable_ of its portion. static const short int yypact_[]; static const signed char yypact_ninf_; /// For a state, default reduction number. /// Unless\a yytable_ specifies something else to do. /// Zero means the default is an error. static const unsigned char yydefact_[]; static const signed char yypgoto_[]; static const short int yydefgoto_[]; /// What to do in a state. /// \a yytable_[yypact_[s]]: what to do in state \a s. /// - if positive, shift that token. /// - if negative, reduce the rule which number is the opposite. /// - if zero, do what YYDEFACT says. static const unsigned short int yytable_[]; static const signed char yytable_ninf_; static const short int yycheck_[]; /// For a state, its accessing symbol. static const unsigned char yystos_[]; /// For a rule, its LHS. static const unsigned char yyr1_[]; /// For a rule, its RHS length. static const unsigned char yyr2_[]; #if YYDEBUG /// For a symbol, its name in clear. static const char* const yytname_[]; /// A type to store symbol numbers and -1. typedef short int rhs_number_type; /// A `-1'-separated list of the rules' RHS. static const rhs_number_type yyrhs_[]; /// For each rule, the index of the first RHS symbol in \a yyrhs_. static const unsigned short int yyprhs_[]; /// For each rule, its source line number. static const unsigned short int yyrline_[]; /// For each scanner token number, its symbol number. static const unsigned short int yytoken_number_[]; /// Report on the debug stream that the rule \a r is going to be reduced. virtual void yy_reduce_print_ (int r); /// Print the state stack on the debug stream. virtual void yystack_print_ (); /* Debugging. */ int yydebug_; std::ostream* yycdebug_; #endif /// Convert a scanner token number \a t to a symbol number. token_number_type yytranslate_ (int t); /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// If null, do not display the symbol, just free it. /// \param yytype The symbol type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. inline void yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp); /// Pop \a n symbols the three stacks. inline void yypop_ (unsigned int n = 1); /* Constants. */ static const int yyeof_; /* LAST_ -- Last index in TABLE_. */ static const int yylast_; static const int yynnts_; static const int yyempty_; static const int yyfinal_; static const int yyterror_; static const int yyerrcode_; static const int yyntokens_; static const unsigned int yyuser_token_number_max_; static const token_number_type yyundef_token_; /* User arguments. */ CO::FlexScanner& scanner; Options& options; }; /* Line 33 of lalr1.cc */ #line 24 "../../s/cmdoptions.y" } // CO /* Line 33 of lalr1.cc */ #line 472 "cmdoptions.tab.hpp" #endif /* !YY_YY_CMDOPTIONS_TAB_HPP_INCLUDED */ xilinx-bootgen-2024.2/cmdoptions.y000077500000000000000000001140541475706442400171470ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* command line options grammar * Use bison to process this file into cmdoptions.tab.cpp */ %require "2.7" %skeleton "lalr1.cc" %defines %define namespace "CO" %define parser_class_name "BisonParser" %parse-param { CO::FlexScanner& scanner } %parse-param { Options& options} %lex-param { CO::FlexScanner& scanner } %locations %define api.location.type "BIF::location" %code requires { namespace CO { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "help.h" #include "location.hh" } %code { static int yylex(CO::BisonParser::semantic_type * yylval, CO::BisonParser::location_type* loc, CO::FlexScanner &scanner); } %{ #include #include #include "cmdoptionsscanner.h" #include "version.h" void ShowHelp(); void ShowCmdHelp(int); void ShowBifHelp(int); void ShowCommonHelp(int,bool); %} %start top %union { uint64_t number; char* cstring; } %token _IMAGE _FILL _O_TOK I _H _DEBUG_TOK _LEGACY _NONBOOTING _PACKAGENAME _BIF_HELP %token _LOG ERROR WARNING INFO DEBUG TRACE %token _SPLIT _PROCESS_BITSTREAM MCS BIN _OUT_TYPE %token _DUMP DUMP_PLM DUMP_PMC_CDO DUMP_BOOT_FILES _DUMP_DIR DUMP_SLAVE_PDIS %token _ARCH ZYNQ ZYNQMP VERSAL _R FPGA VERSALNET %token _DUAL_QSPI_MODE _DUAL_OSPI_MODE PARALLEL STACKED %token _W ON OFF %token _NOAUTHBLOCKS _ZYNQMPES1 _OVERLAYCDO %token _EFUSEPPKBITS _GENERATE_HASHES _PADIMAGEHEADER _SPKSIGNATURE _GENERATE_KEYS PEM RSA ECDSAP521 AUTH GREY METAL %token _SECUREDEBUG ECDSA _AUTHJTAG %token _ENCRYPT BBRAM EFUSE _P_TOK %token _INTERFACE SMAPx8 SMAPx16 SMAPx32 SPI BPIx8 BPIx16 %token _READ READ_BH READ_IHT READ_IH READ_PHT READ_AC %token _VERIFY _VERIFYKDF _AUTH_OPTIMIZATION %token _ZYNQMPENCRDUMP %token HEXVALUE %token IDENTIFIER FILENAME QFILENAME HEXSTRING %token EQUALS HMAC STARTCBC KEY0 COMMA %type number %type filename charstring %token HBIFHELP HARCH HIMAGE HFILL HO HP HW HEFUSEPPKBITS HGENHASHES HLEGACY HPADHDR H_SPKSIGN HAUTHOPT %token HPACKAGE HENCRYPT HGENKEYS HDQSPI HLOG HZYNQMPES1 HPROCESSBIT HNONBOOTING HENCRDUMP HPOSTPROCESS %token HVERIFY HSECUREDEBUG HREAD HVERIFYKDF HDUMP HDUMPDIR HOVLCDO HOUTTYPE %token H_BIF_INIT H_BIF_UDFBH H_BIF_AES H_BIF_PPK H_BIF_PSK H_BIF_SPK H_BIF_SSK H_BIF_SPKSIGN H_BIF_HIVEC %token H_BIF_HDRSIGN H_BIF_BOOTIMAGE H_BIF_BL H_BIF_PID H_BIF_ENCR H_BIF_AUTH H_BIF_CHKSM H_BIF_ELYHNDOFF H_BIF_BHSIGN H_BIF_TCMBOOT H_BIF_OPTIONALDATA %token H_BIF_POWNER H_BIF_PRESIGN H_BIF_UDF H_BIF_XIP H_BIF_ALIGN H_BIF_OFFSET H_BIF_RES H_BIF_LOAD H_BIF_TZ %token H_BIF_STARTUP H_BIF_KEYSRC H_BIF_FSBLCFG H_BIF_BOOTDEV H_BIF_DESTCPU H_BIF_DESTDEV H_BIF_EL H_SPLIT %token H_BIF_AUTHPARAM H_BIF_BHKEY H_BIF_PFW H_BIF_BLOCKS H_BIF_METAL H_BIF_BHIV H_BIF_BOOTVEC %token H_BIF_PUFDATA H_BIF_PTYPE H_BIF_IMAGECFG H_BIF_PMCCONFIG H_BIF_AARCH32 H_BIF_BIGENDIAN H_BIF_BOOTCONFIG H_BIF_COPY %token H_BIF_CORE H_BIF_DELAY_HANDOFF H_BIF_DELAY_LOAD H_BIF_FILE H_BIF_ID H_BIF_IMAGE H_BIF_METAHDR H_BIF_NAME H_BIF_PARTITION %token H_BIF_SLR H_BIF_TYPE H_BIF_KEYSRCENCR H_BIF_PARENTID H_DPACM_ENABLE H_BIF_USERKEYS HVN_BIF_PCR HVN_BIF_PCR_MINDEX HV_BIF_IMAGESTORE %% top : option_list; option_list : /* empty */ | option_list option ; option : _IMAGE filename { options.SetBifFilename($2); } | _SPLIT memsplit | filloption | _O_TOK I filename { options.GetOutputFileNames().push_back($3); } | _O_TOK filename { options.GetOutputFileNames().push_back($2); } /* superfluous i can be ommitted */ | _P_TOK IDENTIFIER { options.SetDevicePartName($2); } | _W wopt | _LOG loglevel | _H helpoption | _BIF_HELP bifhelpoption | _ENCRYPT keysource startcbc key0 hmac keyfile | _EFUSEPPKBITS filename { options.SetEfuseHashFileName($2); } | _GENERATE_HASHES { options.SetGenerateHashes(true); } | _NONBOOTING { options.SetNonBootingFlag(true); } | _LEGACY { options.SetLegacyFlag(true); } | _PADIMAGEHEADER { options.SetPadHeaderTable(true); } | _PADIMAGEHEADER EQUALS HEXSTRING { options.SetPadHeaderTable((bool)(strcmp($3,"0"))); } | _PADIMAGEHEADER HEXSTRING { options.SetPadHeaderTable((bool)(strcmp($2,"0"))); } | _PROCESS_BITSTREAM bitfile_type | _DUAL_QSPI_MODE qpsi_mode | _DUAL_OSPI_MODE opsi_mode | _SPKSIGNATURE filename { options.SetSpkSigFileName($2); } | _PACKAGENAME IDENTIFIER { options.SetDevicePackageName($2); } | _ARCH archOptions | _R { options.SetArchType(Arch::ZYNQMP); } | _NOAUTHBLOCKS { options.SetNoAuthBlocksFlag(true); } | _GENERATE_KEYS key_type | _DEBUG_TOK { LOG_ERROR("'-debug' option is no more supported. Please use '-log' option"); } | _ZYNQMPENCRDUMP encrDumpOptions | _ZYNQMPES1 { options.SetZynqmpes1Flag(true); } | _SECUREDEBUG auth_type { LOG_ERROR("The option '-securedebugimage' is deprecated. Use '-authenticatedjtag' instead."); } | _AUTHJTAG authJtagOptions | _READ readImageOptions | _VERIFY verifyImageOptions | _DUMP dumpOptions | _DUMP_DIR filename { options.SetDumpDirectory($2); } | _VERIFYKDF filename { options.SetKDFTestVectorFile($2); } | _AUTH_OPTIMIZATION { options.SetAuthOptimization();} | _OVERLAYCDO filename { options.SetOverlayCDOFileName($2); } | _OUT_TYPE outputType ; charstring : IDENTIFIER | HEXSTRING; filename : HEXSTRING | IDENTIFIER | FILENAME | QFILENAME; memsplit : MCS { options.SetSplitType(File::MCS); } | BIN { options.SetSplitType(File::BIN); } ; filloption : _FILL { options.SetDoFill(true); } | _FILL number { options.SetDoFill(true); if ($2 >= 0 && $2 <= 255) options.SetOutputFillByte((uint8_t)$2); else LOG_ERROR("'-fill' - Fill byte must be 8 bits"); } ; outputType : MCS { options.SetOutType(File::MCS); } | BIN { options.SetOutType(File::BIN); } ; helpoption : /* empty */ { ShowHelp(); exit(0); } | HBIFHELP { ShowCmdHelp(CO::BisonParser::token::HBIFHELP); exit(0); } | HARCH { ShowCmdHelp(CO::BisonParser::token::HARCH); exit(0); } | HAUTHOPT { ShowCmdHelp(CO::BisonParser::token::HAUTHOPT); exit(0); } | HIMAGE { ShowCmdHelp(CO::BisonParser::token::HIMAGE); exit(0); } | HFILL { ShowCmdHelp(CO::BisonParser::token::HFILL); exit(0); } | H_SPLIT { ShowCommonHelp(CO::BisonParser::token::H_SPLIT,true); exit(0); } | HO { ShowCmdHelp(CO::BisonParser::token::HO); exit(0); } | HP { ShowCmdHelp(CO::BisonParser::token::HP); exit(0); } | HW { ShowCmdHelp(CO::BisonParser::token::HW); exit(0); } | HEFUSEPPKBITS { ShowCmdHelp(CO::BisonParser::token::HEFUSEPPKBITS); exit(0); } | HGENHASHES { ShowCmdHelp(CO::BisonParser::token::HGENHASHES); exit(0); } | HLEGACY { ShowCmdHelp(CO::BisonParser::token::HLEGACY); exit(0); } | HPADHDR { ShowCmdHelp(CO::BisonParser::token::HPADHDR); exit(0); } | H_SPKSIGN { ShowCommonHelp(CO::BisonParser::token::H_SPKSIGN,true); exit(0); } | HPACKAGE { ShowCmdHelp(CO::BisonParser::token::HPACKAGE); exit(0); } | HENCRYPT { ShowCmdHelp(CO::BisonParser::token::HENCRYPT); exit(0); } | HGENKEYS { ShowCmdHelp(CO::BisonParser::token::HGENKEYS); exit(0); } | HDQSPI { ShowCmdHelp(CO::BisonParser::token::HDQSPI); exit(0); } | HLOG { ShowCmdHelp(CO::BisonParser::token::HLOG); exit(0); } | HZYNQMPES1 { ShowCmdHelp(CO::BisonParser::token::HZYNQMPES1); exit(0); } | HPROCESSBIT { ShowCmdHelp(CO::BisonParser::token::HPROCESSBIT); exit(0); } | HNONBOOTING { ShowCmdHelp(CO::BisonParser::token::HNONBOOTING); exit(0); } | HENCRDUMP { ShowCmdHelp(CO::BisonParser::token::HENCRDUMP); exit(0); } | HVERIFY { ShowCmdHelp(CO::BisonParser::token::HVERIFY); exit(0); } | HVERIFYKDF { ShowCmdHelp(CO::BisonParser::token::HVERIFYKDF); exit(0); } | HREAD { ShowCmdHelp(CO::BisonParser::token::HREAD); exit(0); } | HSECUREDEBUG { ShowCmdHelp(CO::BisonParser::token::HSECUREDEBUG); exit(0); } | HDUMP { ShowCmdHelp(CO::BisonParser::token::HDUMP); exit(0); } | HDUMPDIR { ShowCmdHelp(CO::BisonParser::token::HDUMPDIR); exit(0); } | HOVLCDO { ShowCmdHelp(CO::BisonParser::token::HOVLCDO); exit(0); } | HOUTTYPE { ShowCmdHelp(CO::BisonParser::token::HOUTTYPE); exit(0); } ; bifhelpoption : /* empty */ { ShowBifHelp(0); exit(0); } | H_BIF_INIT { ShowBifHelp(CO::BisonParser::token::H_BIF_INIT); exit(0); } | H_BIF_UDFBH { ShowBifHelp(CO::BisonParser::token::H_BIF_UDFBH); exit(0); } | H_BIF_AES { ShowBifHelp(CO::BisonParser::token::H_BIF_AES); exit(0); } | H_BIF_PPK { ShowBifHelp(CO::BisonParser::token::H_BIF_PPK); exit(0); } | H_BIF_PSK { ShowBifHelp(CO::BisonParser::token::H_BIF_PSK); exit(0); } | H_BIF_SPK { ShowBifHelp(CO::BisonParser::token::H_BIF_SPK); exit(0); } | H_BIF_SSK { ShowBifHelp(CO::BisonParser::token::H_BIF_SSK); exit(0); } | H_BIF_SPKSIGN { ShowBifHelp(CO::BisonParser::token::H_BIF_SPKSIGN); exit(0); } | H_BIF_HDRSIGN { ShowBifHelp(CO::BisonParser::token::H_BIF_HDRSIGN); exit(0); } | H_BIF_BOOTIMAGE { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTIMAGE); exit(0); } | H_BIF_BL { ShowBifHelp(CO::BisonParser::token::H_BIF_BL); exit(0); } | H_BIF_ENCR { ShowBifHelp(CO::BisonParser::token::H_BIF_ENCR); exit(0); } | H_BIF_PID { ShowBifHelp(CO::BisonParser::token::H_BIF_PID); exit(0); } | H_BIF_AUTH { ShowBifHelp(CO::BisonParser::token::H_BIF_AUTH); exit(0); } | H_BIF_TCMBOOT { ShowBifHelp(CO::BisonParser::token::H_BIF_TCMBOOT); exit(0); } | H_BIF_OPTIONALDATA { ShowBifHelp(CO::BisonParser::token::H_BIF_OPTIONALDATA); exit(0); } | H_BIF_CHKSM { ShowBifHelp(CO::BisonParser::token::H_BIF_CHKSM); exit(0); } | H_BIF_POWNER { ShowBifHelp(CO::BisonParser::token::H_BIF_POWNER); exit(0); } | H_BIF_PRESIGN { ShowBifHelp(CO::BisonParser::token::H_BIF_PRESIGN); exit(0); } | H_BIF_UDF { ShowBifHelp(CO::BisonParser::token::H_BIF_UDF); exit(0); } | H_BIF_XIP { ShowBifHelp(CO::BisonParser::token::H_BIF_XIP); exit(0); } | H_BIF_ALIGN { ShowBifHelp(CO::BisonParser::token::H_BIF_ALIGN); exit(0); } | H_BIF_OFFSET { ShowBifHelp(CO::BisonParser::token::H_BIF_OFFSET); exit(0); } | H_BIF_RES { ShowBifHelp(CO::BisonParser::token::H_BIF_RES); exit(0); } | H_BIF_LOAD { ShowBifHelp(CO::BisonParser::token::H_BIF_LOAD); exit(0); } | H_BIF_STARTUP { ShowBifHelp(CO::BisonParser::token::H_BIF_STARTUP); exit(0); } | H_BIF_KEYSRC { ShowBifHelp(CO::BisonParser::token::H_BIF_KEYSRC); exit(0); } | H_BIF_FSBLCFG { ShowBifHelp(CO::BisonParser::token::H_BIF_FSBLCFG); exit(0); } | H_BIF_BOOTDEV { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTDEV); exit(0); } | H_BIF_DESTCPU { ShowBifHelp(CO::BisonParser::token::H_BIF_DESTCPU); exit(0); } | H_BIF_DESTDEV { ShowBifHelp(CO::BisonParser::token::H_BIF_DESTDEV); exit(0); } | H_BIF_EL { ShowBifHelp(CO::BisonParser::token::H_BIF_EL); exit(0); } | H_BIF_TZ { ShowBifHelp(CO::BisonParser::token::H_BIF_TZ); exit(0); } | H_BIF_AUTHPARAM { ShowBifHelp(CO::BisonParser::token::H_BIF_AUTHPARAM); exit(0); } | H_BIF_BHKEY { ShowBifHelp(CO::BisonParser::token::H_BIF_BHKEY); exit(0); } | H_BIF_PFW { ShowBifHelp(CO::BisonParser::token::H_BIF_PFW); exit(0); } | H_BIF_BLOCKS { ShowBifHelp(CO::BisonParser::token::H_BIF_BLOCKS); exit(0); } | H_BIF_BHIV { ShowBifHelp(CO::BisonParser::token::H_BIF_BHIV); exit(0); } | H_BIF_METAL { ShowBifHelp(CO::BisonParser::token::H_BIF_METAL); exit(0); } | H_BIF_ELYHNDOFF { ShowBifHelp(CO::BisonParser::token::H_BIF_ELYHNDOFF); exit(0); } | H_BIF_HIVEC { ShowBifHelp(CO::BisonParser::token::H_BIF_HIVEC); exit(0); } | H_BIF_BHSIGN { ShowBifHelp(CO::BisonParser::token::H_BIF_BHSIGN); exit(0); } | H_SPLIT { ShowCommonHelp(CO::BisonParser::token::H_SPLIT,false); exit(0); } | H_SPKSIGN { ShowCommonHelp(CO::BisonParser::token::H_SPKSIGN,false); exit(0); } | H_BIF_BOOTVEC { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTVEC); exit(0); } | H_BIF_PUFDATA { ShowBifHelp(CO::BisonParser::token::H_BIF_PUFDATA); exit(0); } | H_BIF_AARCH32 { ShowBifHelp(CO::BisonParser::token::H_BIF_AARCH32); exit(0); } | H_BIF_BIGENDIAN { ShowBifHelp(CO::BisonParser::token::H_BIF_BIGENDIAN); exit(0); } | H_BIF_BOOTCONFIG { ShowBifHelp(CO::BisonParser::token::H_BIF_BOOTCONFIG); exit(0); } | H_BIF_COPY { ShowBifHelp(CO::BisonParser::token::H_BIF_COPY); exit(0); } | H_BIF_CORE { ShowBifHelp(CO::BisonParser::token::H_BIF_CORE); exit(0); } | H_BIF_DELAY_HANDOFF { ShowBifHelp(CO::BisonParser::token::H_BIF_DELAY_HANDOFF); exit(0); } | H_BIF_DELAY_LOAD { ShowBifHelp(CO::BisonParser::token::H_BIF_DELAY_LOAD); exit(0); } | H_BIF_FILE { ShowBifHelp(CO::BisonParser::token::H_BIF_FILE); exit(0); } | H_BIF_ID { ShowBifHelp(CO::BisonParser::token::H_BIF_ID); exit(0); } | H_BIF_IMAGE { ShowBifHelp(CO::BisonParser::token::H_BIF_IMAGE); exit(0); } | H_BIF_METAHDR { ShowBifHelp(CO::BisonParser::token::H_BIF_METAHDR); exit(0); } | H_BIF_NAME { ShowBifHelp(CO::BisonParser::token::H_BIF_NAME); exit(0); } | H_BIF_PARENTID { ShowBifHelp(CO::BisonParser::token::H_BIF_PARENTID); exit(0); } | H_BIF_PARTITION { ShowBifHelp(CO::BisonParser::token::H_BIF_PARTITION); exit(0); } | H_BIF_SLR { ShowBifHelp(CO::BisonParser::token::H_BIF_SLR); exit(0); } | H_BIF_TYPE { ShowBifHelp(CO::BisonParser::token::H_BIF_TYPE); exit(0); } | H_BIF_KEYSRCENCR { ShowBifHelp(CO::BisonParser::token::H_BIF_KEYSRCENCR); exit(0); } | H_DPACM_ENABLE { ShowBifHelp(CO::BisonParser::token::H_DPACM_ENABLE); exit(0); } | H_BIF_USERKEYS { ShowBifHelp(CO::BisonParser::token::H_BIF_USERKEYS); exit(0); } | HVN_BIF_PCR { ShowBifHelp(CO::BisonParser::token::HVN_BIF_PCR); exit(0); } | HVN_BIF_PCR_MINDEX { ShowBifHelp(CO::BisonParser::token::HVN_BIF_PCR_MINDEX); exit(0); } | HV_BIF_IMAGESTORE { ShowBifHelp(CO::BisonParser::token::HV_BIF_IMAGESTORE); exit(0); } ; wopt : /* empty*/ { options.SetOverwrite(true); } | ON { options.SetOverwrite(true); } | OFF { options.SetOverwrite(false); } ; loglevel : /* empty */ | ERROR { options.SetLogLevel(LogLevel::ERROR); } | WARNING { options.SetLogLevel(LogLevel::WARNING); } | INFO { options.SetLogLevel(LogLevel::INFO); } | DEBUG { options.SetLogLevel(LogLevel::DEBUG); } | TRACE { options.SetLogLevel(LogLevel::TRACE); } ; keysource : BBRAM { options.SetEncryptedKeySource(KeySource::BbramRedKey); } | EFUSE { options.SetEncryptedKeySource(KeySource::EfuseRedKey); } ; startcbc : /* empty*/ | STARTCBC EQUALS HEXSTRING { options.SetStartCbc($3);}; key0 : /* empty*/ | KEY0 EQUALS HEXSTRING { options.SetKey0($3);}; hmac : /* empty*/ | HMAC EQUALS HEXSTRING { options.SetHmac($3);}; keyfile : /* empty*/ | filename { options.SetEncryptionKeyFile($1);}; number : HEXVALUE; bitfile_type : MCS { options.SetProcessBitstreamType(File::MCS); } | BIN { options.SetProcessBitstreamType(File::BIN); } ; qpsi_mode : PARALLEL { options.SetDualQspiMode(QspiMode::PARALLEL_LQSPI); } | STACKED qspi_size { options.SetDualQspiMode(QspiMode::STACKED); } ; opsi_mode : PARALLEL { LOG_ERROR("'parallel' option is not supported with '-dual_ospi_mode'."); } | STACKED ospi_size { options.SetDualQspiMode(QspiMode::STACKED); } ; qspi_size : HEXVALUE { options.SetQspiSize((uint16_t)$1); } | HEXSTRING { options.SetQspiSize((uint16_t)atoi($1)); } ; ospi_size : HEXVALUE { options.SetOspiSize((uint16_t)$1); } | HEXSTRING { options.SetOspiSize((uint16_t)atoi($1)); } ; archOptions : ZYNQ { options.SetArchType(Arch::ZYNQ); } | ZYNQMP { options.SetArchType(Arch::ZYNQMP); } | VERSAL { options.SetArchType(Arch::VERSAL); } | FPGA { options.SetArchType(Arch::FPGA); } | VERSALNET { options.SetArchType(Arch::VERSALNET); } ; key_type : AUTH auth_key_options | GREY { options.SetGreyKeyGeneration(true); } | METAL { options.SetMetalKeyGeneration(true); } | PEM { options.SetAuthKeyGeneration(GenAuthKeys::PEM); } | RSA { options.SetAuthKeyGeneration(GenAuthKeys::RSA); } | ECDSA { options.SetAuthKeyGeneration(GenAuthKeys::ECDSA); } | ECDSAP521 { options.SetAuthKeyGeneration(GenAuthKeys::ECDSAP521); } ; auth_key_options: PEM { options.SetAuthKeyGeneration(GenAuthKeys::PEM); } | RSA { options.SetAuthKeyGeneration(GenAuthKeys::RSA); } ; auth_type : ECDSA { options.SetSecureDebugAuthType(Authentication::ECDSA); options.SetSecureDebugImageFile("secureDebugImage-ecdsa.bin"); } | RSA { options.SetSecureDebugAuthType(Authentication::RSA); options.SetSecureDebugImageFile("secureDebugImage-rsa.bin"); } authJtagOptions : authJtagType filename { options.SetSecureDebugImageFile($2); } | authJtagType authJtagType : ECDSA { options.SetSecureDebugAuthType(Authentication::ECDSA); options.SetSecureDebugImageFile("authenticatedJtagImage-ecdsa.bin"); } | RSA { options.SetSecureDebugAuthType(Authentication::RSA); options.SetSecureDebugImageFile("authenticatedJtagImage-rsa.bin"); } verifyImageOptions: filename { options.SetReadImageFile($1); options.SetVerifyImageOption(true); } readImageOptions: filename { options.SetReadImageFile($1); options.SetReadImageOption(ReadImageOption::ALL); } | filename readType { options.SetReadImageFile($1); } readType : READ_BH { options.SetReadImageOption(ReadImageOption::BH); } | READ_IHT { options.SetReadImageOption(ReadImageOption::IHT); } | READ_IH { options.SetReadImageOption(ReadImageOption::IH); } | READ_PHT { options.SetReadImageOption(ReadImageOption::PHT); } | READ_AC { options.SetReadImageOption(ReadImageOption::AC); } ; dumpOptions : READ_BH { options.SetDumpOption(DumpOption::BH); } | filename READ_BH { options.SetReadImageFile($1); options.SetDumpOption(DumpOption::BH); } | READ_BH filename { options.SetReadImageFile($2); options.SetDumpOption(DumpOption::BH); } | filename { options.SetReadImageFile($1); options.SetDumpOption(DumpOption::PARTITIONS); } | filename DUMP_PLM { options.SetReadImageFile($1); options.SetDumpOption(DumpOption::PLM); } | filename DUMP_PMC_CDO { options.SetReadImageFile($1); options.SetDumpOption(DumpOption::PMC_CDO); } | filename DUMP_BOOT_FILES { options.SetReadImageFile($1); options.SetDumpOption(DumpOption::BOOT_FILES); } | DUMP_SLAVE_PDIS { options.SetDumpOption(DumpOption::SLAVE_PDIS); } ; encrDumpOptions : /* empty */ { options.SetEncryptionDump(true,"aes_log.txt"); } | filename { options.SetEncryptionDump(true,$1); } %% // int outputByteWidth; // Binary::Address_t baseAddress; // uint32_t defaultAlignment; void ShowHelp() { std::cout << HELP << std::endl; } void ShowCommonHelp(int a, bool cmdhelp) { switch(a) { case CO::BisonParser::token::H_SPLIT: if(cmdhelp) std::cout << SPLITHELP << std::endl; else std::cout << H_BIF_SPLIT_H << std::endl; break; case CO::BisonParser::token::H_SPKSIGN: if(cmdhelp) std::cout << SPKSIGNHELP << std::endl; else std::cout << H_BIF_SPKSIGN_H << std::endl; break; case 0: std::cout << HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void ShowCmdHelp(int a) { switch (a) { case CO::BisonParser::token::HARCH: std::cout << ARCHHELP << std::endl; break; case CO::BisonParser::token::HAUTHOPT: std::cout << ENABLEAUTHOPTHELP << std::endl; break; case CO::BisonParser::token::HIMAGE: std::cout << IMAGEHELP << std::endl; break; case CO::BisonParser::token::HFILL: std::cout << FILLHELP << std::endl; break; case CO::BisonParser::token::HO: std::cout << OHELP << std::endl; break; case CO::BisonParser::token::HP: std::cout << PHELP << std::endl; break; case CO::BisonParser::token::HW: std::cout << WHELP << std::endl; break; case CO::BisonParser::token::HEFUSEPPKBITS: std::cout << EFUSEPPKBITSHELP << std::endl; break; case CO::BisonParser::token::HZYNQMPES1: std::cout << ZYNQMPES1HELP << std::endl; break; case CO::BisonParser::token::HGENHASHES: std::cout << GENERATEHASHESHELP << std::endl; break; case CO::BisonParser::token::HPADHDR: std::cout << PADHDRHELP << std::endl; break; case CO::BisonParser::token::HENCRYPT: std::cout << ENCRYPTHELP << std::endl; break; case CO::BisonParser::token::HGENKEYS: std::cout << GENKEYSHELP << std::endl; break; case CO::BisonParser::token::HDQSPI: std::cout << DQSPIHELP << std::endl; break; case CO::BisonParser::token::HLOG: std::cout << LOGHELP << std::endl; break; case CO::BisonParser::token::HBIFHELP: std::cout << BIFHELP << std::endl; break; case CO::BisonParser::token::HPROCESSBIT: std::cout << PROCESSBITHELP << std::endl; break; case CO::BisonParser::token::HNONBOOTING: std::cout << NONBOOTINGHELP << std::endl; break; case CO::BisonParser::token::HENCRDUMP: std::cout << ENCRDUMPHELP << std::endl; break; case CO::BisonParser::token::HVERIFY: std::cout << VERIFYHELP << std::endl; break; case CO::BisonParser::token::HPOSTPROCESS: std::cout << POSTPROCESSHELP << std::endl; break; case CO::BisonParser::token::HVERIFYKDF: std::cout << VERIFYKDFHELP << std::endl; break; case CO::BisonParser::token::HREAD: std::cout << READHELP << std::endl; break; case CO::BisonParser::token::HSECUREDEBUG: std::cout << SECUREDEBUGHELP << std::endl; break; case CO::BisonParser::token::HDUMP: std::cout << DUMPHELP << std::endl; break; case CO::BisonParser::token::HDUMPDIR: std::cout << DUMPDIRHELP << std::endl; break; case CO::BisonParser::token::HOVLCDO: std::cout << OVERLAYCDO << std::endl; break; case CO::BisonParser::token::HOUTTYPE: std::cout << OUTTYPEHELP << std::endl; break; case 0: std::cout << HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void ShowBifHelp(int a) { switch (a) { case CO::BisonParser::token::H_BIF_INIT: std::cout << H_BIF_INIT_H << std::endl; break; case CO::BisonParser::token::H_BIF_UDFBH: std::cout << H_BIF_UDFBH_H << std::endl; break; case CO::BisonParser::token::H_BIF_AES: std::cout << H_BIF_AES_H << std::endl; break; case CO::BisonParser::token::H_BIF_PPK: case CO::BisonParser::token::H_BIF_PSK: case CO::BisonParser::token::H_BIF_SPK: case CO::BisonParser::token::H_BIF_SSK: std::cout << H_BIF_PPK_H << std::endl; break; case CO::BisonParser::token::H_BIF_SPKSIGN: std::cout << H_BIF_SPKSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_HDRSIGN: std::cout << H_BIF_HDRSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTIMAGE: std::cout << H_BIF_BOOTIMAGE_H << std::endl; break; case CO::BisonParser::token::H_BIF_BL: std::cout << H_BIF_BL_H << std::endl; break; case CO::BisonParser::token::H_BIF_ENCR: std::cout << H_BIF_ENCR_H << std::endl; break; case CO::BisonParser::token::H_BIF_PID: std::cout << H_BIF_PID_H << std::endl; break; case CO::BisonParser::token::H_BIF_AUTH: std::cout << H_BIF_AUTH_H << std::endl; break; case CO::BisonParser::token::H_BIF_TCMBOOT: std::cout << H_BIF_TCMBOOT_H << std::endl; break; case CO::BisonParser::token::H_BIF_OPTIONALDATA: std::cout << H_BIF_OPTIONALDATA_H << std::endl; break; case CO::BisonParser::token::H_BIF_CHKSM: std::cout << H_BIF_CHKSM_H << std::endl; break; case CO::BisonParser::token::H_BIF_POWNER: std::cout << H_BIF_POWNER_H << std::endl; break; case CO::BisonParser::token::H_BIF_PRESIGN: std::cout << H_BIF_PRESIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_UDF: std::cout << H_BIF_UDF_H << std::endl; break; case CO::BisonParser::token::H_BIF_XIP: std::cout << H_BIF_XIP_H << std::endl; break; case CO::BisonParser::token::H_BIF_ALIGN: std::cout << H_BIF_ALIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_OFFSET: std::cout << H_BIF_OFFSET_H << std::endl; break; case CO::BisonParser::token::H_BIF_RES: std::cout << H_BIF_RES_H << std::endl; break; case CO::BisonParser::token::H_BIF_LOAD: std::cout << H_BIF_LOAD_H << std::endl; break; case CO::BisonParser::token::H_BIF_STARTUP: std::cout << H_BIF_STARTUP_H << std::endl; break; case CO::BisonParser::token::H_BIF_KEYSRC: std::cout << H_BIF_KEYSRC_H << std::endl; break; case CO::BisonParser::token::H_BIF_FSBLCFG: std::cout << H_BIF_FSBLCFG_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTDEV: std::cout << H_BIF_BOOTDEV_H << std::endl; break; case CO::BisonParser::token::H_BIF_DESTCPU: std::cout << H_BIF_DESTCPU_H << std::endl; break; case CO::BisonParser::token::H_BIF_DESTDEV: std::cout << H_BIF_DESTDEV_H << std::endl; break; case CO::BisonParser::token::H_BIF_EL: std::cout << H_BIF_EL_H << std::endl; break; case CO::BisonParser::token::H_BIF_TZ: std::cout << H_BIF_TZ_H << std::endl; break; case CO::BisonParser::token::H_BIF_AUTHPARAM: std::cout << H_BIF_AUTHPARAM_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHKEY: std::cout << H_BIF_BHKEY_H << std::endl; break; case CO::BisonParser::token::H_BIF_PFW: std::cout << H_BIF_PFW_H << std::endl; break; case CO::BisonParser::token::H_BIF_BLOCKS: std::cout << H_BIF_BLOCKS_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHIV: std::cout << H_BIF_BHIV_H << std::endl; break; case CO::BisonParser::token::H_BIF_METAL: std::cout << H_BIF_METAL_H << std::endl; break; case CO::BisonParser::token::H_BIF_ELYHNDOFF: std::cout << H_BIF_ELYHNDOFF_H << std::endl; break; case CO::BisonParser::token::H_BIF_HIVEC: std::cout << H_BIF_HIVEC_H << std::endl; break; case CO::BisonParser::token::H_BIF_BHSIGN: std::cout << H_BIF_BHSIGN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTVEC: std::cout << H_BIF_BOOTVEC_H << std::endl; break; case CO::BisonParser::token::H_BIF_PUFDATA: std::cout << H_BIF_PUFDATA_H << std::endl; break; case CO::BisonParser::token::H_BIF_AARCH32: std::cout << H_BIF_AARCH32_H << std::endl; break; case CO::BisonParser::token::H_BIF_BIGENDIAN: std::cout << H_BIF_BIGENDIAN_H << std::endl; break; case CO::BisonParser::token::H_BIF_BOOTCONFIG: std::cout << H_BIF_BOOTCONFIG_H << std::endl; break; case CO::BisonParser::token::H_BIF_COPY: std::cout << H_BIF_COPY_H << std::endl; break; case CO::BisonParser::token::H_BIF_CORE: std::cout << H_BIF_CORE_H << std::endl; break; case CO::BisonParser::token::H_BIF_DELAY_HANDOFF: std::cout << H_BIF_DELAY_HANDOFF_H << std::endl; break; case CO::BisonParser::token::H_BIF_DELAY_LOAD: std::cout << H_BIF_DELAY_LOAD_H << std::endl; break; case CO::BisonParser::token::H_BIF_FILE: std::cout << H_BIF_FILE_H << std::endl; break; case CO::BisonParser::token::H_BIF_ID: std::cout << H_BIF_ID_H << std::endl; break; case CO::BisonParser::token::H_BIF_IMAGE: std::cout << H_BIF_IMAGE_H << std::endl; break; case CO::BisonParser::token::H_BIF_METAHDR: std::cout << H_BIF_METAHDR_H << std::endl; break; case CO::BisonParser::token::H_BIF_NAME: std::cout << H_BIF_NAME_H << std::endl; break; case CO::BisonParser::token::H_BIF_PARENTID: std::cout << H_BIF_PARENTID_H << std::endl; break; case CO::BisonParser::token::H_BIF_PARTITION: std::cout << H_BIF_PARTITION_H << std::endl; break; case CO::BisonParser::token::H_BIF_SLR: std::cout << H_BIF_SLR_H << std::endl; break; case CO::BisonParser::token::H_BIF_TYPE: std::cout << H_BIF_TYPE_H << std::endl; break; case CO::BisonParser::token::H_BIF_KEYSRCENCR: std::cout << H_BIF_KEYSRCENCR_H << std::endl; break; case CO::BisonParser::token::H_DPACM_ENABLE: std::cout << H_DPACM_ENABLE_H << std::endl; break; case CO::BisonParser::token::H_BIF_USERKEYS: std::cout << H_BIF_USERKEYS_H << std::endl; break; case CO::BisonParser::token::HVN_BIF_PCR_MINDEX: std::cout << HVN_BIF_PCR_MINDEX_H << std::endl; break; case CO::BisonParser::token::HVN_BIF_PCR: std::cout << HVN_BIF_PCR_H << std::endl; break; case CO::BisonParser::token::HV_BIF_IMAGESTORE: std::cout << HV_BIF_IMAGESTORE_H << std::endl; break; case 0: std::cout << BIF_HELP << std::endl; break; default: LOG_ERROR("Unsupported Option"); break; } } void CO::BisonParser::error(const CO::BisonParser::location_type &loc, const std::string &msg) { scanner.ReportError(loc, msg); } static int yylex(CO::BisonParser::semantic_type * yylval, CO::BisonParser::location_type* loc, CO::FlexScanner &scanner) { return scanner.yylex(yylval, loc); } xilinx-bootgen-2024.2/cmdoptions.yy.cpp000077500000000000000000003133641475706442400201260ustar00rootroot00000000000000#line 2 "../bisonflex/cmdoptions.yy.cpp" #line 4 "../bisonflex/cmdoptions.yy.cpp" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ /* %not-for-header */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ /* %ok-for-header */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* %if-c++-only */ /* The c++ scanner is a mess. The FlexLexer.h header file relies on the * following macro. This is required in order to pass the c++-multiple-scanners * test in the regression suite. We get reports that it breaks inheritance. * We will address this in a future release of flex, or omit the C++ scanner * altogether. */ #define yyFlexLexer cmdoptionsFlexLexer /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ /* %if-c-only */ /* %endif */ /* %if-tables-serialization */ /* %endif */ /* end standard C headers. */ /* %if-c-or-c++ */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ /* %endif */ /* %if-c++-only */ /* begin standard C++ headers. */ #include #include #include #include /* end standard C++ headers. */ /* %endif */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* %not-for-header */ /* Returned upon end-of-file. */ #define YY_NULL 0 /* %ok-for-header */ /* %not-for-header */ /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* %ok-for-header */ /* %if-reentrant */ /* %endif */ /* %if-not-reentrant */ /* %endif */ /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif /* %if-not-reentrant */ extern int yyleng; /* %endif */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { /* %if-c-only */ /* %endif */ /* %if-c++-only */ std::istream* yy_input_file; /* %endif */ char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %if-not-reentrant */ /* %endif */ /* %ok-for-header */ /* %endif */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* %if-c-only Standard (non-C++) definition */ /* %if-not-reentrant */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ /* %endif */ void *cmdoptionsalloc (yy_size_t ); void *cmdoptionsrealloc (void *,yy_size_t ); void cmdoptionsfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ /* Begin user sect3 */ #define YY_SKIP_YYWRAP #define FLEX_DEBUG typedef unsigned char YY_CHAR; #define yytext_ptr yytext #include "FlexLexer.h" int yyFlexLexer::yywrap() { return 1; } int yyFlexLexer::yylex() { LexerError( "yyFlexLexer::yylex invoked but %option yyclass used" ); return 0; } #define YY_DECL int FlexScanner::yylex() /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ #define YY_NUM_RULES 192 #define YY_END_OF_BUFFER 193 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[1094] = { 0, 0, 0, 193, 191, 189, 190, 187, 191, 37, 186, 186, 187, 185, 185, 36, 185, 186, 186, 186, 186, 185, 185, 185, 185, 185, 185, 186, 186, 7, 186, 186, 186, 186, 91, 92, 186, 186, 186, 186, 186, 93, 186, 186, 189, 190, 187, 0, 0, 186, 186, 186, 186, 186, 186, 186, 186, 84, 186, 186, 186, 6, 8, 69, 186, 186, 9, 186, 1, 187, 185, 186, 0, 186, 186, 186, 185, 75, 185, 186, 186, 186, 185, 71, 186, 186, 186, 186, 186, 185, 186, 186, 185, 185, 185, 186, 186, 186, 185, 186, 186, 186, 186, 186, 186, 186, 125, 73, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 10, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 188, 0, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 0, 2, 187, 3, 0, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 31, 186, 186, 186, 186, 186, 185, 186, 186, 186, 186, 186, 186, 185, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 72, 186, 186, 186, 186, 186, 186, 103, 30, 186, 186, 186, 186, 11, 186, 186, 186, 186, 186, 186, 186, 182, 53, 74, 146, 40, 186, 186, 186, 186, 186, 186, 186, 186, 186, 54, 186, 186, 131, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 0, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 12, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 22, 26, 186, 186, 186, 186, 87, 52, 186, 186, 186, 186, 186, 186, 186, 186, 120, 121, 186, 186, 186, 186, 186, 113, 186, 186, 186, 186, 186, 186, 186, 186, 124, 90, 67, 186, 186, 186, 186, 23, 186, 15, 134, 27, 186, 186, 159, 186, 128, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 112, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 132, 186, 186, 186, 186, 186, 186, 64, 63, 186, 186, 186, 186, 39, 186, 186, 186, 5, 186, 85, 186, 186, 186, 186, 186, 186, 186, 186, 186, 70, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 20, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 16, 186, 186, 186, 186, 186, 186, 57, 21, 186, 186, 13, 186, 186, 186, 186, 186, 175, 89, 186, 186, 186, 186, 186, 186, 186, 186, 186, 151, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 177, 186, 186, 186, 186, 17, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 38, 186, 186, 186, 186, 186, 186, 4, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 28, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 171, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 133, 96, 186, 186, 186, 157, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 135, 186, 186, 108, 66, 186, 186, 65, 186, 186, 186, 186, 186, 186, 186, 186, 186, 45, 186, 186, 186, 186, 186, 186, 186, 186, 186, 78, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 100, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 41, 186, 137, 153, 186, 138, 186, 158, 186, 186, 139, 186, 140, 35, 186, 160, 148, 186, 186, 186, 186, 186, 14, 186, 186, 186, 186, 186, 186, 186, 186, 186, 19, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 24, 186, 186, 186, 186, 186, 186, 186, 186, 86, 186, 186, 186, 186, 186, 186, 186, 150, 186, 186, 186, 186, 186, 114, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 116, 186, 186, 186, 34, 186, 186, 186, 186, 186, 179, 186, 186, 186, 25, 186, 154, 181, 186, 186, 155, 186, 186, 18, 186, 186, 44, 186, 186, 186, 186, 186, 186, 83, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 156, 186, 186, 172, 186, 186, 186, 186, 186, 186, 143, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 56, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 130, 129, 186, 186, 186, 186, 186, 186, 167, 186, 68, 104, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 81, 186, 136, 186, 186, 169, 186, 118, 186, 186, 42, 144, 186, 186, 123, 186, 186, 186, 186, 58, 59, 186, 186, 145, 186, 186, 186, 186, 186, 184, 186, 127, 106, 186, 186, 186, 186, 186, 186, 183, 186, 186, 186, 43, 186, 109, 186, 186, 186, 186, 186, 186, 186, 186, 186, 60, 186, 186, 186, 186, 186, 186, 77, 186, 168, 186, 176, 119, 163, 178, 186, 186, 186, 186, 186, 186, 186, 186, 186, 162, 186, 186, 186, 186, 186, 186, 115, 99, 186, 186, 170, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 82, 62, 186, 186, 186, 186, 117, 186, 186, 186, 186, 180, 186, 186, 94, 186, 186, 186, 186, 186, 186, 186, 186, 149, 186, 186, 186, 186, 98, 186, 186, 186, 47, 186, 186, 186, 186, 80, 186, 186, 186, 61, 186, 186, 122, 186, 186, 186, 174, 186, 186, 186, 186, 101, 186, 186, 55, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 51, 186, 186, 186, 186, 147, 186, 186, 102, 186, 186, 186, 186, 186, 186, 97, 186, 186, 186, 186, 33, 32, 186, 186, 186, 46, 186, 186, 186, 164, 186, 88, 107, 166, 95, 142, 186, 152, 186, 186, 186, 76, 79, 48, 186, 186, 186, 186, 186, 186, 110, 186, 186, 49, 111, 186, 161, 105, 50, 29, 165, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 5, 5, 5, 5, 1, 5, 5, 7, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 18, 20, 1, 1, 21, 1, 1, 5, 22, 23, 24, 25, 25, 25, 26, 27, 26, 26, 28, 26, 29, 26, 26, 26, 26, 26, 30, 26, 26, 26, 26, 31, 26, 26, 1, 32, 1, 5, 33, 1, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[60] = { 0, 1, 1, 1, 2, 3, 4, 1, 5, 6, 6, 3, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 } ; static yyconst flex_int16_t yy_base[1100] = { 0, 0, 0, 1318, 1319, 58, 1314, 0, 59, 0, 88, 114, 54, 162, 51, 1319, 137, 1296, 59, 46, 130, 200, 182, 184, 172, 213, 235, 47, 170, 226, 144, 202, 169, 61, 239, 276, 223, 271, 283, 228, 168, 60, 248, 151, 85, 1312, 0, 1308, 152, 0, 0, 32, 1271, 157, 232, 1270, 1273, 1272, 1263, 180, 1260, 227, 249, 1269, 204, 1268, 0, 1247, 1319, 341, 245, 351, 203, 1282, 1245, 1268, 254, 258, 298, 1259, 1264, 1246, 275, 204, 299, 1250, 1249, 1258, 248, 346, 1261, 267, 300, 321, 302, 301, 1243, 1257, 348, 1247, 1251, 1255, 1242, 1254, 1232, 1252, 0, 1232, 1250, 265, 1225, 1242, 320, 1229, 1227, 1233, 1231, 1238, 1237, 0, 1222, 1221, 1235, 1225, 346, 1220, 1224, 1216, 1231, 1221, 317, 1222, 260, 1221, 1225, 350, 1229, 1226, 358, 351, 1217, 1226, 1213, 346, 1209, 1218, 1218, 1204, 1203, 1204, 1205, 1319, 361, 1215, 1197, 1210, 1213, 365, 1193, 370, 1201, 1198, 1199, 1209, 1202, 1201, 367, 1187, 1201, 371, 1190, 1203, 1200, 368, 1184, 1187, 1230, 1319, 414, 0, 0, 1208, 1219, 1179, 1193, 1184, 1187, 1185, 1184, 1190, 1179, 1180, 1188, 1187, 0, 1183, 1165, 1181, 1158, 1177, 379, 1180, 1160, 1176, 1166, 1161, 1164, 388, 1156, 1172, 1155, 1157, 1166, 1161, 122, 1168, 1156, 1162, 1162, 1160, 1161, 0, 1156, 1147, 1141, 411, 1159, 1155, 0, 0, 1157, 1152, 1154, 1134, 1135, 1144, 1152, 1133, 1145, 1138, 1139, 390, 1147, 0, 0, 0, 0, 1146, 1139, 1138, 1124, 1139, 1135, 1140, 1135, 1133, 0, 1116, 1114, 0, 386, 1126, 1128, 390, 1131, 1129, 1112, 1125, 1129, 1110, 385, 1113, 1126, 1108, 1151, 1115, 1114, 1121, 1099, 1107, 1102, 1098, 1114, 1097, 1102, 1108, 1096, 1104, 1109, 0, 1088, 1106, 1107, 1088, 1094, 1095, 1100, 1098, 1080, 1081, 1090, 1089, 1080, 0, 0, 1076, 1087, 1089, 1079, 0, 406, 1079, 1086, 1083, 1081, 1083, 1076, 409, 1075, 0, 0, 1078, 1059, 1074, 1069, 1081, 1080, 1054, 1077, 1072, 1064, 1050, 1056, 1057, 1060, 0, 0, 0, 1071, 1052, 1064, 1065, 0, 1062, 0, 0, 0, 1048, 1062, 0, 1056, 0, 1048, 1043, 1056, 1045, 1039, 1046, 1039, 1055, 1042, 1042, 1039, 1043, 1038, 1047, 1026, 1039, 1038, 1041, 1036, 1038, 0, 1025, 1024, 1036, 1031, 1030, 1018, 1028, 1025, 1015, 1019, 1028, 1012, 0, 394, 1020, 1024, 1028, 1019, 1014, 1013, 0, 1020, 1016, 1016, 1022, 1021, 1015, 1007, 993, 0, 999, 0, 1011, 1012, 994, 998, 992, 999, 1009, 996, 1003, 0, 989, 997, 985, 998, 990, 1011, 1019, 975, 986, 982, 983, 0, 971, 981, 989, 979, 973, 410, 978, 975, 984, 969, 0, 987, 972, 985, 967, 979, 982, 1005, 964, 974, 962, 0, 957, 951, 972, 973, 955, 0, 953, 968, 945, 964, 953, 964, 946, 951, 939, 962, 0, 955, 960, 948, 939, 938, 948, 952, 955, 942, 946, 933, 939, 941, 927, 943, 947, 934, 938, 0, 932, 938, 394, 927, 0, 915, 932, 938, 933, 912, 924, 921, 919, 917, 918, 926, 0, 402, 926, 913, 923, 911, 925, 0, 900, 916, 908, 897, 920, 913, 918, 899, 912, 909, 0, 890, 898, 923, 931, 905, 905, 908, 888, 420, 906, 894, 901, 0, 889, 898, 893, 900, 899, 896, 877, 217, 896, 891, 876, 885, 885, 876, 875, 890, 869, 879, 876, 871, 865, 865, 863, 882, 0, 880, 860, 878, 0, 877, 861, 851, 870, 867, 868, 872, 862, 856, 854, 859, 862, 852, 846, 859, 851, 857, 857, 844, 854, 844, 852, 852, 853, 838, 833, 837, 0, 831, 825, 849, 834, 840, 842, 840, 824, 831, 823, 822, 831, 823, 838, 817, 816, 0, 833, 814, 817, 807, 826, 823, 810, 824, 813, 826, 820, 833, 823, 813, 807, 802, 810, 809, 808, 796, 799, 805, 799, 790, 799, 803, 805, 788, 794, 805, 790, 784, 789, 786, 783, 799, 440, 788, 797, 788, 781, 790, 780, 788, 783, 763, 766, 766, 757, 745, 45, 153, 303, 293, 394, 411, 416, 412, 424, 0, 416, 0, 0, 432, 0, 428, 0, 429, 431, 0, 435, 0, 0, 434, 0, 0, 424, 438, 421, 430, 437, 0, 438, 425, 436, 430, 431, 432, 431, 439, 450, 443, 448, 442, 446, 451, 457, 444, 454, 460, 456, 461, 452, 445, 0, 452, 454, 447, 467, 466, 448, 459, 451, 0, 472, 468, 466, 471, 472, 473, 464, 0, 466, 480, 473, 482, 475, 0, 471, 500, 506, 486, 468, 475, 477, 467, 487, 494, 488, 478, 483, 493, 485, 495, 497, 0, 499, 502, 496, 0, 501, 492, 502, 507, 507, 0, 508, 502, 492, 0, 508, 0, 0, 510, 495, 0, 536, 514, 0, 509, 510, 0, 518, 500, 507, 523, 509, 511, 0, 523, 526, 520, 527, 528, 511, 528, 553, 519, 530, 0, 523, 536, 0, 533, 521, 526, 532, 539, 524, 0, 526, 527, 542, 543, 533, 547, 550, 547, 569, 573, 545, 535, 542, 557, 0, 549, 551, 546, 556, 560, 546, 558, 562, 566, 564, 556, 565, 0, 571, 548, 566, 565, 554, 557, 556, 0, 572, 0, 0, 578, 580, 581, 573, 563, 570, 577, 583, 580, 585, 577, 586, 583, 572, 573, 589, 0, 592, 0, 578, 578, 0, 594, 0, 593, 596, 0, 0, 583, 588, 0, 590, 593, 593, 592, 0, 0, 588, 601, 610, 599, 605, 612, 609, 614, 0, 598, 0, 0, 606, 598, 604, 615, 620, 607, 0, 618, 604, 618, 0, 608, 0, 607, 615, 616, 610, 623, 632, 632, 629, 624, 0, 621, 632, 637, 619, 633, 623, 0, 637, 0, 638, 0, 0, 0, 0, 638, 645, 641, 633, 643, 631, 651, 648, 648, 0, 635, 630, 636, 632, 653, 658, 0, 0, 656, 638, 0, 643, 654, 659, 660, 651, 652, 649, 669, 666, 652, 647, 654, 0, 0, 670, 656, 667, 672, 0, 674, 664, 674, 678, 0, 679, 678, 0, 670, 665, 665, 680, 670, 669, 675, 667, 0, 688, 680, 675, 683, 0, 693, 694, 695, 0, 685, 680, 694, 684, 0, 699, 685, 693, 0, 697, 694, 0, 693, 705, 706, 0, 696, 700, 709, 710, 0, 698, 697, 0, 700, 714, 702, 720, 712, 718, 719, 709, 713, 722, 0, 710, 711, 729, 711, 0, 711, 711, 0, 714, 719, 724, 718, 733, 730, 0, 722, 736, 735, 723, 0, 0, 724, 729, 727, 0, 742, 741, 748, 0, 741, 0, 0, 0, 0, 0, 736, 0, 751, 748, 753, 0, 0, 0, 754, 751, 750, 755, 745, 747, 0, 754, 749, 0, 0, 758, 0, 0, 0, 0, 0, 1319, 794, 799, 801, 806, 812, 818 } ; static yyconst flex_int16_t yy_def[1100] = { 0, 1093, 1, 1093, 1093, 1093, 1093, 1094, 1095, 1096, 1093, 10, 1094, 11, 13, 1093, 13, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1093, 1093, 1094, 1097, 1097, 1096, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1093, 1098, 13, 11, 1093, 11, 11, 11, 13, 13, 13, 11, 11, 11, 13, 11, 11, 11, 11, 11, 11, 13, 11, 11, 13, 13, 13, 11, 11, 11, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1093, 1093, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1099, 1093, 1098, 71, 1094, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 11, 11, 11, 11, 11, 11, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1097, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 1093, 1093, 1093, 1093, 1093, 1093 } ; static yyconst flex_int16_t yy_nxt[1379] = { 0, 4, 5, 6, 5, 7, 8, 4, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 4, 15, 16, 16, 16, 16, 17, 18, 19, 17, 20, 17, 7, 11, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 30, 31, 32, 33, 34, 35, 17, 36, 37, 38, 39, 40, 41, 42, 17, 43, 44, 68, 44, 47, 47, 69, 72, 72, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 72, 72, 72, 50, 153, 74, 102, 154, 44, 73, 44, 751, 47, 47, 46, 148, 115, 49, 50, 50, 46, 50, 50, 50, 50, 50, 50, 50, 50, 50, 116, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 46, 50, 51, 52, 50, 53, 54, 55, 56, 57, 58, 50, 50, 59, 50, 60, 61, 62, 50, 63, 64, 50, 50, 65, 66, 50, 50, 67, 50, 50, 72, 50, 50, 50, 50, 50, 50, 72, 151, 50, 335, 50, 50, 50, 72, 50, 50, 336, 50, 50, 50, 72, 152, 50, 70, 70, 70, 70, 70, 70, 70, 70, 110, 75, 70, 70, 70, 70, 72, 72, 72, 752, 72, 71, 50, 156, 70, 70, 70, 70, 70, 70, 72, 50, 72, 113, 147, 114, 103, 150, 89, 157, 104, 50, 180, 50, 105, 82, 164, 71, 72, 90, 72, 83, 84, 87, 91, 85, 165, 50, 86, 50, 88, 72, 76, 180, 77, 190, 78, 50, 111, 50, 172, 72, 50, 79, 72, 92, 72, 93, 112, 80, 94, 173, 81, 72, 191, 50, 636, 72, 95, 135, 637, 106, 96, 145, 50, 107, 72, 98, 97, 158, 108, 109, 117, 136, 50, 99, 118, 159, 146, 167, 168, 169, 100, 50, 119, 101, 120, 50, 149, 72, 50, 121, 122, 123, 72, 198, 250, 199, 170, 204, 50, 72, 223, 184, 50, 224, 251, 137, 124, 50, 125, 205, 126, 50, 138, 127, 128, 142, 139, 129, 130, 140, 141, 131, 189, 132, 133, 50, 134, 50, 50, 50, 143, 209, 753, 210, 192, 193, 754, 144, 176, 176, 177, 176, 194, 176, 176, 176, 185, 206, 50, 247, 227, 50, 208, 50, 207, 50, 228, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 248, 274, 179, 179, 179, 179, 50, 50, 50, 265, 200, 239, 240, 254, 179, 179, 179, 179, 179, 179, 201, 258, 274, 213, 260, 261, 241, 202, 279, 266, 290, 255, 50, 282, 50, 283, 294, 295, 259, 50, 280, 299, 300, 291, 176, 176, 177, 176, 50, 176, 176, 176, 346, 361, 376, 380, 388, 362, 491, 585, 492, 755, 321, 176, 176, 50, 389, 377, 424, 328, 381, 432, 363, 425, 50, 533, 534, 586, 535, 599, 433, 600, 624, 434, 736, 756, 737, 757, 625, 758, 759, 760, 347, 435, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 890, 891, 889, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 916, 917, 915, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 974, 975, 976, 973, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 46, 750, 749, 46, 48, 48, 748, 747, 48, 49, 49, 47, 47, 47, 746, 47, 178, 178, 178, 178, 178, 178, 176, 176, 176, 176, 176, 176, 745, 744, 743, 742, 741, 740, 739, 738, 735, 734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, 667, 666, 665, 664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651, 650, 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, 639, 638, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 623, 622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609, 608, 607, 606, 605, 604, 603, 602, 601, 598, 597, 596, 595, 594, 593, 592, 591, 590, 589, 588, 587, 584, 583, 582, 581, 580, 579, 578, 577, 576, 575, 574, 573, 572, 571, 570, 569, 568, 567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, 545, 544, 543, 542, 541, 540, 539, 538, 537, 536, 532, 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, 521, 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, 495, 494, 493, 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, 480, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, 454, 453, 452, 451, 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, 431, 430, 429, 428, 427, 426, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396, 395, 394, 393, 1093, 392, 391, 390, 387, 386, 385, 384, 383, 382, 379, 378, 375, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 360, 359, 358, 357, 356, 355, 354, 353, 352, 351, 350, 349, 348, 345, 344, 343, 342, 341, 340, 339, 338, 337, 334, 333, 332, 331, 330, 329, 327, 326, 325, 324, 323, 322, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 177, 302, 301, 298, 297, 296, 293, 292, 289, 288, 287, 286, 285, 284, 281, 278, 277, 276, 275, 273, 272, 271, 270, 269, 268, 267, 264, 263, 262, 257, 256, 253, 252, 249, 246, 245, 244, 243, 242, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 226, 225, 222, 221, 220, 219, 218, 217, 216, 215, 214, 212, 211, 203, 197, 196, 195, 188, 187, 186, 183, 182, 181, 175, 174, 171, 166, 163, 162, 161, 160, 155, 151, 45, 72, 45, 1093, 3, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093 } ; static yyconst flex_int16_t yy_chk[1379] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 12, 5, 8, 8, 12, 19, 27, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 18, 41, 33, 14, 51, 19, 27, 51, 44, 18, 44, 657, 8, 8, 10, 41, 33, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 14, 33, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 20, 11, 11, 11, 11, 11, 11, 16, 48, 11, 214, 11, 11, 11, 30, 11, 11, 214, 16, 11, 11, 43, 48, 11, 13, 13, 13, 13, 13, 13, 13, 13, 30, 20, 13, 13, 13, 13, 40, 32, 28, 658, 24, 13, 16, 53, 13, 13, 13, 13, 13, 13, 22, 24, 23, 32, 40, 32, 28, 43, 24, 53, 28, 22, 72, 23, 28, 22, 59, 13, 21, 24, 31, 22, 22, 23, 24, 22, 59, 24, 22, 21, 23, 25, 21, 72, 21, 83, 21, 22, 31, 23, 64, 36, 25, 21, 29, 25, 39, 25, 31, 21, 25, 64, 21, 26, 83, 21, 540, 34, 25, 36, 540, 29, 25, 39, 26, 29, 42, 26, 25, 54, 29, 29, 34, 36, 70, 26, 34, 54, 39, 61, 61, 62, 26, 76, 34, 26, 34, 77, 42, 37, 26, 34, 34, 34, 35, 88, 132, 88, 62, 91, 70, 38, 109, 76, 82, 109, 132, 37, 35, 76, 35, 91, 35, 77, 37, 35, 35, 38, 37, 35, 35, 37, 37, 35, 82, 35, 35, 78, 35, 92, 82, 94, 38, 95, 659, 95, 84, 84, 660, 38, 69, 69, 69, 69, 84, 69, 69, 69, 78, 92, 93, 130, 112, 78, 94, 92, 93, 94, 112, 69, 69, 71, 71, 71, 71, 71, 71, 71, 71, 130, 152, 71, 71, 71, 71, 89, 93, 98, 143, 89, 124, 124, 135, 71, 71, 71, 71, 71, 71, 89, 138, 152, 98, 139, 139, 124, 89, 157, 143, 166, 135, 89, 159, 98, 159, 169, 169, 138, 200, 157, 173, 173, 166, 178, 178, 178, 178, 207, 178, 178, 178, 225, 241, 260, 263, 270, 241, 386, 487, 386, 661, 200, 178, 178, 200, 270, 260, 310, 207, 263, 317, 241, 310, 207, 432, 432, 487, 432, 502, 317, 502, 528, 317, 643, 662, 643, 663, 528, 664, 665, 667, 225, 317, 670, 672, 674, 675, 677, 680, 683, 684, 685, 686, 687, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 712, 713, 714, 715, 716, 717, 718, 719, 721, 722, 723, 724, 725, 726, 727, 729, 730, 731, 732, 733, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 753, 754, 755, 757, 758, 759, 760, 761, 763, 764, 765, 767, 770, 771, 773, 774, 776, 777, 779, 780, 781, 782, 783, 784, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 797, 798, 800, 801, 802, 803, 804, 805, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 822, 823, 824, 825, 823, 826, 827, 828, 829, 830, 831, 832, 833, 835, 836, 837, 838, 839, 840, 841, 843, 846, 847, 848, 849, 850, 851, 852, 853, 854, 852, 855, 856, 857, 858, 859, 860, 861, 863, 865, 866, 868, 870, 871, 874, 875, 877, 878, 879, 880, 883, 884, 885, 886, 887, 888, 889, 890, 892, 895, 896, 897, 898, 899, 900, 902, 903, 904, 906, 908, 909, 910, 911, 912, 913, 914, 915, 916, 918, 919, 920, 921, 922, 923, 925, 927, 932, 933, 934, 927, 935, 936, 937, 938, 939, 940, 942, 943, 944, 945, 946, 947, 950, 951, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 967, 968, 969, 970, 972, 973, 974, 975, 975, 977, 978, 980, 981, 982, 983, 984, 985, 986, 987, 989, 990, 991, 992, 994, 995, 996, 998, 999, 1000, 1001, 1003, 1004, 1005, 1007, 1008, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1019, 1020, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1033, 1034, 1035, 1036, 1038, 1039, 1041, 1042, 1043, 1044, 1045, 1046, 1048, 1049, 1050, 1051, 1054, 1055, 1056, 1058, 1059, 1060, 1062, 1068, 1070, 1071, 1072, 1076, 1077, 1078, 1079, 1080, 1081, 1083, 1084, 1087, 1094, 656, 655, 1094, 1095, 1095, 654, 653, 1095, 1096, 1096, 1097, 1097, 1097, 652, 1097, 1098, 1098, 1098, 1098, 1098, 1098, 1099, 1099, 1099, 1099, 1099, 1099, 651, 650, 649, 648, 647, 646, 645, 644, 642, 641, 640, 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623, 622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609, 608, 607, 605, 604, 603, 602, 601, 600, 599, 598, 597, 596, 595, 594, 593, 592, 591, 590, 588, 587, 586, 585, 584, 583, 582, 581, 580, 579, 578, 577, 576, 575, 574, 573, 572, 571, 570, 569, 568, 567, 566, 565, 564, 563, 562, 560, 559, 558, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, 545, 544, 543, 542, 541, 539, 538, 537, 536, 535, 534, 533, 531, 530, 529, 527, 526, 525, 524, 523, 522, 521, 520, 518, 517, 516, 515, 514, 513, 512, 511, 510, 509, 507, 506, 505, 504, 503, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 488, 486, 485, 483, 482, 481, 480, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, 453, 452, 451, 450, 449, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 436, 435, 434, 433, 431, 430, 429, 428, 427, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 413, 412, 411, 410, 409, 408, 407, 406, 405, 403, 401, 400, 399, 398, 397, 396, 395, 394, 392, 391, 390, 389, 388, 387, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 352, 350, 348, 347, 343, 341, 340, 339, 338, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, 318, 316, 315, 314, 313, 312, 311, 308, 307, 306, 305, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 269, 268, 267, 266, 265, 264, 262, 261, 258, 257, 255, 254, 253, 252, 251, 250, 249, 248, 247, 242, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 227, 226, 224, 223, 222, 220, 219, 218, 217, 216, 215, 213, 212, 211, 210, 209, 208, 206, 205, 204, 203, 202, 201, 199, 198, 197, 196, 195, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 176, 175, 174, 172, 171, 170, 168, 167, 165, 164, 163, 162, 161, 160, 158, 156, 155, 154, 153, 150, 149, 148, 147, 146, 145, 144, 142, 141, 140, 137, 136, 134, 133, 131, 129, 128, 127, 126, 125, 123, 122, 121, 120, 118, 117, 116, 115, 114, 113, 111, 110, 108, 107, 105, 104, 103, 102, 101, 100, 99, 97, 96, 90, 87, 86, 85, 81, 80, 79, 75, 74, 73, 67, 65, 63, 60, 58, 57, 56, 55, 52, 47, 45, 17, 6, 3, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093 } ; static yyconst flex_int16_t yy_rule_linenum[192] = { 0, 43, 44, 46, 49, 50, 51, 52, 53, 55, 56, 57, 59, 60, 61, 62, 63, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 115, 116, 117, 119, 120, 121, 122, 123, 124, 126, 128, 129, 130, 131, 132, 133, 135, 136, 137, 138, 139, 140, 141, 142, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 249, 250, 251, 252, 255, 256, 257 } ; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "../s/cmdoptions.l" /****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the register initialization file */ /* Run the cmdoptions.y file first through bison to generate the regidit.tab.hpp file, which is included herein */ /* Then run this file through flex to generate the cmdoptions.yy.c source code */ #line 23 "../s/cmdoptions.l" #include #include "cmdoptionsscanner.h" #include "cmdoptions.tab.hpp" typedef CO::BisonParser::token tok; #line 32 "../s/cmdoptions.l" # define YY_USER_ACTION yylloc->columns (yyleng); #line 1206 "../bisonflex/cmdoptions.yy.cpp" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ #include /* %endif */ #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* %if-c-only Reentrant structure and macros (non-C++). */ /* %if-reentrant */ /* %if-c-only */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif End reentrant structures and macros. */ /* %if-bison-bridge */ /* %endif */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #endif /* %if-c-only */ /* %endif */ /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define ECHO LexerOutput( yytext, yyleng ) /* %endif */ #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ /* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ \ /* %if-c++-only C++ definition \ */\ if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); /* %endif */ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR /* %if-c-only */ /* %endif */ /* %if-c++-only */ #define YY_FATAL_ERROR(msg) LexerError( msg ) /* %endif */ #endif /* %if-tables-serialization structures and prototypes */ /* %not-for-header */ /* %ok-for-header */ /* %not-for-header */ /* %tables-yydmap generated elements */ /* %endif */ /* end tables serialization structures and prototypes */ /* %ok-for-header */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define YY_DECL int yyFlexLexer::yylex() /* %endif */ #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif /* %% [6.0] YY_RULE_SETUP definition goes here */ #define YY_RULE_SETUP \ YY_USER_ACTION /* %not-for-header */ /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; /* %% [7.0] user's declarations go here */ #line 35 "../s/cmdoptions.l" yylloc->step (); #line 1372 "../bisonflex/cmdoptions.yy.cpp" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyin = & std::cin; /* %endif */ if ( ! yyout ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyout = & std::cout; /* %endif */ if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { /* %% [8.0] yymore()-related code goes here */ yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; /* %% [9.0] code to set up and find next match goes here */ yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1094 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 1093 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: /* %% [10.0] code to find the action number goes here */ yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; /* %% [11.0] code for yylineno update goes here */ do_action: /* This label is used only to access EOF actions. */ /* %% [12.0] debug code goes here */ if ( yy_flex_debug ) { if ( yy_act == 0 ) std::cerr << "--scanner backing up\n"; else if ( yy_act < 192 ) std::cerr << "--accepting rule at line " << yy_rule_linenum[yy_act] << "(\"" << yytext << "\")\n"; else if ( yy_act == 192 ) std::cerr << "--accepting default rule (\"" << yytext << "\")\n"; else if ( yy_act == 193 ) std::cerr << "--(end of buffer or a NUL)\n"; else std::cerr << "--EOF (start condition " << YY_START << ")\n"; } switch ( yy_act ) { /* beginning of action switch */ /* %% [13.0] actions go here */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 43 "../s/cmdoptions.l" { comment(); } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 44 "../s/cmdoptions.l" /* ignore */; YY_BREAK case 3: YY_RULE_SETUP #line 46 "../s/cmdoptions.l" yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; YY_BREAK case 4: YY_RULE_SETUP #line 49 "../s/cmdoptions.l" return tok::_IMAGE; YY_BREAK case 5: YY_RULE_SETUP #line 50 "../s/cmdoptions.l" return tok::_FILL; YY_BREAK case 6: YY_RULE_SETUP #line 51 "../s/cmdoptions.l" return tok::_O_TOK; YY_BREAK case 7: YY_RULE_SETUP #line 52 "../s/cmdoptions.l" return tok::I; YY_BREAK case 8: YY_RULE_SETUP #line 53 "../s/cmdoptions.l" return tok::_P_TOK; YY_BREAK case 9: YY_RULE_SETUP #line 55 "../s/cmdoptions.l" return tok::_W; YY_BREAK case 10: YY_RULE_SETUP #line 56 "../s/cmdoptions.l" return tok::ON; YY_BREAK case 11: YY_RULE_SETUP #line 57 "../s/cmdoptions.l" return tok::OFF; YY_BREAK case 12: YY_RULE_SETUP #line 59 "../s/cmdoptions.l" return tok::_LOG; YY_BREAK case 13: YY_RULE_SETUP #line 60 "../s/cmdoptions.l" return tok::ERROR; YY_BREAK case 14: YY_RULE_SETUP #line 61 "../s/cmdoptions.l" return tok::WARNING; YY_BREAK case 15: YY_RULE_SETUP #line 62 "../s/cmdoptions.l" return tok::INFO; YY_BREAK case 16: YY_RULE_SETUP #line 63 "../s/cmdoptions.l" return tok::DEBUG; YY_BREAK case 17: YY_RULE_SETUP #line 64 "../s/cmdoptions.l" return tok::TRACE; YY_BREAK case 18: YY_RULE_SETUP #line 66 "../s/cmdoptions.l" return tok::_BIF_HELP; YY_BREAK case 19: YY_RULE_SETUP #line 68 "../s/cmdoptions.l" return tok::_ENCRYPT; YY_BREAK case 20: YY_RULE_SETUP #line 69 "../s/cmdoptions.l" return tok::BBRAM; YY_BREAK case 21: YY_RULE_SETUP #line 70 "../s/cmdoptions.l" return tok::EFUSE; YY_BREAK case 22: YY_RULE_SETUP #line 71 "../s/cmdoptions.l" return tok::HMAC; YY_BREAK case 23: YY_RULE_SETUP #line 72 "../s/cmdoptions.l" return tok::HMAC; YY_BREAK case 24: YY_RULE_SETUP #line 73 "../s/cmdoptions.l" return tok::STARTCBC; YY_BREAK case 25: YY_RULE_SETUP #line 74 "../s/cmdoptions.l" return tok::STARTCBC; YY_BREAK case 26: YY_RULE_SETUP #line 75 "../s/cmdoptions.l" return tok::KEY0; YY_BREAK case 27: YY_RULE_SETUP #line 76 "../s/cmdoptions.l" return tok::KEY0; YY_BREAK case 28: YY_RULE_SETUP #line 78 "../s/cmdoptions.l" return tok::_SPLIT; YY_BREAK case 29: YY_RULE_SETUP #line 79 "../s/cmdoptions.l" return tok::_PROCESS_BITSTREAM; YY_BREAK case 30: YY_RULE_SETUP #line 80 "../s/cmdoptions.l" return tok::MCS; YY_BREAK case 31: YY_RULE_SETUP #line 81 "../s/cmdoptions.l" return tok::BIN; YY_BREAK case 32: YY_RULE_SETUP #line 83 "../s/cmdoptions.l" return tok::_DUAL_QSPI_MODE; YY_BREAK case 33: YY_RULE_SETUP #line 84 "../s/cmdoptions.l" return tok::_DUAL_OSPI_MODE; YY_BREAK case 34: YY_RULE_SETUP #line 85 "../s/cmdoptions.l" return tok::PARALLEL; YY_BREAK case 35: YY_RULE_SETUP #line 86 "../s/cmdoptions.l" return tok::STACKED; YY_BREAK case 36: YY_RULE_SETUP #line 88 "../s/cmdoptions.l" return tok::EQUALS; YY_BREAK case 37: YY_RULE_SETUP #line 89 "../s/cmdoptions.l" return tok::COMMA; YY_BREAK case 38: YY_RULE_SETUP #line 90 "../s/cmdoptions.l" return tok::_DEBUG_TOK; YY_BREAK case 39: YY_RULE_SETUP #line 91 "../s/cmdoptions.l" return tok::_DUMP; YY_BREAK case 40: YY_RULE_SETUP #line 92 "../s/cmdoptions.l" return tok::DUMP_PLM; YY_BREAK case 41: YY_RULE_SETUP #line 93 "../s/cmdoptions.l" return tok::DUMP_PMC_CDO; YY_BREAK case 42: YY_RULE_SETUP #line 94 "../s/cmdoptions.l" return tok::DUMP_BOOT_FILES; YY_BREAK case 43: YY_RULE_SETUP #line 95 "../s/cmdoptions.l" return tok::DUMP_SLAVE_PDIS; YY_BREAK case 44: YY_RULE_SETUP #line 96 "../s/cmdoptions.l" return tok::_DUMP_DIR; YY_BREAK case 45: YY_RULE_SETUP #line 97 "../s/cmdoptions.l" return tok::_LEGACY; YY_BREAK case 46: YY_RULE_SETUP #line 98 "../s/cmdoptions.l" return tok::_PADIMAGEHEADER; YY_BREAK case 47: YY_RULE_SETUP #line 99 "../s/cmdoptions.l" return tok::_EFUSEPPKBITS; YY_BREAK case 48: YY_RULE_SETUP #line 100 "../s/cmdoptions.l" return tok::_GENERATE_HASHES; YY_BREAK case 49: YY_RULE_SETUP #line 102 "../s/cmdoptions.l" return tok::_SECUREDEBUG; YY_BREAK case 50: YY_RULE_SETUP #line 103 "../s/cmdoptions.l" return tok::_AUTHJTAG; YY_BREAK case 51: YY_RULE_SETUP #line 105 "../s/cmdoptions.l" return tok::_GENERATE_KEYS; YY_BREAK case 52: YY_RULE_SETUP #line 106 "../s/cmdoptions.l" return tok::AUTH; YY_BREAK case 53: YY_RULE_SETUP #line 107 "../s/cmdoptions.l" return tok::PEM; YY_BREAK case 54: YY_RULE_SETUP #line 108 "../s/cmdoptions.l" return tok::RSA; YY_BREAK case 55: YY_RULE_SETUP #line 109 "../s/cmdoptions.l" return tok::GREY; YY_BREAK case 56: YY_RULE_SETUP #line 110 "../s/cmdoptions.l" return tok::METAL; YY_BREAK case 57: YY_RULE_SETUP #line 111 "../s/cmdoptions.l" return tok::ECDSA; YY_BREAK case 58: YY_RULE_SETUP #line 112 "../s/cmdoptions.l" return tok::ECDSA; YY_BREAK case 59: YY_RULE_SETUP #line 113 "../s/cmdoptions.l" return tok::ECDSAP521; YY_BREAK case 60: YY_RULE_SETUP #line 115 "../s/cmdoptions.l" return tok::_NONBOOTING; YY_BREAK case 61: YY_RULE_SETUP #line 116 "../s/cmdoptions.l" return tok::_SPKSIGNATURE; YY_BREAK case 62: YY_RULE_SETUP #line 117 "../s/cmdoptions.l" return tok::_PACKAGENAME; YY_BREAK case 63: YY_RULE_SETUP #line 119 "../s/cmdoptions.l" return tok::_ARCH; YY_BREAK case 64: YY_RULE_SETUP #line 120 "../s/cmdoptions.l" return tok::ZYNQ; YY_BREAK case 65: YY_RULE_SETUP #line 121 "../s/cmdoptions.l" return tok::ZYNQMP; YY_BREAK case 66: YY_RULE_SETUP #line 122 "../s/cmdoptions.l" return tok::VERSAL; YY_BREAK case 67: YY_RULE_SETUP #line 123 "../s/cmdoptions.l" return tok::FPGA; YY_BREAK case 68: YY_RULE_SETUP #line 124 "../s/cmdoptions.l" return tok::VERSALNET; YY_BREAK case 69: YY_RULE_SETUP #line 126 "../s/cmdoptions.l" return tok::_R; YY_BREAK case 70: YY_RULE_SETUP #line 128 "../s/cmdoptions.l" return tok::_READ; YY_BREAK case 71: YY_RULE_SETUP #line 129 "../s/cmdoptions.l" return tok::READ_BH; YY_BREAK case 72: YY_RULE_SETUP #line 130 "../s/cmdoptions.l" return tok::READ_IHT; YY_BREAK case 73: YY_RULE_SETUP #line 131 "../s/cmdoptions.l" return tok::READ_IH; YY_BREAK case 74: YY_RULE_SETUP #line 132 "../s/cmdoptions.l" return tok::READ_PHT; YY_BREAK case 75: YY_RULE_SETUP #line 133 "../s/cmdoptions.l" return tok::READ_AC; YY_BREAK case 76: YY_RULE_SETUP #line 135 "../s/cmdoptions.l" return tok::_AUTH_OPTIMIZATION; YY_BREAK case 77: YY_RULE_SETUP #line 136 "../s/cmdoptions.l" return tok::_VERIFYKDF; YY_BREAK case 78: YY_RULE_SETUP #line 137 "../s/cmdoptions.l" return tok::_VERIFY; YY_BREAK case 79: YY_RULE_SETUP #line 138 "../s/cmdoptions.l" return tok::_ZYNQMPENCRDUMP; YY_BREAK case 80: YY_RULE_SETUP #line 139 "../s/cmdoptions.l" return tok::_NOAUTHBLOCKS; YY_BREAK case 81: YY_RULE_SETUP #line 140 "../s/cmdoptions.l" return tok::_ZYNQMPES1; YY_BREAK case 82: YY_RULE_SETUP #line 141 "../s/cmdoptions.l" return tok::_OVERLAYCDO; YY_BREAK case 83: YY_RULE_SETUP #line 142 "../s/cmdoptions.l" return tok::_OUT_TYPE; YY_BREAK case 84: YY_RULE_SETUP #line 144 "../s/cmdoptions.l" return tok::_H; YY_BREAK case 85: YY_RULE_SETUP #line 145 "../s/cmdoptions.l" return tok::_H; YY_BREAK case 86: YY_RULE_SETUP #line 146 "../s/cmdoptions.l" return tok::HBIFHELP; YY_BREAK case 87: YY_RULE_SETUP #line 147 "../s/cmdoptions.l" return tok::HARCH; YY_BREAK case 88: YY_RULE_SETUP #line 148 "../s/cmdoptions.l" return tok::HAUTHOPT; YY_BREAK case 89: YY_RULE_SETUP #line 149 "../s/cmdoptions.l" return tok::HIMAGE; YY_BREAK case 90: YY_RULE_SETUP #line 150 "../s/cmdoptions.l" return tok::HFILL; YY_BREAK case 91: YY_RULE_SETUP #line 151 "../s/cmdoptions.l" return tok::HO; YY_BREAK case 92: YY_RULE_SETUP #line 152 "../s/cmdoptions.l" return tok::HP; YY_BREAK case 93: YY_RULE_SETUP #line 153 "../s/cmdoptions.l" return tok::HW; YY_BREAK case 94: YY_RULE_SETUP #line 154 "../s/cmdoptions.l" return tok::HEFUSEPPKBITS; YY_BREAK case 95: YY_RULE_SETUP #line 155 "../s/cmdoptions.l" return tok::HGENHASHES; YY_BREAK case 96: YY_RULE_SETUP #line 156 "../s/cmdoptions.l" return tok::HLEGACY; YY_BREAK case 97: YY_RULE_SETUP #line 157 "../s/cmdoptions.l" return tok::HPADHDR; YY_BREAK case 98: YY_RULE_SETUP #line 158 "../s/cmdoptions.l" return tok::H_SPKSIGN; YY_BREAK case 99: YY_RULE_SETUP #line 159 "../s/cmdoptions.l" return tok::HPACKAGE; YY_BREAK case 100: YY_RULE_SETUP #line 160 "../s/cmdoptions.l" return tok::HENCRYPT; YY_BREAK case 101: YY_RULE_SETUP #line 161 "../s/cmdoptions.l" return tok::HGENKEYS; YY_BREAK case 102: YY_RULE_SETUP #line 162 "../s/cmdoptions.l" return tok::HDQSPI; YY_BREAK case 103: YY_RULE_SETUP #line 163 "../s/cmdoptions.l" return tok::HLOG; YY_BREAK case 104: YY_RULE_SETUP #line 164 "../s/cmdoptions.l" return tok::HZYNQMPES1; YY_BREAK case 105: YY_RULE_SETUP #line 165 "../s/cmdoptions.l" return tok::HPROCESSBIT; YY_BREAK case 106: YY_RULE_SETUP #line 166 "../s/cmdoptions.l" return tok::HNONBOOTING; YY_BREAK case 107: YY_RULE_SETUP #line 167 "../s/cmdoptions.l" return tok::HENCRDUMP; YY_BREAK case 108: YY_RULE_SETUP #line 168 "../s/cmdoptions.l" return tok::HVERIFY; YY_BREAK case 109: YY_RULE_SETUP #line 169 "../s/cmdoptions.l" return tok::HVERIFYKDF; YY_BREAK case 110: YY_RULE_SETUP #line 170 "../s/cmdoptions.l" return tok::HSECUREDEBUG; YY_BREAK case 111: YY_RULE_SETUP #line 171 "../s/cmdoptions.l" return tok::HSECUREDEBUG; YY_BREAK case 112: YY_RULE_SETUP #line 172 "../s/cmdoptions.l" return tok::HREAD; YY_BREAK case 113: YY_RULE_SETUP #line 173 "../s/cmdoptions.l" return tok::HDUMP; YY_BREAK case 114: YY_RULE_SETUP #line 174 "../s/cmdoptions.l" return tok::HDUMPDIR; YY_BREAK case 115: YY_RULE_SETUP #line 175 "../s/cmdoptions.l" return tok::HOVLCDO; YY_BREAK case 116: YY_RULE_SETUP #line 176 "../s/cmdoptions.l" return tok::HOUTTYPE; YY_BREAK case 117: YY_RULE_SETUP #line 178 "../s/cmdoptions.l" return tok::H_BIF_AARCH32; YY_BREAK case 118: YY_RULE_SETUP #line 179 "../s/cmdoptions.l" return tok::H_BIF_BIGENDIAN; YY_BREAK case 119: YY_RULE_SETUP #line 180 "../s/cmdoptions.l" return tok::H_BIF_BOOTCONFIG; YY_BREAK case 120: YY_RULE_SETUP #line 181 "../s/cmdoptions.l" return tok::H_BIF_COPY; YY_BREAK case 121: YY_RULE_SETUP #line 182 "../s/cmdoptions.l" return tok::H_BIF_CORE; YY_BREAK case 122: YY_RULE_SETUP #line 183 "../s/cmdoptions.l" return tok::H_BIF_DELAY_HANDOFF; YY_BREAK case 123: YY_RULE_SETUP #line 184 "../s/cmdoptions.l" return tok::H_BIF_DELAY_LOAD; YY_BREAK case 124: YY_RULE_SETUP #line 185 "../s/cmdoptions.l" return tok::H_BIF_FILE; YY_BREAK case 125: YY_RULE_SETUP #line 186 "../s/cmdoptions.l" return tok::H_BIF_ID; YY_BREAK case 126: YY_RULE_SETUP #line 187 "../s/cmdoptions.l" return tok::H_BIF_IMAGE; YY_BREAK case 127: YY_RULE_SETUP #line 188 "../s/cmdoptions.l" return tok::H_BIF_METAHDR; YY_BREAK case 128: YY_RULE_SETUP #line 189 "../s/cmdoptions.l" return tok::H_BIF_NAME; YY_BREAK case 129: YY_RULE_SETUP #line 190 "../s/cmdoptions.l" return tok::H_BIF_PARTITION; YY_BREAK case 130: YY_RULE_SETUP #line 191 "../s/cmdoptions.l" return tok::H_BIF_PARENTID; YY_BREAK case 131: YY_RULE_SETUP #line 192 "../s/cmdoptions.l" return tok::H_BIF_SLR; YY_BREAK case 132: YY_RULE_SETUP #line 193 "../s/cmdoptions.l" return tok::H_BIF_TYPE; YY_BREAK case 133: YY_RULE_SETUP #line 194 "../s/cmdoptions.l" return tok::H_BIF_KEYSRC; YY_BREAK case 134: YY_RULE_SETUP #line 195 "../s/cmdoptions.l" return tok::H_BIF_INIT; YY_BREAK case 135: YY_RULE_SETUP #line 196 "../s/cmdoptions.l" return tok::H_BIF_UDFBH; YY_BREAK case 136: YY_RULE_SETUP #line 197 "../s/cmdoptions.l" return tok::H_BIF_AES; YY_BREAK case 137: YY_RULE_SETUP #line 198 "../s/cmdoptions.l" return tok::H_BIF_PPK; YY_BREAK case 138: YY_RULE_SETUP #line 199 "../s/cmdoptions.l" return tok::H_BIF_PSK; YY_BREAK case 139: YY_RULE_SETUP #line 200 "../s/cmdoptions.l" return tok::H_BIF_SPK; YY_BREAK case 140: YY_RULE_SETUP #line 201 "../s/cmdoptions.l" return tok::H_BIF_SSK; YY_BREAK case 141: YY_RULE_SETUP #line 202 "../s/cmdoptions.l" return tok::H_BIF_SPKSIGN; YY_BREAK case 142: YY_RULE_SETUP #line 203 "../s/cmdoptions.l" return tok::H_BIF_HDRSIGN; YY_BREAK case 143: YY_RULE_SETUP #line 204 "../s/cmdoptions.l" return tok::H_BIF_BOOTIMAGE; YY_BREAK case 144: YY_RULE_SETUP #line 205 "../s/cmdoptions.l" return tok::H_BIF_BL; YY_BREAK case 145: YY_RULE_SETUP #line 206 "../s/cmdoptions.l" return tok::H_BIF_ENCR; YY_BREAK case 146: YY_RULE_SETUP #line 207 "../s/cmdoptions.l" return tok::H_BIF_PID; YY_BREAK case 147: YY_RULE_SETUP #line 208 "../s/cmdoptions.l" return tok::H_BIF_AUTH; YY_BREAK case 148: YY_RULE_SETUP #line 209 "../s/cmdoptions.l" return tok::H_BIF_TCMBOOT; YY_BREAK case 149: YY_RULE_SETUP #line 210 "../s/cmdoptions.l" return tok::H_BIF_OPTIONALDATA; YY_BREAK case 150: YY_RULE_SETUP #line 211 "../s/cmdoptions.l" return tok::H_BIF_CHKSM; YY_BREAK case 151: YY_RULE_SETUP #line 212 "../s/cmdoptions.l" return tok::H_BIF_POWNER; YY_BREAK case 152: YY_RULE_SETUP #line 213 "../s/cmdoptions.l" return tok::H_BIF_POWNER; YY_BREAK case 153: YY_RULE_SETUP #line 214 "../s/cmdoptions.l" return tok::H_BIF_PRESIGN; YY_BREAK case 154: YY_RULE_SETUP #line 215 "../s/cmdoptions.l" return tok::H_BIF_UDF; YY_BREAK case 155: YY_RULE_SETUP #line 216 "../s/cmdoptions.l" return tok::H_BIF_XIP; YY_BREAK case 156: YY_RULE_SETUP #line 217 "../s/cmdoptions.l" return tok::H_BIF_ALIGN; YY_BREAK case 157: YY_RULE_SETUP #line 218 "../s/cmdoptions.l" return tok::H_BIF_OFFSET; YY_BREAK case 158: YY_RULE_SETUP #line 219 "../s/cmdoptions.l" return tok::H_BIF_RES; YY_BREAK case 159: YY_RULE_SETUP #line 220 "../s/cmdoptions.l" return tok::H_BIF_LOAD; YY_BREAK case 160: YY_RULE_SETUP #line 221 "../s/cmdoptions.l" return tok::H_BIF_STARTUP; YY_BREAK case 161: YY_RULE_SETUP #line 222 "../s/cmdoptions.l" return tok::H_BIF_KEYSRCENCR; YY_BREAK case 162: YY_RULE_SETUP #line 223 "../s/cmdoptions.l" return tok::H_BIF_FSBLCFG; YY_BREAK case 163: YY_RULE_SETUP #line 224 "../s/cmdoptions.l" return tok::H_BIF_BOOTDEV; YY_BREAK case 164: YY_RULE_SETUP #line 225 "../s/cmdoptions.l" return tok::H_BIF_DESTCPU; YY_BREAK case 165: YY_RULE_SETUP #line 226 "../s/cmdoptions.l" return tok::H_BIF_DESTDEV; YY_BREAK case 166: YY_RULE_SETUP #line 227 "../s/cmdoptions.l" return tok::H_BIF_EL; YY_BREAK case 167: YY_RULE_SETUP #line 228 "../s/cmdoptions.l" return tok::H_BIF_TZ; YY_BREAK case 168: YY_RULE_SETUP #line 229 "../s/cmdoptions.l" return tok::H_BIF_AUTHPARAM; YY_BREAK case 169: YY_RULE_SETUP #line 230 "../s/cmdoptions.l" return tok::H_BIF_BHKEY; YY_BREAK case 170: YY_RULE_SETUP #line 231 "../s/cmdoptions.l" return tok::H_BIF_PFW; YY_BREAK case 171: YY_RULE_SETUP #line 232 "../s/cmdoptions.l" return tok::H_BIF_BLOCKS; YY_BREAK case 172: YY_RULE_SETUP #line 233 "../s/cmdoptions.l" return tok::H_BIF_BHIV; YY_BREAK case 173: YY_RULE_SETUP #line 234 "../s/cmdoptions.l" return tok::H_BIF_METAL; YY_BREAK case 174: YY_RULE_SETUP #line 235 "../s/cmdoptions.l" return tok::H_BIF_ELYHNDOFF; YY_BREAK case 175: YY_RULE_SETUP #line 236 "../s/cmdoptions.l" return tok::H_BIF_HIVEC; YY_BREAK case 176: YY_RULE_SETUP #line 237 "../s/cmdoptions.l" return tok::H_BIF_BHSIGN; YY_BREAK case 177: YY_RULE_SETUP #line 238 "../s/cmdoptions.l" return tok::H_SPLIT; YY_BREAK case 178: YY_RULE_SETUP #line 239 "../s/cmdoptions.l" return tok::H_BIF_BOOTVEC; YY_BREAK case 179: YY_RULE_SETUP #line 240 "../s/cmdoptions.l" return tok::H_BIF_PUFDATA; YY_BREAK case 180: YY_RULE_SETUP #line 241 "../s/cmdoptions.l" return tok::H_DPACM_ENABLE; YY_BREAK case 181: YY_RULE_SETUP #line 242 "../s/cmdoptions.l" return tok::H_BIF_USERKEYS; YY_BREAK case 182: YY_RULE_SETUP #line 243 "../s/cmdoptions.l" return tok::HVN_BIF_PCR; YY_BREAK case 183: YY_RULE_SETUP #line 244 "../s/cmdoptions.l" return tok::HVN_BIF_PCR_MINDEX; YY_BREAK case 184: YY_RULE_SETUP #line 245 "../s/cmdoptions.l" return tok::HV_BIF_IMAGESTORE; YY_BREAK case 185: YY_RULE_SETUP #line 249 "../s/cmdoptions.l" yylval->cstring=strdup(yytext); return tok::HEXSTRING; YY_BREAK case 186: YY_RULE_SETUP #line 250 "../s/cmdoptions.l" yylval->cstring=strdup(yytext); return tok::IDENTIFIER; YY_BREAK case 187: YY_RULE_SETUP #line 251 "../s/cmdoptions.l" yylval->cstring=strdup(yytext); return tok::FILENAME; YY_BREAK case 188: YY_RULE_SETUP #line 252 "../s/cmdoptions.l" yylval->cstring=strdup(yytext+1); yylval->cstring[strlen(yytext)-2]=0; return tok::QFILENAME; YY_BREAK case 189: YY_RULE_SETUP #line 255 "../s/cmdoptions.l" yylloc->step (); YY_BREAK case 190: /* rule 190 can match eol */ YY_RULE_SETUP #line 256 "../s/cmdoptions.l" yylloc->lines (yyleng); yylloc->step (); YY_BREAK case 191: YY_RULE_SETUP #line 257 "../s/cmdoptions.l" LOG_ERROR("Unknown option on command line: %s\n",yytext); YY_BREAK case 192: YY_RULE_SETUP #line 258 "../s/cmdoptions.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 2443 "../bisonflex/cmdoptions.yy.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* %ok-for-header */ /* %if-c++-only */ /* %not-for-header */ /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ) { yyin = arg_yyin; yyout = arg_yyout; yy_c_buf_p = 0; yy_init = 0; yy_start = 0; yy_flex_debug = 0; yylineno = 1; // this will only get updated if %option yylineno yy_did_buffer_switch_on_eof = 0; yy_looking_for_trail_begin = 0; yy_more_flag = 0; yy_more_len = 0; yy_more_offset = yy_prev_more_offset = 0; yy_start_stack_ptr = yy_start_stack_depth = 0; yy_start_stack = NULL; yy_buffer_stack = 0; yy_buffer_stack_top = 0; yy_buffer_stack_max = 0; yy_state_buf = 0; } /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::~yyFlexLexer() { delete [] yy_state_buf; cmdoptionsfree(yy_start_stack ); yy_delete_buffer( YY_CURRENT_BUFFER ); cmdoptionsfree(yy_buffer_stack ); } /* The contents of this function are C++ specific, so the () macro is not used. */ void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out ) { if ( new_in ) { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); } if ( new_out ) yyout = new_out; } #ifdef YY_INTERACTIVE int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) #else int yyFlexLexer::LexerInput( char* buf, int max_size ) #endif { if ( yyin->eof() || yyin->fail() ) return 0; #ifdef YY_INTERACTIVE yyin->get( buf[0] ); if ( yyin->eof() ) return 0; if ( yyin->bad() ) return -1; return 1; #else (void) yyin->read( buf, max_size ); if ( yyin->bad() ) return -1; else return yyin->gcount(); #endif } void yyFlexLexer::LexerOutput( const char* buf, int size ) { (void) yyout->write( buf, size ); } /* %ok-for-header */ /* %endif */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_get_next_buffer() /* %endif */ { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ cmdoptionsrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmdoptionsrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ /* %if-c-only */ /* %not-for-header */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_get_previous_state() /* %endif */ { register yy_state_type yy_current_state; register char *yy_cp; /* %% [15.0] code to get the start state into yy_current_state goes here */ yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { /* %% [16.0] code to find the next state goes here */ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1094 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) /* %endif */ { register int yy_is_jam; /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1094 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 1093); return yy_is_jam ? 0 : yy_current_state; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyunput( int c, register char* yy_bp) /* %endif */ { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; /* %% [18.0] update yylineno here */ (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yyinput() /* %endif */ { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); /* %% [19.0] update BOL and yylineno */ return c; } /* %if-c-only */ /* %endif */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyrestart( std::istream* input_file ) /* %endif */ { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_init_buffer( YY_CURRENT_BUFFER, input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) /* %endif */ { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_load_buffer_state() /* %endif */ { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size ) /* %endif */ { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) cmdoptionsalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) cmdoptionsalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) cmdoptionsfree((void *) b->yy_ch_buf ); cmdoptionsfree((void *) b ); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ extern "C" int isatty (int ); /* %endif */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file ) /* %endif */ { int oerrno = errno; yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ b->yy_is_interactive = 0; /* %endif */ errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /* %if-c-or-c++ */ /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer) /* %endif */ { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /* %endif */ /* %if-c-or-c++ */ /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypop_buffer_state (void) /* %endif */ { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* %endif */ /* %if-c-or-c++ */ /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyensure_buffer_stack(void) /* %endif */ { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)cmdoptionsalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)cmdoptionsrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_push_state( int new_state ) /* %endif */ { if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) { yy_size_t new_size; (yy_start_stack_depth) += YY_START_STACK_INCR; new_size = (yy_start_stack_depth) * sizeof( int ); if ( ! (yy_start_stack) ) (yy_start_stack) = (int *) cmdoptionsalloc(new_size ); else (yy_start_stack) = (int *) cmdoptionsrealloc((void *) (yy_start_stack),new_size ); if ( ! (yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; BEGIN(new_state); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_pop_state() /* %endif */ { if ( --(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_top_state() /* %endif */ { return (yy_start_stack)[(yy_start_stack_ptr) - 1]; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::LexerError( yyconst char msg[] ) { std::cerr << msg << std::endl; exit( YY_EXIT_FAILURE ); } /* %endif */ /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /* %if-c-only */ /* %if-reentrant */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif */ /* %if-reentrant */ /* %if-bison-bridge */ /* %endif */ /* %endif if-c-only */ /* %if-c-only */ /* %endif */ /* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ /* %if-reentrant */ /* %endif */ /* %endif */ /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *cmdoptionsalloc (yy_size_t size ) { return (void *) malloc( size ); } void *cmdoptionsrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void cmdoptionsfree (void * ptr ) { free( (char *) ptr ); /* see cmdoptionsrealloc() for (char *) cast */ } /* %if-tables-serialization definitions */ /* %define-yytables The name for this specific scanner's tables. */ #define YYTABLES_NAME "yytables" /* %endif */ /* %ok-for-header */ #line 258 "../s/cmdoptions.l" void CO::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/cmdoptionsscanner.h000077500000000000000000000054531475706442400205020ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _CMDOPTIONSSCANNER_H_ #define _CMDOPTIONSSCANNER_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ // Only include FlexLexer.h if it hasn't been already included #if ! defined(yyFlexLexerOnce) #undef yyFlexLexer #define yyFlexLexer reginitFlexLexer #include "FlexLexer.h" #endif // Override the interface for yylex since we namespaced it #undef YY_DECL #define YY_DECL int CO::FlexScanner::yylex() // Include Bison for types / tokens #include "cmdoptions.tab.hpp" #include "options.h" #include "parsing.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ namespace CO { class FlexScanner : public yyFlexLexer { public: // save the pointer to yylval so we can change it, and invoke scanner int yylex(CO::BisonParser::semantic_type * lval, CO::BisonParser::location_type* loc) { yylval = lval; yylloc = loc; return yylex(); } void comment(); std::string commandline; void ReportError(const CO::BisonParser::location_type &loc, const std::string &msg) { std::cerr << "ERROR: " << msg << "\n"; Parsing::Error2(loc,commandline); } private: // Scanning function created by Flex; make this private to force usage // of the overloaded method so we can get a pointer to Bison's yylval int yylex(); // point to yylval (provided by Bison in overloaded yylex) CO::BisonParser::semantic_type * yylval; CO::BisonParser::location_type * yylloc; }; } #endif xilinx-bootgen-2024.2/elf.h000077500000000000000000000221451475706442400155140ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _SYS_ELF_H #define _SYS_ELF_H /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "elftypes.h" #ifdef __cplusplus extern "C" { #endif /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define EI_NIDENT 16 #define ELF32_FSZ_ADDR 4 #define ELF32_FSZ_HALF 2 #define ELF32_FSZ_OFF 4 #define ELF32_FSZ_SWORD 4 #define ELF32_FSZ_WORD 4 /* e_ident[] indexes */ #define EI_MAG0 0 #define EI_MAG1 1 #define EI_MAG2 2 #define EI_MAG3 3 #define EI_CLASS 4 #define EI_DATA 5 #define EI_VERSION 6 #define EI_PAD 7 /* EI_MAG */ #define ELFMAG0 0x7f #define ELFMAG1 'E' #define ELFMAG2 'L' #define ELFMAG3 'F' #define ELFMAG "\177ELF" #define SELFMAG 4 /* EI_DATA */ #define ELFDATANONE 0 #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 #define ELFDATANUM 3 /* e_type */ #define ET_NONE 0 #define ET_REL 1 #define ET_EXEC 2 #define ET_DYN 3 #define ET_CORE 4 #define ET_NUM 5 /* processor specific range */ #define ET_LOPROC 0xff00 #define ET_HIPROC 0xffff /* e_machine */ #define EM_NONE 0 #define EM_M32 1 /* AT&T WE 32100 */ #define EM_SPARC 2 /* Sun SPARC */ #define EM_386 3 /* Intel 80386 */ #define EM_68K 4 /* Motorola 68000 */ #define EM_88K 5 /* Motorola 88000 */ #define EM_486 6 /* Intel 80486 */ #define EM_860 7 /* Intel i860 */ #define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ #define EM_UNKNOWN9 9 #define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-Endian */ #define EM_RS6000 11 /* RS6000 */ #define EM_UNKNOWN12 12 #define EM_UNKNOWN13 13 #define EM_UNKNOWN14 14 #define EM_PA_RISC 15 /* PA-RISC */ #define EM_nCUBE 16 /* nCUBE */ #define EM_VPP500 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun SPARC 32+ */ #define EM_UNKNOWN19 19 #define EM_PPC 20 /* PowerPC */ #define EM_NUM 21 /* e_version, EI_VERSION */ #define EV_NONE 0 #define EV_CURRENT 1 #define EV_NUM 2 /* p_type */ #define PT_NULL 0 #define PT_LOAD 1 #define PT_DYNAMIC 2 #define PT_INTERP 3 #define PT_NOTE 4 #define PT_SHLIB 5 #define PT_PHDR 6 #define PT_NUM 7 /* processor specific range */ #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7fffffff /* p_flags */ #define PF_R 0x4 #define PF_W 0x2 #define PF_X 0x1 /* processor specific values */ #define PF_MASKPROC 0xf0000000 /* sh_type */ #define SHT_NULL 0 #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_RELA 4 #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 #define SHT_NOBITS 8 #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 #define SHT_NUM 12 #define SHT_LOSUNW 0x6ffffffd #define SHT_SUNW_verdef 0x6ffffffd #define SHT_SUNW_verneed 0x6ffffffe #define SHT_SUNW_versym 0x6fffffff #define SHT_HISUNW 0x6fffffff /* processor specific range */ #define SHT_LOPROC 0x70000000 #define SHT_HIPROC 0x7fffffff #define SHT_LOUSER 0x80000000 #define SHT_HIUSER 0xffffffff /* sh_flags */ #define SHF_WRITE 0x1 #define SHF_ALLOC 0x2 #define SHF_EXECINSTR 0x4 /* processor specific values */ #define SHF_MASKPROC 0xf0000000 /* special section numbers */ #define SHN_UNDEF 0 #define SHN_LORESERVE 0xff00 #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 #define SHN_HIRESERVE 0xffff /* processor specific range */ #define SHN_LOPROC 0xff00 #define SHN_HIPROC 0xff1f #define STN_UNDEF 0 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ typedef struct { unsigned char e_ident[EI_NIDENT]; /* ident bytes */ Elf32_Half e_type; /* file type */ Elf32_Half e_machine; /* target machine */ Elf32_Word e_version; /* file version */ Elf32_Addr e_entry; /* start address */ Elf32_Off e_phoff; /* phdr file offset */ Elf32_Off e_shoff; /* shdr file offset */ Elf32_Word e_flags; /* file flags */ Elf32_Half e_ehsize; /* sizeof ehdr */ Elf32_Half e_phentsize; /* sizeof phdr */ Elf32_Half e_phnum; /* number phdrs */ Elf32_Half e_shentsize; /* sizeof shdr */ Elf32_Half e_shnum; /* number shdrs */ Elf32_Half e_shstrndx; /* shdr string index */ } Elf32_Ehdr; /******************************************************************************/ typedef struct { unsigned char e_ident[EI_NIDENT]; /* ident bytes */ Elf64_Half e_type; /* file type */ Elf64_Half e_machine; /* target machine */ Elf64_Word e_version; /* file version */ Elf64_Addr e_entry; /* start address */ Elf64_Off e_phoff; /* phdr file offset */ Elf64_Off e_shoff; /* shdr file offset */ Elf64_Word e_flags; /* file flags */ Elf64_Half e_ehsize; /* sizeof ehdr */ Elf64_Half e_phentsize; /* sizeof phdr */ Elf64_Half e_phnum; /* number phdrs */ Elf64_Half e_shentsize; /* sizeof shdr */ Elf64_Half e_shnum; /* number shdrs */ Elf64_Half e_shstrndx; /* shdr string index */ } Elf64_Ehdr; /******************************************************************************/ typedef struct { Elf32_Word p_type; /* entry type */ Elf32_Off p_offset; /* file offset */ Elf32_Addr p_vaddr; /* virtual address */ Elf32_Addr p_paddr; /* physical address */ Elf32_Word p_filesz; /* file size */ Elf32_Word p_memsz; /* memory size */ Elf32_Word p_flags; /* entry flags */ Elf32_Word p_align; /* memory/file alignment */ } Elf32_Phdr; /******************************************************************************/ typedef struct { Elf32_Word sh_name; /* section name */ Elf32_Word sh_type; /* SHT_... */ Elf32_Word sh_flags; /* SHF_... */ Elf32_Addr sh_addr; /* virtual address */ Elf32_Off sh_offset; /* file offset */ Elf32_Word sh_size; /* section size */ Elf32_Word sh_link; /* misc info */ Elf32_Word sh_info; /* misc info */ Elf32_Word sh_addralign; /* memory alignment */ Elf32_Word sh_entsize; /* entry size if table */ } Elf32_Shdr; /******************************************************************************/ typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; /* bind, type: ELF_32_ST_... */ unsigned char st_other; Elf32_Half st_shndx; /* SHN_... */ } Elf32_Sym; #ifdef __cplusplus } #endif #endif xilinx-bootgen-2024.2/elftools.cpp000077500000000000000000001021621475706442400171260ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "elftools.h" #include "imageheadertable.h" #include "bootgenexception.h" #include "logger.h" #include "fileutils.h" static bool gEndianessInitialized = false; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ uint32_t ComputeWordChecksum(void* firstWordPtr, size_t length) { uint32_t checksum = 0; size_t numChecksumedWords = length / sizeof(uint32_t); for (size_t i = 0; i< numChecksumedWords; i++) { checksum += ((uint32_t*)firstWordPtr)[i]; } /* Invert the Checksum value */ checksum ^= 0xFFFFFFFF; return checksum; } /******************************************************************************/ Endianness::Type EndianMachine( void ) { static Endianness::Type gEndianMachine = Endianness::NotEndian; if(!gEndianessInitialized) { gEndianessInitialized = true; union { uint8_t bytes[4]; uint32_t value; } data; // pack 0xDEADBEEF as big endian data.bytes[ 0 ] = 0xDE; data.bytes[ 1 ] = 0xAD; data.bytes[ 2 ] = 0xBE; data.bytes[ 3 ] = 0xEF; if( data.value == 0xDEADBEEF ) { gEndianMachine = Endianness::BigEndian; } else if (data.value == 0xEFBEADDE) { gEndianMachine = Endianness::LittleEndian; } else { LOG_ERROR("Cannot determine endianess of the ELF file"); } } return gEndianMachine; } /******************************************************************************/ uint16_t DeendianUInt16(Endianness::Type endian, uint16_t data16) { if(endian != EndianMachine()) { data16 = SwapUInt16Bytes(data16); } return data16; } /******************************************************************************/ uint32_t DeendianUInt32(Endianness::Type endian, uint32_t data32) { if(endian != EndianMachine()) { data32 = SwapUInt32Bytes(data32); } return data32; } /******************************************************************************/ uint64_t DeendianUInt64(Endianness::Type endian, uint64_t data64) { if(endian != EndianMachine()) { data64 = SwapUInt64Bytes(data64); } return data64; } /******************************************************************************/ ElfFormat32::ElfFormat32(uint8_t* start) : sectionHdrTbl(NULL) { endian = (Endianness::Type) ((Elf32_Ehdr*)start)->e_ident[EI_DATA]; DeendianELFHdr(start); /* Get the header's size. For completeness, tell upper layers that we only have one record. */ elfHdrEntryCount = 1; /* Basic ELF checks */ if(ELFHdrEntrySize() != sizeof(Elf32_Ehdr)) { LOG_DEBUG(DEBUG_STAMP, "ELF Header size wrong - %d, actual size - %d", ELFHdrEntrySize(), sizeof(Elf64_Ehdr)); LOG_ERROR("ELF Parsing Error !!!\n Wrong Header Size"); } if (memcmp(header.e_ident, ELFMAG, 4) != 0) { LOG_DEBUG(DEBUG_STAMP, "ELF magic identification word wrong"); LOG_ERROR("ELF Parsing Error !!!\n ELF magic identification word wrong"); } /* If a Section header is defined, get its pointer and its record size count. Otherwise, default it to NULL. */ if(header.e_shoff == 0) { sectionHdrTbl = NULL; sectionHdrEntrySize = 0; sectionHdrEntryCount = 0; } else { sectionHdrTbl = (Elf32SectionHdr_t *)(start + header.e_shoff); sectionHdrEntrySize = header.e_shentsize; sectionHdrEntryCount = header.e_shnum; /* Now loop through all of the Sections headers and replace indexes with properly endianized values. */ for(unsigned int index=0; indexp_paddr = programHeaders[index]->p_vaddr; } } #else /* If the number of physical addresses of all the program section the same, signal that the physical addresses should be ignored, and logical address should be used instead. However, if we're doing an extended dump, don't "fix" the addresses so that we can see what they were actually set to. */ if(((dumpMode & DATA_DUMP_EXTENDED ) == false) && ( countProgramPhysicalAddresses == programHdrEntryCount ) ) { useLogicalLoadAddress = true; // Loop through all of the Program headers and replace the physical address // values with the virtual addresses. for( index = 0; index < programHdrEntryCount; ++index ) INDEXED_PROGRAM_STRUCT_ADDRESS( index )->p_paddr = INDEXED_PROGRAM_STRUCT_ADDRESS( index )->p_vaddr; } #endif for(unsigned int index = 0; index < programHdrEntryCount; ++index) { Elf32ProgramHeader& prgHdr(*programHeaders[index]); /* The GNU linkers sometimes put an extraneous ELF header into the beginning the of some Program segments. This messes up what is put in memory, so get rid of those headers by changing the Program header info. */ TrimUnwantedELFHeaders(prgHdr, start); /* Record the lowest and highest program section address for this ELF file. */ if(prgHdr.p_filesz > 0) { if(prgHdr.p_paddr < lowestProgramAddress) { lowestProgramAddress = prgHdr.p_paddr; } if( ((prgHdr.p_paddr + prgHdr.p_filesz) - 1) > highestProgramAddress ) { highestProgramAddress = (prgHdr.p_paddr + prgHdr.p_filesz - 1); } } } } } /******************************************************************************/ ElfFormat32::~ElfFormat32() { uint32_t index; if(sectionHdrTbl) { free (sectionHdrTbl); sectionHdrTbl = 0; } for(index = 0; index < programHdrEntryCount; ++index) { if (programHeaders[index]->data) { delete[] programHeaders[index]->data; } } } /******************************************************************************/ void ElfFormat32::DeendianELFHdr( uint8_t* start) { Elf32_Ehdr* src = (Elf32_Ehdr*) start; memcpy(header.e_ident, src->e_ident, 16); header.e_type = DeendianUInt16(endian, src->e_type); header.e_machine = DeendianUInt16(endian, src->e_machine); header.e_version = DeendianUInt32(endian, src->e_version); header.e_entry = DeendianUInt32(endian, src->e_entry); header.e_phoff = DeendianUInt32(endian, src->e_phoff); header.e_shoff = DeendianUInt32(endian, src->e_shoff); header.e_flags = DeendianUInt32(endian, src->e_flags); header.e_ehsize = DeendianUInt16(endian, src->e_ehsize); header.e_phentsize = DeendianUInt16(endian, src->e_phentsize); header.e_phnum = DeendianUInt16(endian, src->e_phnum); header.e_shentsize = DeendianUInt16(endian, src->e_shentsize); header.e_shnum = DeendianUInt16(endian, src->e_shnum); header.e_shstrndx = DeendianUInt16(endian, src->e_shstrndx); } /******************************************************************************/ void ElfFormat32::TrimUnwantedELFHeaders( Elf32ProgramHeader& prgHeader, uint8_t* elfStart) { /* The GNU linkers sometimes put an extraneous ELF header into the beginning the of some Program segments.This messes up what is put in memory, so get rid of those headers by changing the Program header info. */ // Ignore any zero length program sections. if( prgHeader.p_filesz == 0 ) return; // Ignore if program section does not have a redundant copy if the ELF file header if( memcmp( prgHeader.data, ELFMAG, 4 ) ) return; Elf32SectionHdr_t foundSection; bool isFoundSection = false; /* Now loop through all of the Sections headers looking for the lowest addressed one the fits within the program section. */ for(uint32_t index = 0; index < sectionHdrEntryCount; ++index ) { Elf32SectionHdr_t sectionHdr(sectionHdrTbl[index]); /* Does this section have bits defined by the program (i.e., the GNU tools), and the bit will actually occupy space in the target memory? */ if( ( sectionHdr.sh_type == xSHT_PROGBITS ) && ( sectionHdr.sh_flags & xSHF_ALLOC ) ) { // If this section is mapped to within this program section, then keep it if( ( sectionHdr.sh_addr >= prgHeader.p_vaddr ) && ( sectionHdr.sh_addr + sectionHdr.sh_size <= prgHeader.p_paddr + prgHeader.p_filesz ) ) { // Save section if this is the first, or it is lowest in memory order. if( isFoundSection == false || sectionHdr.sh_addr < foundSection.sh_addr) { foundSection = sectionHdr; isFoundSection = true; } } } } // Did we NOT find any sections that fit with this program section? if( isFoundSection == false ) { /* This is a completely superfluous program section that the idiot compiler tools decided to add! Trim this program section down to nothing. */ prgHeader.p_filesz = 0; prgHeader.p_memsz = 0; } else { /* The superfluous ELF header may overlap part of the saved section. So, copy the contents of the saved section back into the program section. */ uint32_t skipByteCount = foundSection.sh_addr - prgHeader.p_vaddr; //memmove( prgHeader.data, elfStart + foundSection.sh_offset, foundSection.sh_size ); /* Trim off the beginning of the program section, up to the first real data byte from the saved section. */ prgHeader.p_offset += skipByteCount; prgHeader.p_paddr += skipByteCount; prgHeader.p_vaddr += skipByteCount; prgHeader.p_filesz -= skipByteCount; prgHeader.p_memsz -= skipByteCount; memmove( prgHeader.data, elfStart + prgHeader.p_offset, prgHeader.p_filesz ); } } /******************************************************************************/ ElfFormat64::ElfFormat64(uint8_t* start) : sectionHdrTbl(NULL) { endian = (Endianness::Type) ((Elf64_Ehdr*)start)->e_ident[EI_DATA]; DeendianELFHdr(start); /* Get the header's size. For completeness, tell upper layers that we only have one record. */ elfHdrEntryCount = 1; if( ELFHdrEntrySize() != sizeof( Elf64_Ehdr ) ) { LOG_DEBUG(DEBUG_STAMP, "ELF Header size wrong - %d, actual size - %d", ELFHdrEntrySize(), sizeof(Elf64_Ehdr)); LOG_ERROR("ELF Parsing Error !!!\n Wrong Header Size"); } if ( memcmp( header.e_ident, ELFMAG, 4 ) != 0 ) { LOG_DEBUG(DEBUG_STAMP, "ELF magic identification word wrong"); LOG_ERROR("ELF Parsing Error !!!\n ELF magic identification word wrong"); } /* If a Section header is defined, get its pointer and its record size count. Otherwise, default it to NULL. */ if( header.e_shoff == 0 ) { sectionHdrTbl = NULL; sectionHdrEntrySize = 0; sectionHdrEntryCount = 0; } else { sectionHdrTbl = (Elf64SectionHdr_t *)(start + header.e_shoff ); sectionHdrEntrySize = header.e_shentsize; sectionHdrEntryCount = header.e_shnum; /* Now loop through all of the Sections headers and replace indexes with properly endianized values. */ for( unsigned int index = 0; index < sectionHdrEntryCount; ++index ) { /* Convert the header's endian type into the native endian type of the machine we're running on. */ sectionHdrTbl[index].Deendian(endian); } // Replace the in-file Sections headers, with a out-of-file copy. Elf64SectionHdr_t *tempsectionHdrTbl = (Elf64SectionHdr_t*) malloc( sectionHdrEntrySize *sectionHdrEntryCount ); memmove( tempsectionHdrTbl, sectionHdrTbl, sectionHdrEntrySize * sectionHdrEntryCount ); sectionHdrTbl = tempsectionHdrTbl; // If we have a String Table Section, save a pointer to the String Table Section data. if( header.e_shstrndx == 0 ) { stringTableSection = NULL; stringTableSectionSize = 0; } else { /* Index from the beginning of the ELF file with the offset index in the String Table Section. */ stringTableSection = (StringTableSectionTbl *)(start+ sectionHdrTbl[header.e_shstrndx].sh_offset ); stringTableSectionSize = sectionHdrTbl[header.e_shstrndx].sh_size; } uint64_t dataSecAddr = 0; uint64_t dataSecOff = 0; for(unsigned int index = 0; index < sectionHdrEntryCount; index++) { stringTableSection = (StringTableSectionTbl *)(start + sectionHdrTbl[header.e_shstrndx].sh_offset); char* name = (char*) stringTableSection; std::string sectn = name + sectionHdrTbl[index].sh_name; if(sectn == ".data") { dataSecAddr = sectionHdrTbl[index].sh_addr; dataSecOff = sectionHdrTbl[index].sh_offset; } if(sectionHdrTbl[index].sh_type == SHT_SYMTAB) { symbolTableSection = (Elf64Symbol_t *)((char *)start + sectionHdrTbl[index].sh_offset); int count = sectionHdrTbl[index].sh_size / sectionHdrTbl[index].sh_entsize; char *symbol_names = (char *)(start + sectionHdrTbl[sectionHdrTbl[index].sh_link].sh_offset); for (int symb = 0; symb < count; symb++) { std::string name = symbol_names + symbolTableSection[symb].st_name; if(name == "bif_atf_handoff_params") { atf_handoff_params_found = true; uint64_t symbValue = symbolTableSection[symb].st_value; uint64_t offset = symbValue - dataSecAddr; atf_handoff_params_offset = dataSecOff + offset; } } } } } /* If a Program header is defined, get its pointer and its record size count. Otherwise, default it to NULL. */ if( header.e_phoff == 0 ) { programHdrEntrySize = 0; programHdrEntryCount = 0; } else { programHdrEntrySize = header.e_phentsize; programHdrEntryCount = header.e_phnum; /* Now loop through all of the Program headers and replace indexes with properly endianized values. */ Elf64_Addr currentProgramPhysicalAddresses = 0; uint64_t countProgramPhysicalAddresses = 0; uint8_t* ptr = (start + header.e_phoff ); for(unsigned int index = 0; index < programHdrEntryCount; ++index, ptr += header.e_phentsize ) { Elf64ProgramHeader& prgHdr(* new Elf64ProgramHeader(endian, ptr)); programHeaders.push_back(&prgHdr); /* Now, put the Program section's data in a separate buffer to keep separate from the in-memory ELF data. */ prgHdr.data = new uint8_t[prgHdr.p_filesz]; memcpy( prgHdr.data,( start + prgHdr.p_offset ),prgHdr.p_filesz); if((atf_handoff_params_offset >= prgHdr.p_offset) && (atf_handoff_params_offset <= (prgHdr.p_offset + prgHdr.p_filesz))) { atf_handoff_params_offset -= prgHdr.p_offset; atf_handoff_params_prg_hdr_count = index; } if( index == 0 ) { // Capture the first physical address. currentProgramPhysicalAddresses = prgHdr.p_paddr; countProgramPhysicalAddresses = 1; } else { // Count the remaining physical address that are the same as the first one. if( currentProgramPhysicalAddresses == prgHdr.p_paddr ) { countProgramPhysicalAddresses += 1; } } } if( countProgramPhysicalAddresses == programHdrEntryCount ) { useLogicalLoadAddress = true; // replace the physical address values with the virtual addresses. for( unsigned int index = 0; index < programHdrEntryCount; ++index ) { programHeaders[index]->p_paddr = programHeaders[index]->p_vaddr; } } for(unsigned int index = 0; index < programHdrEntryCount; ++index ) { Elf64ProgramHeader& prgHdr(*programHeaders[index]); TrimUnwantedELFHeaders( prgHdr, start ); if( prgHdr.p_filesz > 0 ) { if( prgHdr.p_paddr < lowestProgramAddress ) lowestProgramAddress = prgHdr.p_paddr; if( ( ( prgHdr.p_paddr + prgHdr.p_filesz ) - 1 ) > highestProgramAddress ) highestProgramAddress = ( prgHdr.p_paddr + prgHdr.p_filesz - 1 ); } } } } /******************************************************************************/ ElfFormat64::~ElfFormat64() { uint32_t index; if(sectionHdrTbl) { free (sectionHdrTbl); sectionHdrTbl = 0; } for( index = 0; index < programHdrEntryCount; ++index ) { if (programHeaders[index]->data) { delete[] programHeaders[index]->data; } } } /******************************************************************************/ void ElfFormat64::DeendianELFHdr( uint8_t* start) { Elf64_Ehdr* src = (Elf64_Ehdr*) start; memcpy(header.e_ident, src->e_ident, 16); header.e_type = DeendianUInt16(endian, src->e_type); header.e_machine = DeendianUInt16(endian, src->e_machine); header.e_version = DeendianUInt32(endian, src->e_version); header.e_entry = DeendianUInt64(endian, src->e_entry); header.e_phoff = DeendianUInt64(endian, src->e_phoff); header.e_shoff = DeendianUInt64(endian, src->e_shoff); header.e_flags = DeendianUInt32(endian, src->e_flags); header.e_ehsize = DeendianUInt16(endian, src->e_ehsize); header.e_phentsize = DeendianUInt16(endian, src->e_phentsize); header.e_phnum = DeendianUInt16(endian, src->e_phnum); header.e_shentsize = DeendianUInt16(endian, src->e_shentsize); header.e_shnum = DeendianUInt16(endian, src->e_shnum); header.e_shstrndx = DeendianUInt16(endian, src->e_shstrndx); } /******************************************************************************/ void ElfFormat64::TrimUnwantedELFHeaders(Elf64ProgramHeader& prgHeader, uint8_t* elfStart) { /* The GNU linkers sometimes put an extraneous ELF header into the beginning the of some Program segments. This messes up what is put in memory, so get rid of those headers by changing the Program header info. */ // Ignore any zero length program sections. if( prgHeader.p_filesz == 0 ) return; // Ignore if program section does not have a redundant copy if the ELF file header if( memcmp( prgHeader.data, ELFMAG, 4 ) ) return; Elf64SectionHdr_t foundSection; bool isFoundSection = false; /* Now loop through all of the Sections headers looking for the lowest addressed one the fits within the program section. */ for(uint32_t index = 0; index < sectionHdrEntryCount; ++index ) { Elf64SectionHdr_t sectionHdr(sectionHdrTbl[index]); /* Does this section have bits defined by the program (i.e., the GNU tools), and the bit will actually occupy space in the target memory? */ if( ( sectionHdr.sh_type == xSHT_PROGBITS ) && ( sectionHdr.sh_flags & xSHF_ALLOC ) ) { // If this section is mapped to within this program section, then keep it if( ( sectionHdr.sh_addr >= prgHeader.p_vaddr ) && ( sectionHdr.sh_addr + sectionHdr.sh_size <= prgHeader.p_paddr + prgHeader.p_filesz ) ) { // Save section if this is the first, or it is lowest in memory order. if( isFoundSection == false || sectionHdr.sh_addr < foundSection.sh_addr) { foundSection = sectionHdr; isFoundSection = true; } } } } // Did we NOT find any sections that fit with this program section? if( isFoundSection == false ) { /* This is a completely superfluous program section that the idiot compiler tools decided to add! Trim this program section down to nothing. */ prgHeader.p_filesz = 0; prgHeader.p_memsz = 0; } else { /* The superfluous ELF header may overlap part of the saved section. So, copy the contents of the saved section back into the program section. */ uint64_t skipByteCount = foundSection.sh_addr - prgHeader.p_vaddr; /* Trim off the beginning of the program section, up to the first real data byte from the saved section. */ prgHeader.p_offset += skipByteCount; prgHeader.p_paddr += skipByteCount; prgHeader.p_vaddr += skipByteCount; prgHeader.p_filesz -= skipByteCount; prgHeader.p_memsz -= skipByteCount; memmove( prgHeader.data, elfStart + prgHeader.p_offset, prgHeader.p_filesz ); } } /******************************************************************************/ ElfFormat* ElfFormat::GetElfFormat(ElfClass::Type elfClass, uint8_t* start, uint8_t* state) { if(elfClass == ElfClass::ELFCLASS64) { *state = (A53ExecState::Type)A53ExecState::AARCH64; return new ElfFormat64(start); } /* ELF32 may contain either ARMv7/AArch32 or AArch64 using the ILP32 data model */ else if (((Elf32_Ehdr*)start)->e_machine != 0x28) { *state = (A53ExecState::Type)A53ExecState::AARCH64; return new ElfFormat32(start); } else { *state = (A53ExecState::Type)A53ExecState::AARCH32; return new ElfFormat32(start); } } /******************************************************************************/ Program_p_flags ElfFormat32::GetProgramHeaderFlags(uint8_t index) { return programHeaders[index]->Flags(); } /******************************************************************************/ Program_p_type ElfFormat32::GetProgramHeaderType(uint8_t index) { return programHeaders[index]->Type(); } /******************************************************************************/ Binary::Length_t ElfFormat32::GetProgramHeaderFileSize(uint8_t index) { return (uint32_t)programHeaders[index]->p_filesz; } /******************************************************************************/ Binary::Address_t ElfFormat32::GetStartUpAddress(void) { return (Binary::Address_t)header.e_entry; } /******************************************************************************/ Binary::Address_t ElfFormat32::GetPhysicalAddress(uint8_t index) { return (Binary::Address_t)programHeaders[index]->p_paddr; } /******************************************************************************/ uint8_t* ElfFormat32::GetProgramHeaderData(uint8_t index) { return programHeaders[index]->data; } /******************************************************************************/ Program_p_flags ElfFormat64::GetProgramHeaderFlags(uint8_t index) { return programHeaders[index]->Flags(); } /******************************************************************************/ Program_p_type ElfFormat64::GetProgramHeaderType(uint8_t index) { return programHeaders[index]->Type(); } /******************************************************************************/ Binary::Length_t ElfFormat64::GetProgramHeaderFileSize(uint8_t index) { return (uint32_t)programHeaders[index]->p_filesz; } /******************************************************************************/ Binary::Address_t ElfFormat64::GetStartUpAddress(void) { return (Binary::Address_t)header.e_entry; } /******************************************************************************/ Binary::Address_t ElfFormat64::GetPhysicalAddress(uint8_t index) { return (Binary::Address_t)programHeaders[index]->p_paddr; } /******************************************************************************/ uint8_t* ElfFormat64::GetProgramHeaderData(uint8_t index) { return programHeaders[index]->data; } xilinx-bootgen-2024.2/elftools.h000077500000000000000000000351411475706442400165750ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _ELFTOOLS_H_ #define _ELFTOOLS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include "bootgenenum.h" #include "logger.h" /* This is a "standard" header file */ #include "elf.h" /* Forward Class Declarations */ class Elf32SectionHdr_t; class Elf64SectionHdr_t; class Elf64Symbol_t; #define DATA_ID_PARTITION_HASHES 3 #define DATA_ID_STRUCT_INFO 2 #define DATA_ID_XPLM_MODULES 1 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef char* StringTableSectionTbl[]; struct DataFileSectionType; uint32_t DeendianUInt32(Endianness::Type endianData, uint32_t data32); uint64_t DeendianUInt64(Endianness::Type endianData, uint64_t data64); Endianness::Type EndianMachine(void); /* ------------------------------------------------------------------------------- ***************************** E N U M E R A T E D D A T A T Y P E S *** ------------------------------------------------------------------------------- */ /* p-type */ typedef enum { xPT_NULL = 0, xPT_LOAD = 1, xPT_DYNAMIC = 2, xPT_INTERP = 3, xPT_NOTE = 4, xPT_SHLIB = 5, xPT_PHDR = 6, xPT_NUM = 7, xPT_LOPROC = 0x70000000, xPT_HIPROC = 0x7FFFFFFF } Program_p_type; /* p-flags */ typedef enum { xPF_R = 0x4, xPF_W = 0x2, xPF_X = 0x1, xPF_MASKPROC = 0xF0000000 } Program_p_flags; /* sh_type */ typedef enum Section_sh_s { xSHT_NULL = 0, xSHT_PROGBITS = 1, xSHT_SYMTAB = 2, xSHT_STRTAB = 3, xSHT_RELA = 4, xSHT_HASH = 5, xSHT_DYNAMIC = 6, xSHT_NOTE = 7, xSHT_NOBITS = 8, xSHT_REL = 9, xSHT_SHLIB = 10, xSHT_DYNSYM = 11, xSHT_NUM = 12, xSHT_LOSUNW = 0x6FFFFFFD, xSHT_SUNW_verdef = 0x6FFFFFFD, xSHT_SUNW_verneed = 0x6FFFFFFE, xSHT_SUNW_versym = 0x6FFFFFFF, xSHT_HISUNW = 0x6FFFFFFF, xSHT_LOPROC = 0x70000000, xSHT_HIPROC = 0x7FFFFFFF, xSHT_LOUSER = 0x80000000, xSHT_HIUSER = 0xFFFFFFFF } Section_sh_type; /* sh_flags */ typedef enum Section_sh_flags_s { xSHF_WRITE = 0x00000001, xSHF_ALLOC = 0x00000002, xSHF_EXECINSTR = 0x00000004, xSHF_FLAGMASK = 0x00000007, xSHF_MASKPROC = 0xF0000000 } Section_sh_flags; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Elf32ProgramHeader { public: Elf32ProgramHeader(Endianness::Type endian, uint8_t* ptr) : data(0) { uint32_t* origData = (uint32_t*) ptr; p_type = DeendianUInt32(endian, *origData++); p_offset = DeendianUInt32(endian, *origData++); p_vaddr = DeendianUInt32(endian, *origData++); p_paddr = DeendianUInt32(endian, *origData++); p_filesz = DeendianUInt32(endian, *origData++); p_memsz = DeendianUInt32(endian, *origData++); p_flags = DeendianUInt32(endian, *origData++); p_align = DeendianUInt32(endian, *origData++); } Elf32_Word p_type; /* entry type */ Elf32_Off p_offset; /* file offset */ Elf32_Addr p_vaddr; /* virtual address */ Elf32_Addr p_paddr; /* physical address */ Elf32_Word p_filesz; /* file size */ Elf32_Word p_memsz; /* memory size */ Elf32_Word p_flags; /* entry flags */ Elf32_Word p_align; /* memory/file alignment */ uint8_t* data; Program_p_type Type() { return (Program_p_type) p_type; } Program_p_flags Flags() { return (Program_p_flags) p_flags; } }; /******************************************************************************/ class Elf64ProgramHeader { public: Elf64ProgramHeader(Endianness::Type endian, uint8_t* ptr) : data(0) { uint32_t* origData = (uint32_t*)ptr; p_type = DeendianUInt32(endian, *(origData++)); p_flags = DeendianUInt32(endian, *(origData++)); uint64_t lsb = (uint64_t)*(origData++); p_offset = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); lsb = (uint64_t)*(origData++); p_vaddr = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); lsb = (uint64_t)*(origData++); p_paddr = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); lsb = (uint64_t)*(origData++); p_filesz = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); lsb = (uint64_t)*(origData++); p_memsz = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); lsb = (uint64_t)*(origData++); p_align = DeendianUInt64(endian, (lsb | (uint64_t)*(origData++) << 32)); } Elf64_Word p_type; /* entry type 32-bit*/ Elf32_Word p_flags; /* entry flags 32-bit*/ Elf64_Off p_offset; /* file offset 64-bit*/ Elf64_Addr p_vaddr; /* virtual address 64-bit*/ Elf64_Addr p_paddr; /* physical address 64-bit*/ Elf64_Xword p_filesz; /* file size 64-bit*/ Elf64_Xword p_memsz; /* memory size 64-bit*/ Elf64_Xword p_align; /* memory/file alignment 64-bit*/ uint8_t* data; Program_p_type Type() { return (Program_p_type) p_type; } Program_p_flags Flags() { return (Program_p_flags) p_flags; } }; /******************************************************************************/ class ElfFormat { public: ElfFormat() : elfHdrEntryCount(0) , useLogicalLoadAddress(false) , programHdrEntrySize(0) , programHdrEntryCount(0) , sectionHdrEntrySize(0) , sectionHdrEntryCount(0) , stringTableSection(NULL) , stringTableSectionSize(0) , lowestProgramAddress(0xFFFFFFFF) , highestProgramAddress(0) , endian(Endianness::NotEndian) , atf_handoff_params_offset(0) , atf_handoff_params_prg_hdr_count(0) , atf_handoff_params_found(false) , iht_optional_data_size(0) , iht_optional_data(NULL) , xplm_modules_data(NULL) , xplm_modules_data_size(0) { }; ~ElfFormat() {}; static ElfFormat* GetElfFormat(ElfClass::Type elfClass, uint8_t* start, uint8_t* state); virtual Program_p_flags GetProgramHeaderFlags(uint8_t index) = 0; virtual Program_p_type GetProgramHeaderType(uint8_t index) = 0; virtual Binary::Length_t GetProgramHeaderFileSize(uint8_t index) = 0; virtual Binary::Address_t GetStartUpAddress(void) = 0; virtual Binary::Address_t GetPhysicalAddress(uint8_t index) = 0; virtual uint8_t* GetProgramHeaderData(uint8_t index) = 0; Endianness::Type endian; uint32_t elfHdrEntryCount; bool useLogicalLoadAddress; uint32_t programHdrEntrySize; uint32_t programHdrEntryCount; uint32_t sectionHdrEntrySize; uint32_t sectionHdrEntryCount; StringTableSectionTbl* stringTableSection; uint64_t stringTableSectionSize; uint64_t lowestProgramAddress; uint64_t highestProgramAddress; uint32_t* iht_optional_data; uint32_t* xplm_modules_data; uint32_t xplm_modules_data_size; uint16_t iht_optional_data_size; uint64_t atf_handoff_params_offset; uint64_t atf_handoff_params_prg_hdr_count; bool atf_handoff_params_found; }; /*************************************************************************************/ class Elf32Symbol_t { public: Elf32Symbol_t() {} Elf32Symbol_t(Elf32Symbol_t* sym_t) { st_name = sym_t->st_name; st_info = sym_t->st_info; st_other = sym_t->st_other; st_shndx = sym_t->st_shndx; st_value = sym_t->st_value; st_size = sym_t->st_size; } Elf32_Word st_name; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; Elf32_Addr st_value; Elf32_Xword st_size; }; /******************************************************************************/ class ElfFormat32 : public ElfFormat { public: ElfFormat32(uint8_t* start); ~ElfFormat32(); Program_p_flags GetProgramHeaderFlags(uint8_t index); Program_p_type GetProgramHeaderType(uint8_t index); Binary::Length_t GetProgramHeaderFileSize(uint8_t index); Binary::Address_t GetStartUpAddress(void); Binary::Address_t GetPhysicalAddress(uint8_t index); uint8_t* GetProgramHeaderData(uint8_t index); uint32_t ELFHdrEntrySize() { return header.e_ehsize;} Elf32_Ehdr header; std::vector programHeaders; Elf32SectionHdr_t* sectionHdrTbl; Elf32Symbol_t* symbolTableSection; private: void TrimUnwantedELFHeaders( Elf32ProgramHeader& prgHeader, uint8_t* elfStart ); void DeendianELFHdr(uint8_t*); }; /******************************************************************************/ class ElfFormat64 : public ElfFormat { public: ElfFormat64(uint8_t* start); ~ElfFormat64(); Program_p_flags GetProgramHeaderFlags(uint8_t index); Program_p_type GetProgramHeaderType(uint8_t index); Binary::Length_t GetProgramHeaderFileSize(uint8_t index); Binary::Address_t GetStartUpAddress(void); Binary::Address_t GetPhysicalAddress(uint8_t index); uint8_t* GetProgramHeaderData(uint8_t index); uint32_t ELFHdrEntrySize() { return header.e_ehsize;} Elf64_Ehdr header; std::vector programHeaders; Elf64SectionHdr_t* sectionHdrTbl; Elf64Symbol_t* symbolTableSection; private: void TrimUnwantedELFHeaders( Elf64ProgramHeader& prgHeader, uint8_t* elfStart ); void DeendianELFHdr(uint8_t*); }; /******************************************************************************/ class Elf32SectionHdr_t { public: Elf32SectionHdr_t() {} Elf32SectionHdr_t(Elf32SectionHdr_t* secHdr) { sh_name = secHdr->sh_name; sh_type = secHdr->sh_type; sh_flags = secHdr->sh_flags; sh_addr = secHdr->sh_addr; sh_offset = secHdr->sh_offset; sh_size = secHdr->sh_size; sh_link = secHdr->sh_link; sh_info = secHdr->sh_info; sh_addralign = secHdr->sh_addralign; sh_entsize = secHdr->sh_entsize; } Elf32_Word sh_name; /* section name */ Elf32_Word sh_type; /* SHT_... */ Elf32_Word sh_flags; /* SHF_... */ Elf32_Addr sh_addr; /* virtual address */ Elf32_Off sh_offset; /* file offset */ Elf32_Word sh_size; /* section size */ Elf32_Word sh_link; /* misc info */ Elf32_Word sh_info; /* misc info */ Elf32_Word sh_addralign; /* memory alignment */ Elf32_Word sh_entsize; /* entry size if table */ Section_sh_type Type() { return (Section_sh_type)sh_type; } void Deendian(Endianness::Type endian ) { sh_name = DeendianUInt32(endian, sh_name); sh_type = DeendianUInt32(endian, sh_type); sh_flags = DeendianUInt32(endian, sh_flags); sh_addr = DeendianUInt32(endian, sh_addr); sh_offset = DeendianUInt32(endian, sh_offset); sh_size = DeendianUInt32(endian, sh_size); sh_link = DeendianUInt32(endian, sh_link); sh_info = DeendianUInt32(endian, sh_info); sh_addralign = DeendianUInt32(endian, sh_addralign); sh_entsize = DeendianUInt32(endian, sh_entsize); } }; /******************************************************************************/ class Elf64SectionHdr_t { public: Elf64SectionHdr_t() {} Elf64SectionHdr_t(Elf64SectionHdr_t* secHdr) { sh_name = secHdr->sh_name; sh_type = secHdr->sh_type; sh_flags = secHdr->sh_flags; sh_addr = secHdr->sh_addr; sh_offset = secHdr->sh_offset; sh_size = secHdr->sh_size; sh_link = secHdr->sh_link; sh_info = secHdr->sh_info; sh_addralign = secHdr->sh_addralign; sh_entsize = secHdr->sh_entsize; } Elf64_Word sh_name; /* section name */ Elf64_Word sh_type; /* SHT_... */ Elf64_Xword sh_flags; /* SHF_... */ Elf64_Addr sh_addr; /* virtual address */ Elf64_Off sh_offset; /* file offset */ Elf64_Xword sh_size; /* section size */ Elf64_Word sh_link; /* misc info */ Elf64_Word sh_info; /* misc info */ Elf64_Xword sh_addralign; /* memory alignment */ Elf64_Xword sh_entsize; /* entry size if table */ Section_sh_type Type() { return (Section_sh_type)sh_type; } void Deendian(Endianness::Type endian ) { sh_name = DeendianUInt32(endian, sh_name); sh_type = DeendianUInt32(endian, sh_type); sh_flags = DeendianUInt64(endian, sh_flags); sh_addr = DeendianUInt64(endian, sh_addr); sh_offset = DeendianUInt64(endian, sh_offset); sh_size = DeendianUInt64(endian, sh_size); sh_link = DeendianUInt32(endian, sh_link); sh_info = DeendianUInt32(endian, sh_info); sh_addralign = DeendianUInt64(endian, sh_addralign); sh_entsize= DeendianUInt64(endian, sh_entsize); } }; /*************************************************************************************/ class Elf64Symbol_t { public: Elf64Symbol_t() {} Elf64Symbol_t(Elf64Symbol_t* sym_t) { st_name = sym_t->st_name; st_info = sym_t->st_info; st_other = sym_t->st_other; st_shndx = sym_t->st_shndx; st_value = sym_t->st_value; st_size = sym_t->st_size; } Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; }; #endif xilinx-bootgen-2024.2/elftypes.h000077500000000000000000000030501475706442400165730ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _ELFTYPES_H_ #define _ELFTYPES_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include /* ELF 32-bit */ typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Xword; typedef uint32_t Elf32_Word; /* ELF 64-bit */ typedef uint64_t Elf64_Addr; typedef uint64_t Elf64_Off; typedef int64_t Elf64_Sxword; typedef uint64_t Elf64_Xword; typedef int32_t Elf32_Sword; typedef uint32_t Elf64_Word; typedef uint16_t Elf64_Half; #endif xilinx-bootgen-2024.2/encryption-versal.cpp000077500000000000000000001546631475706442400210000ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "encryption-versal.h" #include "bootimage.h" #include "encryptutils.h" #include "options.h" #include "imageheadertable-versal.h" #include "partitionheadertable-versal.h" #include /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalEncryptionContext::VersalEncryptionContext() : isBootloader(false) , aesSeedexits(false) , isPmcData(false) { encryptionAlgorithm = new AesGcmEncryptionContext(); }; /******************************************************************************/ VersalEncryptionContext::VersalEncryptionContext(const EncryptionContext* other) : isBootloader(false) , aesSeedexits(false) , isPmcData(false) { aesFilename = other->aesFilename; encryptionAlgorithm = new AesGcmEncryptionContext(); } /******************************************************************************/ VersalEncryptionContext::~VersalEncryptionContext() { if (encryptionAlgorithm != NULL) { delete[] encryptionAlgorithm; } } /******************************************************************************/ void VersalEncryptionContext::SetAesKey(const uint8_t* key) { aesKey = new uint32_t[WORDS_PER_AES_KEY]; for (uint32_t index = 0; index < WORDS_PER_AES_KEY; index++) { aesKey[index] = ReadBigEndian32(key); key += sizeof(uint32_t); } } /******************************************************************************/ void VersalEncryptionContext::SetAesSeedString(const std::string& key) { uint8_t hexData[256]; if (key.size() != (WORDS_PER_AES_KEY * 8)) { LOG_DEBUG(DEBUG_STAMP, "Seed size - %d", key.size()); LOG_ERROR("An AES Seed must be 256 bits long - %s", key.c_str()); } PackHex(key, hexData); SetAesSeed(hexData); } /******************************************************************************/ void VersalEncryptionContext::GenerateAesKey(void) { uint32_t keysize = WORDS_PER_AES_KEY * sizeof(uint32_t); uint8_t newKey[BYTES_PER_AES_KEY]; RAND_bytes(newKey, keysize); SetAesKey(newKey); LOG_INFO("AES Key generated successfully"); } /******************************************************************************/ void VersalEncryptionContext::GetEncryptionKeys(Options& options, uint8_t* aesKey, uint8_t* aesOptKey, uint8_t* aesIV) { const uint32_t* tmpKey = GetAesKey(); if (tmpKey != NULL) { memcpy_be(aesKey, tmpKey, AES_GCM_KEY_SZ); } else { LOG_ERROR("Encryption Error !!!\n Key 0 does not exist in the AES key file "); } const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { memcpy_be(aesIV, tmpIv, AES_GCM_IV_SZ); } else { LOG_ERROR("IV does not exist in the AES key file "); } } /******************************************************************************/ void VersalEncryptionContext::WriteEncryptionKeyFile(const std::string & baseFileName, bool useOptionalKey, uint32_t blocks) { uint32_t x, y, index; /* Setup the file for writing */ std::string ext = StringUtils::GetExtension(baseFileName); std::string filename; if (ext == "") { filename = baseFileName + ".nky"; } else { filename = baseFileName; } std::ofstream keyFile(filename.c_str()); if (!keyFile) { LOG_ERROR("Failure writing AES key file", filename.c_str()); } /* Write device name */ if (deviceName != "") { keyFile << "Device " << deviceName << ";\n"; keyFile << "\n"; } /* Ko can then be used for key/iv pairs */ for (x = 0; x> word; if (word == "") { return; } char c = ' '; if (word == "Device") { word = ""; keyFile >> word; c = word[word.size() - 1]; word.erase(word.size() - 1); deviceName = word; } else if (word == "Key") { keyFile >> word; if (word == "Opt") { LOG_ERROR("The key word 'Key Opt' is not supported in VERSAL architecture"); } if (word != "" && isalnum(word[0])) { /* Second Word is "0" or "1" or "2" ...*/ int index = std::stoi(word); if (aesKeyNum != index) { LOG_DEBUG(DEBUG_STAMP, "Key order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesKeyNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (aesKeyVec.size() == 0) { SetAesKeyString(word); } aesKeyVec.push_back(word); } else { /* Second Word other than "0", - throw error */ LOG_DEBUG(DEBUG_STAMP, "Unknown key type - '%s' in %s", word.c_str(), inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } } else if (word == "IV") { keyFile >> word; if (word != "") { if (word.size() == ((BYTES_PER_IV * 2) + 1)) { c = word[word.size() - 1]; word.erase(word.size() - 1); SetIvString(word); } else { int index = std::stoi(word); if (aesIvNum != index) { LOG_DEBUG(DEBUG_STAMP, "Iv order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesIvNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (aesIvVec.size() == 0) { SetIvString(word); } } } aesIvVec.push_back(word); } else if (word == "Seed") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } SetAesSeedString(word); aesSeedexits = true; } else if (word == "Label") { LOG_ERROR("The input 'Label' is deprecated.\n\t Please construct a FixedInputData of 60 Bytes instead and provide the same in the nky file.This will be used along with Seed in KDF."); } else if (word == "Context") { LOG_ERROR("The input 'Context' is deprecated.\n\t Please construct a FixedInputData of 60 Bytes instead and provide the same in the nky file.This will be used along with Seed in KDF."); } else if (word == "FixedInputData") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } SetAesFixedInputDataString(word); fixedInputDataExits = true; } else { /* If the word is neither of the above */ LOG_DEBUG(DEBUG_STAMP, "'Key' or 'Device' identifier expected, '%s' found instead", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if (c != ';') { /* Semicolons expected at end of every line */ while ((keyFile >> c) && isspace(c)) { word.push_back(c); } } if (c != ';') { LOG_DEBUG(DEBUG_STAMP, "Terminating ';' expected. Last word read was '%s'", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if (deviceName == "") { LOG_DEBUG(DEBUG_STAMP, "Partname 'Device' missing in the key file - %s", inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if ((aesKeyVec.size() > 1 || aesIvVec.size() > 1) && aesSeedexits) { LOG_ERROR("Seed is not expected with multiple keys/Iv."); } if (fixedInputDataExits && !aesSeedexits) { LOG_ERROR("Seed must be specified along with FixedInputData."); } } } /******************************************************************************/ void VersalEncryptionContext::PackNextEncryptionKey(uint8_t* aesKeyNext, int aeskeyPtr) { uint8_t hexData[AES_GCM_KEY_SZ]; uint8_t* hexDataPtr = hexData; if (aesKeyVec[aeskeyPtr].length() != (WORDS_PER_AES_KEY * 8)) { LOG_DEBUG(DEBUG_STAMP, "AES key %d size - %d", aeskeyPtr, aesKeyVec[aeskeyPtr].length()); LOG_ERROR("An AES key must be 256 bits long - %s", aesKeyVec[aeskeyPtr].c_str()); } if (aesKeyVec[aeskeyPtr].length() & 1) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - does not have even no. of hex digits", aesKeyVec[aeskeyPtr].c_str()); LOG_ERROR("Error parsing encryption key"); } for (uint32_t i = 0; i No key0/iv0 mentioned. +1 to generate key0/IV0 for SH */ if ((aesKeyVec.size() == 0 || aesIvVec.size() == 0)) { blocks = options.bifOptions->GetEncryptionBlocksList().size() + 1; } else { blocks = options.bifOptions->GetEncryptionBlocksList().size(); } if (GetAesSeed() == NULL) { aesSeed = new uint32_t[WORDS_PER_AES_KEY]; memset(aesSeed, 0, WORDS_PER_AES_KEY); GenerateAesSeed(); } if (GetFixedInputData() == NULL) { fixedInputData = new uint32_t[WORDS_PER_FID]; memset(fixedInputData, 0, WORDS_PER_FID); GenerateAesFixedInputData(); } uint32_t outBufBytes = blocks * (AES_GCM_KEY_SZ + AES_GCM_IV_SZ); outBufKDF = new uint32_t[outBufBytes]; SetKdfLogFile(options.GetEncryptionDumpFlag()); uint32_t ret = kdf->CounterModeKDF(aesSeed, fixedInputData, fixedInputDataByteLength, outBufKDF, outBufBytes); if (ret != 0) { LOG_ERROR("Error generating encryption keys from Counter Mode KDF."); } uint8_t aesKeyNext[AES_GCM_KEY_SZ]; uint8_t aesIvNext[AES_GCM_IV_SZ]; for (x = 0; x < blocks; x++) { memcpy(aesKeyNext, &outBufKDF[(x * 11)], AES_GCM_KEY_SZ); if (aesKeyVec.size() < (options.bifOptions->GetEncryptionBlocksList().size() + 1)) { aesKeyVec.push_back(ConvertKeyIvToString(aesKeyNext, AES_GCM_KEY_SZ).c_str()); } if (GetAesKey() == NULL) { SetAesKey(aesKeyNext); } memcpy(aesIvNext, &outBufKDF[(x * 11) + WORDS_PER_AES_KEY], AES_GCM_IV_SZ); if (aesIvVec.size() < (options.bifOptions->GetEncryptionBlocksList().size() + 1)) { aesIvVec.push_back(ConvertKeyIvToString(aesIvNext, AES_GCM_IV_SZ).c_str()); } if (GetIv() == NULL) { SetIv(aesIvNext); } } } /******************************************************************************/ void VersalEncryptionContext::ChunkifyAndEncrypt(Options& options, const uint8_t *inBuf, uint32_t inLen, uint8_t *aad, uint32_t aad_len, uint8_t* outBuf, uint32_t& outLen) { std::vector blockList = options.bifOptions->GetEncryptionBlocksList(); uint8_t *aesIv = new uint8_t[AES_GCM_IV_SZ]; uint8_t *aesKey = new uint8_t[AES_GCM_KEY_SZ]; uint8_t *aesIVNext = new uint8_t[AES_GCM_IV_SZ]; uint8_t *aesKeyNext = new uint8_t[AES_GCM_KEY_SZ]; GetEncryptionKeys(options, aesKey, NULL, aesIv); GetNextKey(aesKeyNext, 1); GetNextIv(aesIVNext, 1); uint8_t secureHdr_in[AES_GCM_KEY_SZ + AES_GCM_IV_SZ + NUM_BYTES_PER_WORD]; /* Extract the first block size */ uint32_t nextBlkSize = (blockList.empty()) ? inLen : blockList[0]; nextBlkSize = (nextBlkSize > inLen) ? inLen : nextBlkSize + 0; /* Copy Key,IV used for encrypting next block to Secure Header*/ memcpy(secureHdr_in, aesKeyNext, AES_GCM_KEY_SZ); memcpy(secureHdr_in + AES_GCM_KEY_SZ, aesIVNext, AES_GCM_IV_SZ); /* Copy the word Size of Block 0 to Secure Header*/ WriteLittleEndian32(secureHdr_in + AES_GCM_KEY_SZ + AES_GCM_IV_SZ, nextBlkSize / NUM_BYTES_PER_WORD); int ct_len; uint8_t gcm_tag[AES_GCM_TAG_SZ]; /* Encrypt the Secure Header with device key and starting IV */ LOG_TRACE("Encrypting the Secure Header"); uint8_t* ptr = outBuf; AesGcm256Encrypt(secureHdr_in, SECURE_HDR_SZ, aesKey, aesIv, aad, aad_len, ptr, ct_len, gcm_tag); /* Attach the AES-GCM generated Hash Tag to end of the block */ memcpy(outBuf + ct_len, gcm_tag, AES_GCM_TAG_SZ); uint32_t outPtr = ct_len + AES_GCM_TAG_SZ; uint8_t secureHdr_out[1024]; int pt_len; uint32_t length = 0; if (options.GetEncryptionDumpFlag()) { uint32_t i = 0; VERBOSE_OUT << std::endl << " Secure Header"; VERBOSE_OUT << std::endl << " AES Key : "; for (i = 0; i blkPtr) ? blockList[blkPtr] : inLen - bytesWritten; nextBlkSize = ((nextBlkSize + bytesWritten) > inLen) ? (inLen - bytesWritten) : (nextBlkSize + 0); /* Get next key and IV - store in current block - use for next block */ if (nextBlkSize == 0) { memset(aesKeyNext, 0, AES_GCM_KEY_SZ); memset(aesIVNext, 0, AES_GCM_IV_SZ); } else { GetNextKey(aesKeyNext, blkPtr + 1); GetNextIv(aesIVNext, blkPtr + 1); } uint8_t *gcm_pt = new uint8_t[currBlkSize + AES_GCM_KEY_SZ + AES_GCM_IV_SZ + NUM_BYTES_PER_WORD]; /* Prepare the buffer for encryption - Actual block data + Next Block Key + Next Block IV + Next Block Word Size */ memcpy(gcm_pt, inBuf + inPtr, currBlkSize); inPtr += currBlkSize; memcpy(gcm_pt + currBlkSize, aesKeyNext, AES_GCM_KEY_SZ); memcpy(gcm_pt + currBlkSize + AES_GCM_KEY_SZ, aesIVNext, AES_GCM_IV_SZ); WriteLittleEndian32(gcm_pt + currBlkSize + AES_GCM_KEY_SZ + AES_GCM_IV_SZ, nextBlkSize / NUM_BYTES_PER_WORD); //Encrypt the consolidated block LOG_TRACE("Encrypting the block %d of size 0x%x", blkPtr, currBlkSize); AesGcm256Encrypt(gcm_pt, currBlkSize + SECURE_HDR_SZ, aesKey, aesIv, NULL, 0, outBuf + outPtr, ct_len, gcm_tag); memcpy(outBuf + outPtr + ct_len, gcm_tag, AES_GCM_TAG_SZ); uint8_t* inBuf_out = new uint8_t[ct_len + AES_GCM_TAG_SZ]; if (options.GetEncryptionDumpFlag()) { uint32_t i = 0; /*VERBOSE_OUT << std::endl << std::dec << "Unencrypted Bootimage Data - block-" << currBlk << " Length-" << (currBlkSize+SECURE_HDR_SZ) << std::endl; int size = currBlkSize+SECURE_HDR_SZ; for(i=0; i<(currBlkSize+SECURE_HDR_SZ); i++) VERBOSE_OUT << "0x" << std::setfill('0') << std::setw(2) << std::hex << uint32_t(gcm_pt[i]) << " "; VERBOSE_OUT << std::endl; */ VERBOSE_OUT << std::endl << " Block " << blkPtr - 1; VERBOSE_OUT << std::endl << " AES Key : "; for (i = 0; ipartition->section->Name.c_str()); std::vector encrBlocks = partHdr->imageHeader->GetEncrBlocksList(); uint32_t defEncrBlocks = partHdr->imageHeader->GetDefaultEncrBlockSize(); Binary::Length_t lastBlock = 0; uint32_t totalencrBlocks = 0; WarnforDPACMImpactonBootTime(encrBlocks.size() != 0, partHdr->imageHeader->GetDpacm() == DpaCM::DpaCMEnable); /* Default key rolling to make a chunk size of 32KB - Valid for any partition other than bootloader */ if (!partHdr->IsBootloader()) { totalencrBlocks = encrBlocks.size(); defEncrBlocks = 0; uint32_t overhead = (totalencrBlocks) * (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* Due to encryption over head, the actual default size on which the partition needs to be Key rolled is always less than 64KB. So first calculate the default key roll data size by substracting the overhead. */ /* Then calculate the number of such blocks possible on a given partition. */ /* Note that the last block will always be based on the partition length.*/ std::vector secureChunkEncrBlocks; uint32_t actualSecureChunkSize = bi.GetSecureChunkSize(partHdr->IsBootloader()) - overhead; if (partHdr->imageHeader->GetAuthenticationType() == Authentication::None && !partHdr->imageHeader->GetDelayAuthFlag()) { actualSecureChunkSize += SHA3_LENGTH_BYTES; } uint32_t totalKeyRollencrBlocks = GetTotalEncryptionBlocks(partHdr->partition->section->Length, secureChunkEncrBlocks, actualSecureChunkSize, &lastBlock); secureChunkEncrBlocks.clear(); for (uint32_t itr = 0; itr < totalKeyRollencrBlocks; itr++) { if ((itr == totalKeyRollencrBlocks - 1) && (lastBlock != 0)) { secureChunkEncrBlocks.push_back(lastBlock); lastBlock = 0; } else { secureChunkEncrBlocks.push_back(actualSecureChunkSize); } } /* Now chunk each default key roll data size, based on user encryption blocks. Note that the last block will always be based on the partition length.*/ options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr1 = 0; itr1 < totalKeyRollencrBlocks; itr1++) { if ((itr1 == totalKeyRollencrBlocks - 1) && (secureChunkEncrBlocks[itr1] != actualSecureChunkSize)) { Binary::Length_t encrBlocksSize = 0; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; if (secureChunkEncrBlocks[itr1] > encrBlocksSize) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } else { options.bifOptions->InsertEncryptionBlock(secureChunkEncrBlocks[itr1] - (encrBlocksSize - encrBlocks[itr])); break; } } } else { for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } } } totalencrBlocks = options.bifOptions->GetEncryptionBlocksList().size(); } else { totalencrBlocks = GetTotalEncryptionBlocks(partHdr->partition->section->Length, encrBlocks, defEncrBlocks, &lastBlock); options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < totalencrBlocks; itr++) { if (itr < encrBlocks.size()) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } else if (defEncrBlocks != 0) { options.bifOptions->InsertEncryptionBlock(defEncrBlocks); } else if ((itr == totalencrBlocks - 1) && (lastBlock != 0)) { options.bifOptions->InsertEncryptionBlock(lastBlock); } } } LOG_TRACE("Total no. of Key/IV pairs needed to encrypt - %d", totalencrBlocks + 1); /* Get the key file */ SetAesFileName(partHdr->partitionAesKeyFile); LOG_INFO("Key file - %s", aesFilename.c_str()); if (partHdr->generateAesKeyFile) { std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } GenerateEncryptionKeyFile(aesFilename, options); } else { LOG_ERROR("Key Generation Error !!!\n File - %s already exists.", aesFilename.c_str()); } } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); std::pair asesKeyandKeySrcPair (partHdr->imageHeader->GetEncryptionKeySrc(), aesKey); bi.aesKeyandKeySrc.push_back(asesKeyandKeySrcPair); bi.bifOptions->CheckForBadKeyandKeySrcPair(bi.aesKeyandKeySrc, aesFilename); options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, partHdr->partition->section->Name); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } } else { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } GenerateRemainingKeys(options); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), false); if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey != NULL) { memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } break; } } } // For copying SCR HDR IV into Boot Header const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { if (partHdr->IsBootloader()) { if (options.secHdrIv == NULL) { options.secHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(options.secHdrIv, tmpIv, BYTES_PER_IV); } if (partHdr->partitionSecHdrIv == NULL) { partHdr->partitionSecHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(partHdr->partitionSecHdrIv, tmpIv, BYTES_PER_IV); } uint32_t totalBlocksOverhead = (totalencrBlocks + 1) * 64; //64 = AES_GCM_IV_SZ+AES_GCM_KEY_SZ+NUM_BYTES_PER_WORD+AES_GCM_TAG_SZ if (!Binary::CheckAddress(partHdr->partition->section->Length)) { LOG_ERROR("Partition too large to encrypt"); } isBootloader = partHdr->imageHeader->IsBootloader(); if (options.GetEncryptionDumpFlag()) { bi.options.aesLogFile.open(bi.options.aesLogFilename, std::fstream::app); VERBOSE_OUT << std::endl << "------------------------------------"; VERBOSE_OUT << std::endl << " Partition Name : " << partHdr->partition->section->Name; VERBOSE_OUT << std::endl << " Key file : " << StringUtils::BaseName(aesFilename); VERBOSE_OUT << std::endl << "------------------------------------"; } /* Encrypt the stream */ if (isBootloader && partHdr->imageHeader->GetPmcFwSizeIh() != 0) { // BootLoader Encryption uint32_t encrFsblByteLength; uint32_t estimatedEncrFsblLength = partHdr->imageHeader->GetFsblFwSizeIh() + totalBlocksOverhead; uint8_t* encrFsblDataBuffer = new uint8_t[estimatedEncrFsblLength]; LOG_INFO("Encrypting Bootloader"); ChunkifyAndEncrypt(options, partHdr->partition->section->Data, partHdr->imageHeader->GetFsblFwSizeIh(), NULL, 0, encrFsblDataBuffer /* out*/, encrFsblByteLength /* out */); if (estimatedEncrFsblLength < encrFsblByteLength) { LOG_ERROR("Encryption Error!!! - PmcFw Buffer overflow"); } // PMC Data Encryption if (bi.pmcDataAesFile != "") { aesKey = aesIv = aesSeed = NULL; fixedInputData = NULL; aesSeedexits = false; fixedInputDataExits = false; SetAesFileName(bi.pmcDataAesFile); LOG_INFO("Key file - %s", aesFilename.c_str()); std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } GenerateEncryptionKeyFile(aesFilename, options); } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); std::pair asesKeyandKeySrcPair(partHdr->imageHeader->GetEncryptionKeySrc(), aesKey); bi.aesKeyandKeySrc.push_back(asesKeyandKeySrcPair); bi.bifOptions->CheckForBadKeyandKeySrcPair(bi.aesKeyandKeySrc, aesFilename); options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, partHdr->partition->section->Name); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } } else { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } GenerateRemainingKeys(options); } tmpIv = GetIv(); if (tmpIv != NULL) { if (options.secHdrIvPmcData == NULL) { options.secHdrIvPmcData = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(options.secHdrIvPmcData, tmpIv, BYTES_PER_IV); } } else { LOG_ERROR("Key Generation Error !!!\n Key File doesnot exist to encrypt PMC CDO "); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), false); isPmcData = true; uint32_t encrPmcByteLength; uint32_t estimatedEncrPmcLength = partHdr->imageHeader->GetTotalPmcFwSizeIh() + totalBlocksOverhead; uint8_t* encrPmcDataBuffer = new uint8_t[estimatedEncrPmcLength]; LOG_INFO("Encrypting the PMC Data"); ChunkifyAndEncrypt(options, partHdr->partition->section->Data + partHdr->imageHeader->GetFsblFwSizeIh(), partHdr->imageHeader->GetTotalPmcFwSizeIh(), NULL, 0, encrPmcDataBuffer /* out*/, encrPmcByteLength /* out */); if (estimatedEncrPmcLength < encrPmcByteLength) { LOG_ERROR("Encryption Error!!! - PMC Buffer overflow"); } partHdr->partition->section->IncreaseLengthAndPadTo(encrFsblByteLength + encrPmcByteLength, 0x0); memset(partHdr->partition->section->Data, 0, encrFsblByteLength + encrPmcByteLength); memcpy(partHdr->partition->section->Data, encrFsblDataBuffer, encrFsblByteLength); memcpy(partHdr->partition->section->Data + encrFsblByteLength, encrPmcDataBuffer, encrPmcByteLength); partHdr->imageHeader->SetTotalPmcFwSizeIh(encrPmcByteLength); partHdr->imageHeader->SetTotalFsblFwSizeIh(encrFsblByteLength); partHdr->partition->section->Length = encrFsblByteLength + encrPmcByteLength; LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encrFsblDataBuffer; delete[] encrPmcDataBuffer; return; } else { uint32_t encryptedLength; uint32_t estimatedEncrLength = partHdr->partition->section->Length + totalBlocksOverhead; uint8_t* encryptedDataBuffer = new uint8_t[estimatedEncrLength]; ChunkifyAndEncrypt(options, partHdr->partition->section->Data, (uint32_t)partHdr->partition->section->Length, NULL, 0, encryptedDataBuffer /* out*/, encryptedLength /* out */); partHdr->partition->section->IncreaseLengthAndPadTo(encryptedLength, 0x0); memcpy(partHdr->partition->section->Data, encryptedDataBuffer, encryptedLength); partHdr->partition->section->Length = encryptedLength; partHdr->imageHeader->SetTotalFsblFwSizeIh(encryptedLength); LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encryptedDataBuffer; return; } } /******************************************************************************/ void VersalEncryptionContext::Process(BootImage& bi) { size_t size = bi.imageHeaderTable->metaHeaderLength; uint8_t* dataBuffer = new uint8_t[size]; uint32_t offset = 0; for (SectionList::iterator i = bi.headers.begin(); i != bi.headers.end(); i++) { Section& section(**i); memcpy(dataBuffer + offset, section.Data, section.Length); offset += section.Length; } uint32_t totalencrBlocks = bi.options.bifOptions->metaHdrAttributes.encrBlocks.size(); bi.options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < totalencrBlocks; itr++) { bi.options.bifOptions->InsertEncryptionBlock(bi.options.bifOptions->metaHdrAttributes.encrBlocks[itr]); } LOG_TRACE("Total no. of Key/IV pairs needed to encrypt - %d", totalencrBlocks + 1); WarnforDPACMImpactonBootTime(bi.options.bifOptions->metaHdrAttributes.encrBlocks.size() != 0, bi.options.bifOptions->metaHdrAttributes.dpaCM == DpaCM::DpaCMEnable); /* Get the key file */ if (bi.options.bifOptions->metaHdrAttributes.encrKeyFile != "") { SetAesFileName(bi.options.bifOptions->metaHdrAttributes.encrKeyFile); LOG_INFO("Key file - %s", aesFilename.c_str()); std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (bi.options.bifOptions->metaHdrAttributes.encrKeySource == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } GenerateEncryptionKeyFile(aesFilename, bi.options); } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); std::pair asesKeyandKeySrcPair(bi.options.bifOptions->metaHdrAttributes.encrKeySource, aesKey); bi.aesKeyandKeySrc.push_back(asesKeyandKeySrcPair); bi.bifOptions->CheckForBadKeyandKeySrcPair(bi.aesKeyandKeySrc, aesFilename); bi.options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, "MetaHeader"); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in Meta Header."); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in Meta Header."); } } else { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (bi.options.bifOptions->metaHdrAttributes.encrKeySource == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } GenerateRemainingKeys(bi.options); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), false); if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (bi.options.bifOptions->metaHdrAttributes.encrKeySource == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } // For copying SCR HDR IV into Boot Header const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { if (bi.imageHeaderTable->metaHdrSecHdrIv == NULL) { bi.imageHeaderTable->metaHdrSecHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(bi.imageHeaderTable->metaHdrSecHdrIv, tmpIv, BYTES_PER_IV); } bi.imageHeaderTable->SetMetaHdrSecureHdrIv(bi.imageHeaderTable->metaHdrSecHdrIv); bi.imageHeaderTable->SetChecksum(); } else { LOG_ERROR("Key Generation Error !!!\n File - %s already exists.", aesFilename.c_str()); } uint32_t totalBlocksOverhead = (totalencrBlocks + 1) * 64; //64 = AES_GCM_IV_SZ+AES_GCM_KEY_SZ+NUM_BYTES_PER_WORD+AES_GCM_TAG_SZ if (!Binary::CheckAddress(size)) { LOG_ERROR("Partition too large to encrypt"); } if (bi.options.GetEncryptionDumpFlag()) { bi.options.aesLogFile.open(bi.options.aesLogFilename, std::fstream::app); VERBOSE_OUT_MH << std::endl << "------------------------------------"; VERBOSE_OUT_MH << std::endl << " Partition Name : " << "Meta Header"; VERBOSE_OUT_MH << std::endl << " Key file : " << StringUtils::BaseName(aesFilename); VERBOSE_OUT_MH << std::endl << "------------------------------------"; } /* Encrypt the stream */ uint32_t encryptedLength; uint32_t estimatedEncrLength = size + totalBlocksOverhead; if (bi.encryptedHeaders->Length != estimatedEncrLength) { LOG_ERROR("Internal Error : Encrypted metaheader length calculation error."); } uint8_t* encryptedDataBuffer = new uint8_t[estimatedEncrLength]; ChunkifyAndEncrypt(bi.options, dataBuffer, (uint32_t)size, bi.imageHeaderTable->section->Data, sizeof(VersalImageHeaderTableStructure) + bi.imageHeaderTable->iht_optional_data_length, encryptedDataBuffer /* out*/, encryptedLength /* out */); if (bi.encryptedHeaders->Length != encryptedLength) { LOG_ERROR("Internal Error : Encryption buffer allocation error."); } memset(bi.encryptedHeaders->Data, bi.options.GetOutputFillByte(), bi.encryptedHeaders->Length); memcpy(bi.encryptedHeaders->Data, encryptedDataBuffer, encryptedLength); LOG_INFO("Encrypted the partition - %s", bi.encryptedHeaders->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encryptedDataBuffer; delete[] dataBuffer; return; } /******************************************************************************/ void VersalEncryptionContext::AesGcm256Encrypt(unsigned char* gcm_pt, int pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int& ct_len, unsigned char* gcm_tag) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; ctx = EVP_CIPHER_CTX_new(); /* Set cipher type and mode */ EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length to 96 bits or 12 bytes */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL); /* Initialise key and IV */ EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); /* Specify any AAD only if it is non-zero length*/ if ((gcm_aad) && aad_len) { EVP_EncryptUpdate(ctx, NULL, &outlen, gcm_aad, aad_len); } /* Encrypt plaintext */ EVP_EncryptUpdate(ctx, gcm_ct, &outlen, gcm_pt, pt_len); /* Finalise GCM */ EVP_EncryptFinal_ex(ctx, gcm_ct + outlen, &tmplen); /* Get GCM tag */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, gcm_tag); EVP_CIPHER_CTX_free(ctx); ct_len = outlen + tmplen; } /******************************************************************************/ void VersalEncryptionContext::AesGcm256Decrypt(unsigned char* gcm_pt, int& pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int ct_len, unsigned char* gcm_tag) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; ctx = EVP_CIPHER_CTX_new(); /* Select cipher */ EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length, omit for 96 bits */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL); /* Specify key and IV */ EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); #if 1 /* Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier * required the tag before any AAD or ciphertext */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, gcm_tag); #endif /* Specify any AAD only if it is non-zero length*/ if ((gcm_aad) && aad_len > 0) { EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, aad_len); } /* Decrypt plaintext */ EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, ct_len); #if 0 /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, gcm_tag); #endif /* Finalise: GCM */ (void)EVP_DecryptFinal_ex(ctx, gcm_pt + outlen, &tmplen); EVP_CIPHER_CTX_free(ctx); pt_len = outlen + tmplen; } xilinx-bootgen-2024.2/encryption-versal.h000077500000000000000000000076771475706442400204470ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _ENCRYPTION_VERSAL_CONTEXT_ #define _ENCRYPTION_VERSAL_CONTEXT_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "bootgenenum.h" #include "options.h" #include #include /* Forward Class References */ class PartitionHeader; class Options; class DataMover; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalEncryptionContext : public EncryptionContext { public: VersalEncryptionContext(); VersalEncryptionContext(const EncryptionContext * other); ~VersalEncryptionContext(); Encryption::Type Type() { return Encryption::AES; } void Process(BootImage& bi, PartitionHeader* partition); void Process(BootImage& bi); //VersalNet defines uint32_t ConfigureEncryptionBlocksforPmcData(BootImage& bi, PartitionHeader * partHdr); uint32_t ConfigureEncryptionBlocksforPartition(BootImage & bi, PartitionHeader * partHdr); void ChunkifyAndProcess(BootImage & bi, PartitionHeader * partHdr); void SetAesSeedString(const std::string & key); void SetAesSeed(const uint8_t * key); const uint32_t* GetAesSeed(void); void GenerateAesKey(void); void WriteEncryptionKeyFile(const std::string& baseFileName, bool useOptionalKey, uint32_t blocks); void ReadEncryptionKeyFile(const std::string& keyFileName); void SetAesKey(const uint8_t* binarykey); const uint32_t* GetAesKey(void); void SetIv(const uint8_t* iv); void SetIvString(const std::string& IV); void GenerateIv(void); const uint32_t* GetIv(void); void PackNextEncryptionKey(uint8_t* aesKeyNext, int aeskeyPtr); void PackNextIv(uint8_t * aesIvNext, int aesIvPtr); void GetNextKey(uint8_t* keyNext, int ptr); void GetNextIv(uint8_t* keyNext, int ptr); void GenerateRemainingKeys(Options& options); private: bool isBootloader; bool isPmcData; bool aesSeedexits; void ChunkifyAndEncrypt(Options& options, const uint8_t *inBuf, uint32_t inLen, uint8_t *aad, uint32_t aad_len, uint8_t* outBuf, uint32_t& outLen); void GetEncryptionKeys(Options& options, uint8_t* aesKey, uint8_t* aesOptKey, uint8_t* aesIV); void WarnforDPACMImpactonBootTime(bool dpacmKeyRollingEnable, bool dpacmMaskEnable); void AesGcm256Encrypt(unsigned char* gcm_pt, int pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int& ct_len, unsigned char* gcm_tag); void AesGcm256Decrypt(unsigned char* gcm_pt, int& pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int ct_len, unsigned char* gcm_tag); protected: AesGcmEncryptionContext* encryptionAlgorithm; }; #endif xilinx-bootgen-2024.2/encryption-versalnet.cpp000077500000000000000000001105031475706442400214700ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "encryption-versal.h" #include "bootimage.h" #include "encryptutils.h" #include "options.h" #include "imageheadertable-versal.h" #include "bootheader-versal.h" #include "partitionheadertable-versal.h" #include "authentication-versal.h" #include /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ uint32_t VersalEncryptionContext::ConfigureEncryptionBlocksforPmcData(BootImage& bi, PartitionHeader* partHdr) { uint32_t totalencrBlocks = 0; Binary::Length_t lastBlock = 0; std::vector encrBlocks = partHdr->imageHeader->GetEncrBlocksList(); totalencrBlocks = encrBlocks.size(); uint32_t overhead = (totalencrBlocks) * (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* Due to encryption over head, the actual default size on which the partition needs to be Key rolled is always less than 64KB. So first calculate the default key roll data size by substracting the overhead. */ /* Then calculate the number of such blocks possible on a given partition. */ /* Note that the last block will always be based on the partition length.*/ std::vector secureChunkEncrBlocks; uint32_t actualSecureChunkSize = bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader()) - overhead; if (partHdr->imageHeader->GetAuthenticationType() == Authentication::None && !partHdr->imageHeader->GetDelayAuthFlag()) { actualSecureChunkSize += SHA3_LENGTH_BYTES; } uint32_t totalKeyRollencrBlocks = GetTotalEncryptionBlocks(partHdr->imageHeader->GetTotalPmcFwSizeIh(), secureChunkEncrBlocks, actualSecureChunkSize, &lastBlock); secureChunkEncrBlocks.clear(); for (uint32_t itr = 0; itr < totalKeyRollencrBlocks; itr++) { if ((itr == totalKeyRollencrBlocks - 1) && (lastBlock != 0)) { secureChunkEncrBlocks.push_back(lastBlock); lastBlock = 0; } else { secureChunkEncrBlocks.push_back(actualSecureChunkSize); } } /* Now chunk each default key roll data size, based on user encryption blocks. Note that the last block will always be based on the partition length.*/ //std::vector blocks; for (uint32_t itr1 = 0; itr1 < totalKeyRollencrBlocks; itr1++) { if ((itr1 == totalKeyRollencrBlocks - 1) && (secureChunkEncrBlocks[itr1] != actualSecureChunkSize)) { Binary::Length_t encrBlocksSize = 0; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; if (secureChunkEncrBlocks[itr1] > encrBlocksSize) { bi.options.bifOptions->pmcdataBlocks.push_back(encrBlocks[itr]); } else { bi.options.bifOptions->pmcdataBlocks.push_back(secureChunkEncrBlocks[itr1] - (encrBlocksSize - encrBlocks[itr])); break; } } } else { for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { bi.options.bifOptions->pmcdataBlocks.push_back(encrBlocks[itr]); } } } totalencrBlocks = bi.options.bifOptions->pmcdataBlocks.size(); return totalencrBlocks; } uint32_t VersalEncryptionContext::ConfigureEncryptionBlocksforPartition(BootImage& bi, PartitionHeader* partHdr) { Options& options = bi.options; uint32_t totalencrBlocks = 0; Binary::Length_t lastBlock = 0; std::vector encrBlocks = partHdr->imageHeader->GetEncrBlocksList(); totalencrBlocks = encrBlocks.size(); uint32_t overhead = (totalencrBlocks) * (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* Due to encryption over head, the actual default size on which the partition needs to be Key rolled is always less than 64KB. So first calculate the default key roll data size by substracting the overhead. */ /* Then calculate the number of such blocks possible on a given partition. */ /* Note that the last block will always be based on the partition length.*/ std::vector secureChunkEncrBlocks; uint32_t actualSecureChunkSize = bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader()) - overhead; if (partHdr->imageHeader->GetAuthenticationType() == Authentication::None && !partHdr->imageHeader->GetDelayAuthFlag()) { actualSecureChunkSize += SHA3_LENGTH_BYTES; } uint32_t totalKeyRollencrBlocks = 0; if (partHdr->imageHeader->IsBootloader()) { totalKeyRollencrBlocks = GetTotalEncryptionBlocks(partHdr->imageHeader->GetFsblFwSizeIh(), secureChunkEncrBlocks, actualSecureChunkSize, &lastBlock); } else { totalKeyRollencrBlocks = GetTotalEncryptionBlocks(partHdr->partition->section->Length, secureChunkEncrBlocks, actualSecureChunkSize, &lastBlock); } secureChunkEncrBlocks.clear(); for (uint32_t itr = 0; itr < totalKeyRollencrBlocks; itr++) { if ((itr == totalKeyRollencrBlocks - 1) && (lastBlock != 0)) { secureChunkEncrBlocks.push_back(lastBlock); lastBlock = 0; } else { secureChunkEncrBlocks.push_back(actualSecureChunkSize); } } /* Now chunk each default key roll data size, based on user encryption blocks. Note that the last block will always be based on the partition length.*/ options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr1 = 0; itr1 < totalKeyRollencrBlocks; itr1++) { if ((itr1 == totalKeyRollencrBlocks - 1) && (secureChunkEncrBlocks[itr1] != actualSecureChunkSize)) { Binary::Length_t encrBlocksSize = 0; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; if (secureChunkEncrBlocks[itr1] > encrBlocksSize) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } else { options.bifOptions->InsertEncryptionBlock(secureChunkEncrBlocks[itr1] - (encrBlocksSize - encrBlocks[itr])); break; } } } else { for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } } } totalencrBlocks = options.bifOptions->GetEncryptionBlocksList().size(); return totalencrBlocks; } /******************************************************************************/ static std::string ReadIV0(const std::string& inputFileName) { std::ifstream keyFile(inputFileName.c_str()); int aesKeyNum = 0; int aesIvNum = 0; if (!keyFile) { LOG_ERROR("Failure reading AES key file - %s", inputFileName.c_str()); } while (keyFile) { std::string word; keyFile >> word; if (word == "") { return ""; } char c = ' '; if (word == "Device") { word = ""; keyFile >> word; c = word[word.size() - 1]; word.erase(word.size() - 1); } else if (word == "Key") { keyFile >> word; if (word == "Opt") { LOG_ERROR("The key word 'Key Opt' is not supported in VERSAL architecture"); } if (word != "" && isalnum(word[0])) { /* Second Word is "0" or "1" or "2" ...*/ int index = std::stoi(word); if (aesKeyNum != index) { LOG_DEBUG(DEBUG_STAMP, "Key order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesKeyNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } } else { /* Second Word other than "0", - throw error */ LOG_DEBUG(DEBUG_STAMP, "Unknown key type - '%s' in %s", word.c_str(), inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } } else if (word == "IV") { keyFile >> word; if (word != "") { if (word.size() == ((BYTES_PER_IV * 2) + 1)) { c = word[word.size() - 1]; word.erase(word.size() - 1); return word; } else { int index = std::stoi(word); if (aesIvNum != index) { LOG_DEBUG(DEBUG_STAMP, "Iv order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesIvNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (index == 0) { return word; } } } } else if (word == "Seed") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } } else if (word == "Label") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } } else if (word == "Context") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } } else if (word == "FixedInputData") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } } else { /* If the word is neither of the above */ LOG_DEBUG(DEBUG_STAMP, "'Key' or 'Device' identifier expected, '%s' found instead", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if (c != ';') { /* Semicolons expected at end of every line */ while ((keyFile >> c) && isspace(c)) { word.push_back(c); } } if (c != ';') { LOG_DEBUG(DEBUG_STAMP, "Terminating ';' expected. Last word read was '%s'", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } } return ""; } /******************************************************************************/ void VersalEncryptionContext::ChunkifyAndProcess(BootImage& bi, PartitionHeader* partHdr) { Options& options = bi.options; LOG_INFO("Encrypting the partition - %s", partHdr->partition->section->Name.c_str()); WarnforDPACMImpactonBootTime(partHdr->imageHeader->GetEncrBlocksList().size() != 0, partHdr->imageHeader->GetDpacm() == DpaCM::DpaCMEnable); uint32_t totalencrBlocks = ConfigureEncryptionBlocksforPartition(bi, partHdr); LOG_TRACE("Total no. of Key/IV pairs needed to encrypt - %d", totalencrBlocks + 1); /* Get the key file */ SetAesFileName(partHdr->partitionAesKeyFile); LOG_INFO("Key file - %s", aesFilename.c_str()); if (partHdr->generateAesKeyFile) { std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } GenerateEncryptionKeyFile(aesFilename, options); } else { LOG_ERROR("Key Generation Error !!!\n File - %s already exists.", aesFilename.c_str()); } } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); std::pair asesKeyandKeySrcPair(partHdr->imageHeader->GetEncryptionKeySrc(), aesKey); bi.aesKeyandKeySrc.push_back(asesKeyandKeySrcPair); bi.bifOptions->CheckForBadKeyandKeySrcPair(bi.aesKeyandKeySrc, aesFilename); options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, partHdr->partition->section->Name); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } } else { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } GenerateRemainingKeys(options); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), false); if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey != NULL) { memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } break; } } } // For copying SCR HDR IV into Boot Header const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { if (partHdr->IsBootloader()) { if (options.secHdrIv == NULL) { options.secHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(options.secHdrIv, tmpIv, BYTES_PER_IV); } if (partHdr->partitionSecHdrIv == NULL) { partHdr->partitionSecHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(partHdr->partitionSecHdrIv, tmpIv, BYTES_PER_IV); } uint32_t totalBlocksOverhead = (totalencrBlocks + 1) * 64; //64 = AES_GCM_IV_SZ+AES_GCM_KEY_SZ+NUM_BYTES_PER_WORD+AES_GCM_TAG_SZ if (!Binary::CheckAddress(partHdr->partition->section->Length)) { LOG_ERROR("Partition too large to encrypt"); } isBootloader = partHdr->imageHeader->IsBootloader(); if (options.GetEncryptionDumpFlag()) { bi.options.aesLogFile.open(bi.options.aesLogFilename, std::fstream::app); VERBOSE_OUT << std::endl << "------------------------------------"; VERBOSE_OUT << std::endl << " Partition Name : " << partHdr->partition->section->Name; VERBOSE_OUT << std::endl << " Key file : " << StringUtils::BaseName(aesFilename); VERBOSE_OUT << std::endl << "------------------------------------"; } /* Encrypt the stream */ if (isBootloader && partHdr->imageHeader->GetPmcFwSizeIh() != 0) { // BootLoader Encryption uint32_t encrFsblByteLength; uint32_t estimatedEncrFsblLength = partHdr->imageHeader->GetFsblFwSizeIh() + totalBlocksOverhead; uint32_t estimatedTotalFsblLength = estimatedEncrFsblLength; uint8_t* encrFsblDataBuffer = new uint8_t[estimatedEncrFsblLength]; uint32_t totalpmcdataencrBlocks = ConfigureEncryptionBlocksforPmcData(bi, partHdr); uint32_t estimatedtotalPmcCdoLength = partHdr->imageHeader->GetTotalPmcFwSizeIh() + (totalpmcdataencrBlocks + 1) * 64; LOG_INFO("Encrypting Bootloader"); if ((partHdr->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { Binary::Length_t dataChunksCount = 0; // PLM dataChunksCount = ((estimatedEncrFsblLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) / bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) + ((((estimatedEncrFsblLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) % bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) == 0 ? 0 : 1)); // If PMC CDO present, need to calculate the hash, so include hash if (partHdr->imageHeader->GetTotalPmcFwSizeIh()) { estimatedTotalFsblLength += SHA3_LENGTH_BYTES; } if (dataChunksCount != 1) { for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { estimatedTotalFsblLength += SHA3_LENGTH_BYTES; } } // PMC DATA dataChunksCount = 0; dataChunksCount = ((estimatedtotalPmcCdoLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) / bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) + ((((estimatedtotalPmcCdoLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) % bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) == 0 ? 0 : 1)); if (dataChunksCount != 1) { for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { estimatedtotalPmcCdoLength += SHA3_LENGTH_BYTES; } } } uint32_t* tmpIvPMCDATA = new uint32_t[WORDS_PER_IV]; memset(tmpIvPMCDATA, 0, WORDS_PER_IV); // PMC Data Encryption if (bi.pmcDataAesFile != "") { //aesKey = NULL; aesSeedexits = false; fixedInputDataExits = false; SetAesFileName(bi.pmcDataAesFile); LOG_INFO("Key file - %s", aesFilename.c_str()); std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } std::vector blocks = options.bifOptions->GetEncryptionBlocksList(); options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < options.bifOptions->pmcdataBlocks.size(); itr++) { options.bifOptions->InsertEncryptionBlock(options.bifOptions->pmcdataBlocks[itr]); } GenerateEncryptionKeyFile(aesFilename, options); options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < blocks.size(); itr++) { options.bifOptions->InsertEncryptionBlock(blocks[itr]); } blocks.clear(); } std::string iv0 = ReadIV0(aesFilename); uint8_t hexData[256]; if (iv0.size() != (BYTES_PER_IV * 2)) { LOG_DEBUG(DEBUG_STAMP, "IV = %s, IV Size = %d", iv0.c_str(), iv0.size()); LOG_ERROR("Encryption Error !!!\n An IV key must be 12 bytes long"); } PackHex(iv0, hexData); const uint8_t* iv = hexData; for (uint32_t index = 0; index < WORDS_PER_IV; index++) { tmpIvPMCDATA[index] = ReadBigEndian32(iv); iv += sizeof(uint32_t); } } else { LOG_ERROR("Key Generation Error !!!\n Key File doesnot exist to encrypt PMC CDO "); } VersalBootHeaderStructure* bh = (VersalBootHeaderStructure*)bi.bootHeader->section->Data; bh->plmLength = partHdr->imageHeader->GetFsblFwSizeIh(); bh->pmcCdoLength = partHdr->imageHeader->GetTotalPmcFwSizeIh(); bh->totalPlmLength = estimatedTotalFsblLength; if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->totalPlmLength += sizeof(AuthCertificate4096Sha3PaddingStructure); } bh->totalPmcCdoLength = estimatedtotalPmcCdoLength; memcpy_be((uint8_t*)bh->plmSecureHdrIv, tmpIv, BYTES_PER_IV); memcpy_be((uint8_t*)bh->pmcCdoSecureHdrIv, tmpIvPMCDATA, BYTES_PER_IV); if (bi.imageList.size() != 0) { uint8_t cksumType = 0; cksumType = bi.partitionHeaderList.front()->imageHeader->GetChecksumContext()->Type(); bh->bhAttributes = bi.partitionHeaderList.front()->imageHeader->GetPufHdLocation() << PUF_HD_BIT_SHIFT; bh->bhAttributes |= cksumType << BI_HASH_BIT_SHIFT; bh->bhAttributes |= bi.partitionHeaderList.front()->imageHeader->GetDpacm() << DPA_CM_BIT_SHIFT; bh->bhAttributes |= bi.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; bh->bhAttributes |= bi.bifOptions->GetPufMode() << BH_PUF_MODE_BIT_SHIFT; if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->bhAttributes |= BH_RSA_SINGED_BIT_MASK << BH_RSA_SINGED_BIT_SHIFT; } bh->bhAttributes |= bi.bifOptions->GetDice() << BH_DICE_BIT_SHIFT; } bh->sourceOffset = sizeof(VersalBootHeaderStructure); if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->sourceOffset += sizeof(AuthCertificate4096Sha3PaddingStructure); } bh->imageHeaderByteOffset = sizeof(VersalBootHeaderStructure) + bh->totalPlmLength + bh->totalPmcCdoLength; bh->headerChecksum = bi.bootHeader->ComputeWordChecksum(&bh->widthDetectionWord, 3872); ChunkifyAndEncrypt(options, partHdr->partition->section->Data, partHdr->imageHeader->GetFsblFwSizeIh(), (uint8_t*)bh + sizeof(VersalSmapWidthTable), sizeof(VersalBootHeaderStructure) - sizeof(VersalSmapWidthTable), encrFsblDataBuffer /* out*/, encrFsblByteLength /* out */); if (estimatedEncrFsblLength < encrFsblByteLength) { LOG_ERROR("Encryption Error!!! - PmcFw Buffer overflow"); } // PMC Data Encryption totalencrBlocks = totalpmcdataencrBlocks; totalBlocksOverhead = (totalencrBlocks + 1) * 64; //64 = AES_GCM_IV_SZ+AES_GCM_KEY_SZ+NUM_BYTES_PER_WORD+AES_GCM_TAG_SZ options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < options.bifOptions->pmcdataBlocks.size(); itr++) { options.bifOptions->InsertEncryptionBlock(options.bifOptions->pmcdataBlocks[itr]); } if (bi.pmcDataAesFile != "") { aesKey = aesIv = aesSeed = NULL; fixedInputData = NULL; SetAesFileName(bi.pmcDataAesFile); LOG_INFO("Key file - %s", aesFilename.c_str()); std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); break; } } } GenerateEncryptionKeyFile(aesFilename, options); } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); std::pair asesKeyandKeySrcPair(partHdr->imageHeader->GetEncryptionKeySrc(), aesKey); bi.aesKeyandKeySrc.push_back(asesKeyandKeySrcPair); bi.bifOptions->CheckForBadKeyandKeySrcPair(bi.aesKeyandKeySrc, aesFilename); options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, partHdr->partition->section->Name); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } } else { if (bi.aesKeyandKeySrc.size() != 0) { for (uint32_t i = 0; i < bi.aesKeyandKeySrc.size(); i++) { if (partHdr->imageHeader->GetEncryptionKeySrc() == bi.aesKeyandKeySrc[i].first) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.aesKeyandKeySrc[i].second, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } break; } } } GenerateRemainingKeys(options); } tmpIv = GetIv(); if (tmpIv != NULL) { if (options.secHdrIvPmcData == NULL) { options.secHdrIvPmcData = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(options.secHdrIvPmcData, tmpIv, BYTES_PER_IV); } } else { LOG_ERROR("Key Generation Error !!!\n Key File doesnot exist to encrypt PMC CDO "); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), false); isPmcData = true; uint32_t encrPmcByteLength; uint32_t estimatedEncrPmcLength = partHdr->imageHeader->GetTotalPmcFwSizeIh() + totalBlocksOverhead; uint8_t* encrPmcDataBuffer = new uint8_t[estimatedEncrPmcLength]; LOG_INFO("Encrypting the PMC Data"); ChunkifyAndEncrypt(options, partHdr->partition->section->Data + partHdr->imageHeader->GetFsblFwSizeIh(), partHdr->imageHeader->GetTotalPmcFwSizeIh(), NULL, 0, encrPmcDataBuffer /* out*/, encrPmcByteLength /* out */); if (estimatedEncrPmcLength < encrPmcByteLength) { LOG_ERROR("Encryption Error!!! - PMC Buffer overflow"); } partHdr->partition->section->IncreaseLengthAndPadTo(encrFsblByteLength + encrPmcByteLength, 0x0); memset(partHdr->partition->section->Data, 0, encrFsblByteLength + encrPmcByteLength); memcpy(partHdr->partition->section->Data, encrFsblDataBuffer, encrFsblByteLength); memcpy(partHdr->partition->section->Data + encrFsblByteLength, encrPmcDataBuffer, encrPmcByteLength); partHdr->imageHeader->SetTotalPmcFwSizeIh(encrPmcByteLength); partHdr->imageHeader->SetTotalFsblFwSizeIh(encrFsblByteLength); partHdr->partition->section->Length = encrFsblByteLength + encrPmcByteLength; LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encrFsblDataBuffer; delete[] encrPmcDataBuffer; return; } else if(isBootloader && partHdr->imageHeader->GetPmcFwSizeIh() == 0) { uint32_t encryptedLength; uint32_t estimatedEncrLength = partHdr->partition->section->Length + totalBlocksOverhead; uint8_t* encryptedDataBuffer = new uint8_t[estimatedEncrLength]; uint32_t estimatedTotalFsblLength = estimatedEncrLength; if ((partHdr->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { Binary::Length_t dataChunksCount = 0; dataChunksCount = ((estimatedEncrLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) / bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) + ((((estimatedEncrLength - (SECURE_HDR_SZ + AES_GCM_TAG_SZ)) % bi.GetSecureChunkSize(partHdr->imageHeader->IsBootloader())) == 0 ? 0 : 1)); if (dataChunksCount != 1) { for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { estimatedTotalFsblLength += SHA3_LENGTH_BYTES; } } } VersalBootHeaderStructure* bh = (VersalBootHeaderStructure*)bi.bootHeader->section->Data; bh->plmLength = partHdr->imageHeader->GetFsblFwSizeIh(); bh->pmcCdoLength = 0; bh->totalPlmLength = estimatedTotalFsblLength; if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->totalPlmLength += sizeof(AuthCertificate4096Sha3PaddingStructure); } bh->totalPmcCdoLength = 0; memcpy_be((uint8_t*)bh->plmSecureHdrIv, tmpIv, BYTES_PER_IV); memset((uint8_t*)bh->pmcCdoSecureHdrIv, 0, BYTES_PER_IV); if (bi.imageList.size() != 0) { uint8_t cksumType = 0; cksumType = bi.partitionHeaderList.front()->imageHeader->GetChecksumContext()->Type(); bh->bhAttributes = bi.partitionHeaderList.front()->imageHeader->GetPufHdLocation() << PUF_HD_BIT_SHIFT; bh->bhAttributes |= cksumType << BI_HASH_BIT_SHIFT; bh->bhAttributes |= bi.partitionHeaderList.front()->imageHeader->GetDpacm() << DPA_CM_BIT_SHIFT; bh->bhAttributes |= bi.bifOptions->GetBhRsa() << BH_RSA_BIT_SHIFT; bh->bhAttributes |= bi.bifOptions->GetPufMode() << BH_PUF_MODE_BIT_SHIFT; if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->bhAttributes |= BH_RSA_SINGED_BIT_MASK << BH_RSA_SINGED_BIT_SHIFT; } bh->bhAttributes |= bi.bifOptions->GetDice() << BH_DICE_BIT_SHIFT; } bh->sourceOffset = sizeof(VersalBootHeaderStructure); if ((bi.partitionHeaderList.front()->imageHeader->GetAuthenticationType() != Authentication::None) || (partHdr->imageHeader->GetDelayAuthFlag())) { bh->sourceOffset += sizeof(AuthCertificate4096Sha3PaddingStructure); } bh->imageHeaderByteOffset = sizeof(VersalBootHeaderStructure) + bh->totalPlmLength + bh->totalPmcCdoLength; bh->headerChecksum = bi.bootHeader->ComputeWordChecksum(&bh->widthDetectionWord, 3872); ChunkifyAndEncrypt(options, partHdr->partition->section->Data, partHdr->imageHeader->GetFsblFwSizeIh(), bi.bootHeader->section->Data + sizeof(VersalSmapWidthTable), sizeof(VersalBootHeaderStructure) - sizeof(VersalSmapWidthTable), encryptedDataBuffer /* out*/, encryptedLength /* out */); partHdr->partition->section->IncreaseLengthAndPadTo(encryptedLength, 0x0); memcpy(partHdr->partition->section->Data, encryptedDataBuffer, encryptedLength); partHdr->partition->section->Length = encryptedLength; partHdr->imageHeader->SetTotalFsblFwSizeIh(encryptedLength); LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encryptedDataBuffer; return; } else { uint32_t encryptedLength; uint32_t estimatedEncrLength = partHdr->partition->section->Length + totalBlocksOverhead; uint8_t* encryptedDataBuffer = new uint8_t[estimatedEncrLength]; ChunkifyAndEncrypt(options, partHdr->partition->section->Data, (uint32_t)partHdr->partition->section->Length, NULL, 0, encryptedDataBuffer /* out*/, encryptedLength /* out */); partHdr->partition->section->IncreaseLengthAndPadTo(encryptedLength, 0x0); memcpy(partHdr->partition->section->Data, encryptedDataBuffer, encryptedLength); partHdr->partition->section->Length = encryptedLength; partHdr->imageHeader->SetTotalFsblFwSizeIh(encryptedLength); LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encryptedDataBuffer; return; } }xilinx-bootgen-2024.2/encryption-zynq.cpp000077500000000000000000001665311475706442400205020ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include "encryption-zynq.h" #include "bootimage.h" #include "encryptutils.h" #include "options.h" #include "bifoptions.h" #include "encryptutils.h" #include "fileutils.h" #include "stringutils.h" #include "bootgenexception.h" #include "systemutils.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define BITS_PER_SHA_BLOCK 512 #define BYTE_PER_SHA_BLOCK 64 #define WORDS_PER_CBC_KEY 4 #define BYTES_PER_CBC_KEY 16 #define WORDS_PER_HMAC_KEY 8 #define BYTES_PER_HMAC_KEY 32 #define HMAC_IPAD_BYTE 0x36 #define HMAC_OPAD_BYTE 0x5C #define BIT_STREAM_NOOP_COMMAND 0x20000000 static const uint32_t round_constant[30] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 }; static const uint8_t s_box[16][16] = { { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76 }, { 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0 }, { 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15 }, { 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75 }, { 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84 }, { 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF }, { 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8 }, { 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2 }, { 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73 }, { 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB }, { 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79 }, { 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08 }, { 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A }, { 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E }, { 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF }, { 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 } }; static const uint32_t Logtable[256] = { 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7 }; static const uint32_t Alogtable[256] = { 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1 }; const uint32_t K_256[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; const uint32_t H0_256[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ static void loadBar(int i, int n, int r, int w) { // Only update r times. if (n > r) { if (i % (n / r) != 0) return; } // Calculuate the ratio of complete-to-incomplete. float ratio = i / (float)n; int c = (int)(ratio * w + 0.5); // Show the percentage complete. std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; // Show the load bar. int x; for (x = 0; x> val) | (x << (32 - val))); } /******************************************************************************/ static uint32_t shift_right(uint32_t x, uint32_t val) { return (x >> val); } /******************************************************************************/ static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) { return ((x & y) ^ ((~x) & z)); } /******************************************************************************/ static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) { return ((x & y) ^ (x & z) ^ (y & z)); } /******************************************************************************/ static uint32_t c_sigma_0(uint32_t x) { return (rotate_right(x, 2) ^ rotate_right(x, 13) ^ rotate_right(x, 22)); } /******************************************************************************/ static uint32_t c_sigma_1(uint32_t x) { return (rotate_right(x, 6) ^ rotate_right(x, 11) ^ rotate_right(x, 25)); } /******************************************************************************/ static uint32_t sigma_0(uint32_t x) { return (rotate_right(x, 7) ^ rotate_right(x, 18) ^ shift_right(x, 3)); } /******************************************************************************/ static uint32_t sigma_1(uint32_t x) { return (rotate_right(x, 17) ^ rotate_right(x, 19) ^ shift_right(x, 10)); } /******************************************************************************/ static void SubByte(uint8_t& value1, uint8_t& value2, uint8_t& value3, uint8_t& value4) { uint32_t row; uint32_t col; row = (value1 >> 4) & 0x0F; col = value1 & 0x0F; value1 = s_box[row][col]; row = (value2 >> 4) & 0x0F; col = value2 & 0x0F; value2 = s_box[row][col]; row = (value3 >> 4) & 0x0F; col = value3 & 0x0F; value3 = s_box[row][col]; row = (value4 >> 4) & 0x0F; col = value4 & 0x0F; value4 = s_box[row][col]; } /******************************************************************************/ static uint8_t aes_mul(uint32_t a, uint32_t b) { if (a && b) { return (uint8_t)Alogtable[(Logtable[a] + Logtable[b]) % 255]; } else { return 0; } } /******************************************************************************/ void ZynqEncryptionContext::Process(BootImage& bi, PartitionHeader* partHdr) { Options& options = bi.options; /* Setup the AES encryption context */ DataStreamEncryption aes_encrypt(WORDS_PER_AES_BLOCK, WORDS_PER_AES_KEY); /* Data mover for handling endianness across architectures 7-series FPGA requires the data in Big Endian format Zynq & ZynqMp requires the data in Little Endian format */ aes_encrypt.dataMover = new DataMoverLE(); aes_encrypt.maskEfuseFlag = false; /* Get the key file or keys (Key0, StartCBC, HMAC) passed from command line */ std::string keyFilename = options.GetEncryptionKeyFile(); std::string key0 = options.GetKey0(); std::string startCbc = options.GetStartCbc(); std::string hmac = options.GetHmac(); /* If the key file is not given, generate a key file with the BIF file name */ if (aesFilename == "") { if (keyFilename == "") { aesFilename = StringUtils::ChangeExtension(options.GetBifFilename(), ".nky"); } else { aesFilename = keyFilename; } } bool exists; std::ifstream keyFile(aesFilename.c_str()); exists = keyFile.good(); /* If the file already exists */ if (exists) { // Read the existing key file aes_encrypt.ReadEncryptionKeyFile(aesFilename); // Overwrite with the keys, if specified on the command line if (key0 != "") { aes_encrypt.SetAesKeyString(key0); } if (startCbc != "") { aes_encrypt.setCbcString(startCbc); } if (hmac != "") { aes_encrypt.SetHmacKeyString(hmac); } } /* If the key file is not specified - generate it */ else { aes_encrypt.GenerateEncryptionKeyFile(aesFilename, options); } /* Get the key source */ KeySource::Type keySource = options.GetEncryptedKeySource(); if (!Binary::CheckAddress(partHdr->partition->section->Length)) { LOG_ERROR("Partition too large to encrypt"); } bool isFPGA = partHdr->imageHeader->GetDomain() == Domain::PL; /* Output buffer & output length */ uint8_t* encryptedDataBuffer; uint32_t encryptedBufferByteLength; /* Encrypt the stream */ aes_encrypt.AESDataStreamEncrypt(keySource, isFPGA, partHdr->partition->section->Data, (uint32_t)partHdr->partition->section->Length, encryptedDataBuffer, encryptedBufferByteLength, partHdr->preservedBitstreamHdr.data, partHdr->preservedBitstreamHdr.size); delete[] partHdr->partition->section->Data; /* Populate the partition headers */ partHdr->partition->section->Data = encryptedDataBuffer; partHdr->partition->section->Length = encryptedBufferByteLength; partHdr->imageHeader->SetTotalFsblFwSizeIh(encryptedBufferByteLength); } /******************************************************************************/ ZynqEncryptionContext::ZynqEncryptionContext() { wordsPerAesKey = WORDS_PER_AES_KEY; wordsPerAesBlock = WORDS_PER_AES_BLOCK; keySchedule = NULL; aesKey = NULL; hmacKey = NULL; first_AES_block = false; d_NumRounds = 0; working_AES_block = NULL; dataMover = NULL; maskEfuseFlag = false; } /******************************************************************************/ ZynqEncryptionContext::ZynqEncryptionContext(const EncryptionContext * other) : wordsPerAesKey(WORDS_PER_AES_KEY) , wordsPerAesBlock(WORDS_PER_AES_BLOCK) , working_AES_block(NULL) , keySchedule(NULL) , aesKey(NULL) , hmacKey(NULL) , first_AES_block(false) , dataMover(NULL) , maskEfuseFlag(false) , d_NumRounds(0) { aesFilename = other->aesFilename; } /******************************************************************************/ ZynqEncryptionContext::ZynqEncryptionContext(uint32_t words_per_AES_block0, uint32_t words_per_AES_key0) : wordsPerAesKey(words_per_AES_key0) , wordsPerAesBlock(words_per_AES_block0) , keySchedule(NULL) , aesKey(NULL) , hmacKey(NULL) , first_AES_block(false) , dataMover(NULL) , maskEfuseFlag(false) { memset(ivCbc, 0, 16); if ((wordsPerAesBlock == 8) || (wordsPerAesKey == 8)) { d_NumRounds = 14; } else { if ((wordsPerAesBlock == 6) || (wordsPerAesKey == 6)) { d_NumRounds = 12; } else d_NumRounds = 10; } working_AES_block = new uint32_t[wordsPerAesBlock]; } /******************************************************************************/ ZynqEncryptionContext::~ZynqEncryptionContext(void) { if (aesKey != NULL) delete[] aesKey; if (keySchedule != NULL) delete[] keySchedule; if (hmacKey != NULL) delete[] hmacKey; if (working_AES_block != NULL) delete[] working_AES_block; } /******************************************************************************/ uint32_t ZynqEncryptionContext::CvtChars2Int(uint8_t value1, uint8_t value2, uint8_t value3, uint8_t value4) { return (value1 << 24) | (value2 << 16) | (value3 << 8) | value4; } /******************************************************************************/ void ZynqEncryptionContext::ClearKeySchedule(void) { // Allocate a key schedule if we don't already have one. if (keySchedule == NULL) keySchedule = new uint32_t[sizeof(uint32_t) * (d_NumRounds + 1)]; for (uint32_t index = 0; index < sizeof(uint32_t) * (d_NumRounds + 1); index++) { keySchedule[index] = 0; } } /******************************************************************************/ void ZynqEncryptionContext::SetAesKey(const uint8_t* key) { aesKey = new uint32_t[WORDS_PER_AES_KEY]; for (uint32_t index = 0; index < WORDS_PER_AES_KEY; index++) { aesKey[index] = ReadBigEndian32(key); key += sizeof(uint32_t); } } /******************************************************************************/ void ZynqEncryptionContext::GenerateAesKey(void) { uint32_t keysize = WORDS_PER_AES_KEY * sizeof(uint32_t); uint8_t newKeyData[BYTES_PER_AES_KEY]; uint8_t newKey[BYTES_PER_AES_KEY]; // Get temp data to encrypt as the newKey. SetRandomSeed(); GetRandomData(newKeyData, keysize); memcpy(newKey, newKeyData, keysize); // Encrypt the newKeyData with the temp key and temp CBC into newKey as the generated new key. EncryptKeys(newKeyData, keysize, newKey); SetAesKey(newKey); LOG_INFO("AES Key generated successfully"); } /******************************************************************************/ void ZynqEncryptionContext::EncryptKeys(const uint8_t* newKeyData, uint32_t keysize, uint8_t* newKey) { // Use a local encrypt object so that we don't disturb any of the caller's keys. ZynqEncryptionContext temp_encrypt(wordsPerAesBlock, wordsPerAesKey); temp_encrypt.dataMover = new DataMoverLE(); temp_encrypt.GenerateTempKeys(); temp_encrypt.InitKeySchedule(); temp_encrypt.AES_Encrypt(newKeyData, keysize, newKey); } /******************************************************************************/ const uint8_t* ZynqEncryptionContext::GetAesKey(void) { return (uint8_t *)this->aesKey; } /******************************************************************************/ void ZynqEncryptionContext::SetCbc(const uint8_t* initialVector) { memcpy(ivCbc, initialVector, WORDS_PER_AES_BLOCK * sizeof(uint32_t)); } /******************************************************************************/ void ZynqEncryptionContext::setCbcString(const std::string& initialVector) { uint8_t hexData[256]; if (initialVector.size() != (BYTES_PER_CBC_KEY * 2)) { LOG_DEBUG(DEBUG_STAMP, "CBC key size - %d", initialVector.size()); LOG_ERROR("An CBC key must be 128 bits long - %s", initialVector.c_str()); } PackHex(initialVector, hexData); SetCbc(hexData); } /******************************************************************************/ void ZynqEncryptionContext::GenerateCbc(void) { uint8_t newCBC[BYTES_PER_CBC_KEY]; uint8_t newCBCData[BYTES_PER_CBC_KEY]; // Setup a new encrypt object so that we don't disturb any of the caller's keys. ZynqEncryptionContext temp_encrypt(WORDS_PER_AES_BLOCK, WORDS_PER_AES_KEY); temp_encrypt.dataMover = new DataMoverLE(); // Get temp data to encrypt as the newCBC. SetRandomSeed(); GetRandomData(newCBCData, BYTES_PER_CBC_KEY); /* Encrypt the newKeyData with the temp key and temp CBC into newCBC as the generated new CBC. */ temp_encrypt.GenerateTempKeys(); temp_encrypt.InitKeySchedule(); temp_encrypt.AES_Encrypt(newCBCData, BYTES_PER_CBC_KEY, newCBC); SetCbc(newCBC); LOG_INFO("CBC generated successfully"); } /******************************************************************************/ const uint8_t * ZynqEncryptionContext::GetCbc(void) { #if 1 static uint8_t be[16]; ((uint32_t*)be)[0] = ReadBigEndian32(ivCbc); ((uint32_t*)be)[1] = ReadBigEndian32(ivCbc + 4); ((uint32_t*)be)[2] = ReadBigEndian32(ivCbc + 8); ((uint32_t*)be)[3] = ReadBigEndian32(ivCbc + 12); return be; #else return (uint8_t *)this->d_InitialVector; #endif } /******************************************************************************/ void ZynqEncryptionContext::SetHmacKey(const uint8_t * HMACKey) { hmacKey = new uint32_t[WORDS_PER_HMAC_KEY]; for (uint32_t index = 0; index < WORDS_PER_HMAC_KEY; index++) { hmacKey[index] = ReadBigEndian32(HMACKey); HMACKey += sizeof(uint32_t); } } /******************************************************************************/ void ZynqEncryptionContext::SetHmacKeyString(const std::string& HMACKey) { uint8_t hexData[256]; if (HMACKey.size() != (BYTES_PER_HMAC_KEY * 2)) { LOG_DEBUG(DEBUG_STAMP, "HMAC key size - %d", HMACKey.size()); LOG_ERROR("An HMAC key must be 128 bits long - %s", HMACKey.c_str()); } PackHex(HMACKey, hexData); SetHmacKey(hexData); } /******************************************************************************/ void ZynqEncryptionContext::GenerateHmacKey(void) { uint8_t newHMAC[BYTES_PER_HMAC_KEY]; uint8_t newHMACData[BYTES_PER_HMAC_KEY]; // Setup a new encrypt object so that we don't disturb any of the caller's keys. ZynqEncryptionContext temp_encrypt(WORDS_PER_AES_BLOCK, WORDS_PER_AES_KEY); temp_encrypt.dataMover = new DataMoverLE(); // Get temp data to encrypt as the newHMAC. SetRandomSeed(); GetRandomData(newHMACData, BYTES_PER_HMAC_KEY); /* Encrypt the newHMACData with the temp key and temp CBC into newKey as the generated new HMAC */ temp_encrypt.GenerateTempKeys(); temp_encrypt.InitKeySchedule(); temp_encrypt.AES_Encrypt(newHMACData, BYTES_PER_HMAC_KEY, newHMAC); SetHmacKey(newHMAC); LOG_INFO("HMAC generated successfully"); } /******************************************************************************/ const uint8_t * ZynqEncryptionContext::GetHmacKey(void) { return (uint8_t *)this->hmacKey; } /******************************************************************************/ uint32_t ZynqEncryptionContext::Transform(uint32_t orig_col, uint32_t col_num, bool rotate_rcon) { uint8_t element1; uint8_t element2; uint8_t element3; uint8_t element4; if (rotate_rcon != 0) { element1 = (orig_col >> 16) & 0xff; element2 = (orig_col >> 8) & 0xff; element3 = orig_col & 0xff; element4 = orig_col >> 24; } else { element1 = orig_col >> 24; element2 = (orig_col >> 16) & 0xff; element3 = (orig_col >> 8) & 0xff; element4 = orig_col & 0xff; } SubByte(element1, element2, element3, element4); if (rotate_rcon != 0) { element1 ^= round_constant[(col_num / wordsPerAesKey) - 1]; } return CvtChars2Int(element1, element2, element3, element4); } /******************************************************************************/ void ZynqEncryptionContext::InitKeySchedule(void) { uint32_t col; // Clear any key schedule, and make sure we // start CBC chaining from the beginning. ClearKeySchedule(); first_AES_block = true; // copy original key into columns 1 - d_NumKey of key schedule for (col = 0; col < wordsPerAesKey; col++) { keySchedule[col] = aesKey[col]; } // Set the remaining columns of the schedule for (col = wordsPerAesKey; col < sizeof(uint32_t) * (d_NumRounds + 1); col++) { uint32_t T_prev_col; // If col is a multiple of wordsPerAesKey, transform if ((col % wordsPerAesKey) == 0) { T_prev_col = Transform(keySchedule[col - 1], col, true); } else { if ((wordsPerAesKey == 8) && ((col % 4) == 0)) { // For keysize 256, sub bytes for col multiple of 4 T_prev_col = Transform(keySchedule[col - 1], col, false); } else { T_prev_col = keySchedule[col - 1]; } } keySchedule[col] = keySchedule[col - wordsPerAesKey] ^ T_prev_col; } } /******************************************************************************/ void ZynqEncryptionContext::AddRoundKey(uint32_t * int_array, uint32_t num_round) { for (uint32_t index = 0; index < wordsPerAesBlock; index++) { int_array[index] ^= keySchedule[(sizeof(uint32_t) * num_round) + index]; } } /******************************************************************************/ void ZynqEncryptionContext::ByteSubTransformation(uint32_t * int_array) { uint8_t element1; uint8_t element2; uint8_t element3; uint8_t element4; for (uint32_t index = 0; index < wordsPerAesBlock; index++) { element1 = int_array[index] >> 24; element2 = (int_array[index] >> 16) & 0xff; element3 = (int_array[index] >> 8) & 0xff; element4 = int_array[index] & 0xff; SubByte(element1, element2, element3, element4); int_array[index] = CvtChars2Int(element1, element2, element3, element4); } } /******************************************************************************/ void ZynqEncryptionContext::ShiftRowTransformation(uint32_t * int_array) { uint32_t num_cols = wordsPerAesBlock; uint32_t temp_col0 = int_array[0]; uint32_t temp_col1 = int_array[1]; uint32_t temp_col2 = int_array[2]; for (uint32_t index = 0; index < num_cols - 3; index++) { int_array[index] = (int_array[index + 0] & 0xff000000) | (int_array[index + 1] & 0x00ff0000) | (int_array[index + 2] & 0x0000ff00) | (int_array[index + 3] & 0x000000ff); } int_array[num_cols - 3] = (int_array[num_cols - 3] & 0xff000000) | (int_array[num_cols - 2] & 0x00ff0000) | (int_array[num_cols - 1] & 0x0000ff00) | (temp_col0 & 0x000000ff); int_array[num_cols - 2] = (int_array[num_cols - 2] & 0xff000000) | (int_array[num_cols - 1] & 0x00ff0000) | (temp_col0 & 0x0000ff00) | (temp_col1 & 0x000000ff); int_array[num_cols - 1] = (int_array[num_cols - 1] & 0xff000000) | (temp_col0 & 0x00ff0000) | (temp_col1 & 0x0000ff00) | (temp_col2 & 0x000000ff); } /******************************************************************************/ void ZynqEncryptionContext::MixColumnTransformation(uint32_t* int_array) { uint8_t in_byte0; uint8_t in_byte1; uint8_t in_byte2; uint8_t in_byte3; uint8_t temp_byte0; uint8_t temp_byte1; uint8_t temp_byte2; uint8_t temp_byte3; for (uint32_t index = 0; index < wordsPerAesBlock; index++) { in_byte0 = int_array[index] >> 24; in_byte1 = (int_array[index] >> 16) & 0xff; in_byte2 = (int_array[index] >> 8) & 0xff; in_byte3 = int_array[index] & 0xff; temp_byte0 = aes_mul(2, (uint32_t)in_byte0) ^ aes_mul(3, (uint32_t)in_byte1) ^ in_byte2 ^ in_byte3; temp_byte1 = in_byte0 ^ aes_mul(2, (uint32_t)in_byte1) ^ aes_mul(3, (uint32_t)in_byte2) ^ in_byte3; temp_byte2 = in_byte0 ^ in_byte1 ^ aes_mul(2, (uint32_t)in_byte2) ^ aes_mul(3, (uint32_t)in_byte3); temp_byte3 = aes_mul(3, (uint32_t)in_byte0) ^ in_byte1 ^ in_byte2 ^ aes_mul(2, (uint32_t)in_byte3); int_array[index] = CvtChars2Int(temp_byte0, temp_byte1, temp_byte2, temp_byte3); } } /******************************************************************************/ void ZynqEncryptionContext::GenerateTempKeys(void) { uint8_t tempKey[BYTES_PER_AES_KEY]; SetRandomSeed(); GetRandomData(tempKey, BYTES_PER_AES_KEY); SetAesKey(tempKey); uint8_t tempCBC[BYTES_PER_CBC_KEY]; SetRandomSeed(); GetRandomData(tempCBC, BYTES_PER_CBC_KEY); SetCbc(tempCBC); } /******************************************************************************/ void ZynqEncryptionContext::WriteEncryptionKeyFile(const std::string& baseFileName, bool useOptionalKey, uint32_t blocks) { uint32_t index; /* Setup the file for writing */ std::string ext = StringUtils::GetExtension(baseFileName); std::string filename; if (ext == "") { filename = baseFileName + ".nky"; } else { filename = baseFileName; } std::ofstream keyFile(filename.c_str()); if (!keyFile) { LOG_ERROR("Failure writing AES key file", filename.c_str()); } /* Write device name */ if (deviceName != "") { keyFile << "Device " << deviceName << ";\n"; } /* Write AES key */ keyFile << "Key 0 "; for (index = 0; index < wordsPerAesKey; ++index) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << aesKey[index]; } keyFile << ";\n"; /* Write CBC Initial Vector */ keyFile << "Key StartCBC "; for (index = 0; index < WORDS_PER_CBC_KEY * 4; ++index) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)ivCbc[index]; } keyFile << ";\n"; /* Write HMAC key */ keyFile << "Key HMAC "; for (index = 0; index < WORDS_PER_HMAC_KEY; ++index) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << hmacKey[index]; } keyFile << ";\n"; } /******************************************************************************/ void ZynqEncryptionContext::ReadEncryptionKeyFile(const std::string& inputFileName) { std::ifstream keyFile(inputFileName.c_str()); if (!keyFile) { LOG_ERROR("Failure reading AES key file - %s", inputFileName.c_str()); } uint8_t noOfSemiColons = 0; while (keyFile) { std::string word; keyFile >> word; if (word == "") { break; } char c = ' '; if (word == "Key") { // First Word is "Key" keyFile >> word; if (word == "0") { // Second Word is "0" word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (word == "pick") { // Third Word is "pick" - then generate AES key, otherwise set the key specified GenerateAesKey(); } else { SetAesKeyString(word); } } else if (word == "StartCBC") { // Second Word is "StartCBC" word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (word == "pick") { // Third Word is "pick" - then generate CBC key, otherwise set the key specified GenerateCbc(); } else { setCbcString(word); } } else if (word == "HMAC") { // Second Word is "HMAC" word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (word == "pick") { // Third Word is "pick" - then generate HMAC key, otherwise set the key specified GenerateHmacKey(); } else { SetHmacKeyString(word); } } else { // Second Word other than "0", "StartCBC" or "HMAC" - throw error LOG_DEBUG(DEBUG_STAMP, "Unknown key type - '%s' in %s", word.c_str(), inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } } else if (word == "Device") { // If first word is not "Key" but "Device" word = ""; while ((keyFile >> c) && (isalnum(c) || c == '-' || c == '_')) { word.push_back(c); } deviceName = word; } else { // If first word is neither "Key" nor "Device" LOG_DEBUG(DEBUG_STAMP, "'Key' or 'Device' identifier expected, '%s' found instead", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if (c == ';') { // Semicolons expected at end of every line noOfSemiColons++; } } if (deviceName == "") { LOG_DEBUG(DEBUG_STAMP, "Partname 'Device' missing in the key file - %s", inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s. \n Partname 'Device' missing in the key file", inputFileName.c_str()); } if (noOfSemiColons != 4) { LOG_DEBUG(DEBUG_STAMP, "Terminating ';' expected at end of each line"); LOG_ERROR("Error parsing AES key file - %s. \n Terminating ';' expected at end of each line", inputFileName.c_str()); } } /******************************************************************************/ void ZynqEncryptionContext::GenerateEncryptionKeyFile(const std::string& baseFileName, Options& options) { // Get the device name, AES key, CBC & HMAC std::string devicePartName = options.GetDevicePartName(); std::string key = options.GetKey0(); std::string initialVector = options.GetStartCbc(); std::string hmac = options.GetHmac(); // If device name is mentioned, set it, otherwise throw exception if (devicePartName != "") { SetDeviceName(devicePartName); } else { LOG_ERROR("Partname must be specified with -p option in command line for generating a key file"); } // If AES key is not mentioned, generate it, otherwise set the AES key if (key == "") { GenerateAesKey(); } else { SetAesKeyString(key); } // If CBC key is not mentioned, generate it, otherwise set the CBC key if (initialVector == "") { GenerateCbc(); } else { setCbcString(initialVector); } // If HMAC key is not mentioned, generate it, otherwise set the HMAC key if (hmac == "") { GenerateHmacKey(); } else { SetHmacKeyString(hmac); } // Write all the encryption keys to a file WriteEncryptionKeyFile(baseFileName); } /******************************************************************************/ void ZynqEncryptionContext::AES_Encrypt(const uint8_t* inputData, uint32_t inputDataByteLength, uint8_t* encryptedData) { uint32_t inputDataAESBlockCount; uint8_t * encryptedDataPtr = encryptedData; uint32_t dataValue; // Check if message has correct block size if ((inputDataByteLength > 0) && ((inputDataByteLength % wordsPerAesBlock) != 0)) { LOG_DEBUG(DEBUG_STAMP, "Incorrect message bit length %ld, should be multiple of %ld bytes", inputDataByteLength, wordsPerAesBlock); LOG_ERROR("Encryption error !!!"); } // Make sure we have a initialized key schedule. if (keySchedule == NULL) { ClearKeySchedule(); } // Encrypt all AES blocks in the input data. inputDataAESBlockCount = inputDataByteLength / (sizeof(uint32_t) * wordsPerAesBlock); LOG_INFO("Encrypting %d bytes %d blocks", inputDataByteLength, inputDataAESBlockCount); for (uint32_t curr_AES_block_index = 0; curr_AES_block_index < inputDataAESBlockCount; curr_AES_block_index += 1) { if (inputDataAESBlockCount > 4) { loadBar(curr_AES_block_index, inputDataAESBlockCount - 1, 60, 60); } /* Convert incoming chars into array of ints */ if (first_AES_block == true) { first_AES_block = false; for (uint32_t index = 0; index < wordsPerAesBlock; index++) { //dataValue = ReadLittleEndian32( inputData ); dataValue = dataMover->ReadData32(inputData); // DataMovement dataValue ^= ReadBigEndian32(ivCbc + 4 * index); working_AES_block[index] = reverseDataBits(dataValue); inputData += sizeof(uint32_t); } } else { for (uint32_t index = 0; index < wordsPerAesBlock; index++) { //dataValue = ReadLittleEndian32( inputData ); dataValue = dataMover->ReadData32(inputData); // DataMovement /* !!!!!! This has to be done, why !!!!!! Reverse the bit order of each 32 bit value of the non-encrypted input data. */ dataValue = reverseDataBits(dataValue); working_AES_block[index] ^= dataValue; inputData += sizeof(uint32_t); } } // 0th round key addition AddRoundKey(working_AES_block, 0); // Nr - 1 rounds of AES (BS, SR, MRC, ARK) for (uint32_t round = 1; round < d_NumRounds; round++) { ByteSubTransformation(working_AES_block); ShiftRowTransformation(working_AES_block); MixColumnTransformation(working_AES_block); AddRoundKey(working_AES_block, round); } // Last round (BS, SR, ARK) Byte sub transformation ByteSubTransformation(working_AES_block); ShiftRowTransformation(working_AES_block); AddRoundKey(working_AES_block, d_NumRounds); // write out the encrypted AES block. for (uint32_t index = 0; index < wordsPerAesBlock; index++) { dataValue = working_AES_block[index]; /* !!!!!! This has to be done, why !!!!!! Reverse the bit order of each 32 bit value of the non-encrypted input data. */ dataValue = reverseDataBits(dataValue); //WriteLittleEndian32( encryptedDataPtr, dataValue ); dataMover->WriteData32(encryptedDataPtr, dataValue); // DataMovement encryptedDataPtr += sizeof(uint32_t); } } } /******************************************************************************/ void ZynqEncryptionContext::ComputeHMACDigest(const uint8_t* data, const uint32_t dataByteLength, bool initializeNewDigest, uint8_t* digest) { uint32_t dataBitLength = dataByteLength * BITS_IN_BYTE; // Check if message has correct block size if ((dataBitLength > 0) && ((dataBitLength % BITS_PER_SHA_BLOCK) != 0)) { LOG_DEBUG(DEBUG_STAMP, "Incorrect message bit length %ld for SHA256 computation, should be a multiple of %ld bits", (uint32_t)dataBitLength, (uint32_t)BITS_PER_SHA_BLOCK); LOG_ERROR("Encryption error !!!\n Error while calculating HMAC Digest"); } uint32_t a, b, c, d, e, f, g, h; uint32_t T1, T2; uint32_t Wi[64]; uint32_t Hi[8]; uint32_t index; /* Initialize the hash if requested. Otherwise continue calculating the hash with the new data given. */ if (initializeNewDigest == true) { // Start with the inital SHA256 hash values. for (index = 0; index < WORDS_PER_HMAC_KEY; ++index) { Hi[index] = H0_256[index]; } } else { // Start with the previous hash values. for (index = 0; index < WORDS_PER_HMAC_KEY; ++index) { //Hi[ index ] = ReadLittleEndian32( digest ); Hi[index] = dataMover->ReadData32(digest); // DataMovement digest += sizeof(uint32_t); } // Restore the digest pointer to it's previous value. digest -= BYTES_PER_HMAC_KEY; } #if 0 LOG_TRACE("HMAC Message data of %d bytes", dataByteLength); #endif while (dataBitLength > 0) { // Prepare message digest. First 16 integers are from the message for (index = 0; index < 16; ++index) { //Wi[ index ] = ReadLittleEndian32( data ); Wi[index] = dataMover->ReadData32(data); // DataMovement data += sizeof(uint32_t); dataBitLength -= sizeof(uint32_t) * BITS_IN_BYTE; } for (index = 16; index < 64; ++index) { Wi[index] = sigma_1(Wi[index - 2]) + Wi[index - 7] + sigma_0(Wi[index - 15]) + Wi[index - 16]; } // Initialize working variables a = Hi[0]; b = Hi[1]; c = Hi[2]; d = Hi[3]; e = Hi[4]; f = Hi[5]; g = Hi[6]; h = Hi[7]; // Compute working variables for (index = 0; index < 64; ++index) { T1 = h + c_sigma_1(e) + Ch(e, f, g) + K_256[index] + Wi[index]; T2 = c_sigma_0(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } // Compute intermediate hash Hi[0] += a; Hi[1] += b; Hi[2] += c; Hi[3] += d; Hi[4] += e; Hi[5] += f; Hi[6] += g; Hi[7] += h; } for (index = 0; index < WORDS_PER_HMAC_KEY; ++index) { //WriteLittleEndian32(digest, Hi[ index ]); dataMover->WriteData32(digest, Hi[index]); // DataMovement digest += sizeof(uint32_t); } } /******************************************************************************/ DataStreamEncryption::DataStreamEncryption(uint32_t words_per_AES_block0, uint32_t words_per_AES_key0) : ZynqEncryptionContext(words_per_AES_block0, words_per_AES_key0) , input_data_Buffer(NULL) , stream_header(NULL) , input_data_ByteLength(0) { memset(ipad_data, 0, BYTES_PER_IPAD); memset(pad1_data, 0, BYTES_PER_PAD1); memset(gap_2048, 0, BYTES_PER_2048_GAP); memset(opad_data, 0, BYTES_PER_OPAD); memset(first_digest_gap, 0, BYTES_PER_FIRST_DIGEST); memset(pad2_data, 0, BYTES_PER_PAD2); memset(HMAC_digest, 0, BYTES_PER_HMAC_DIGEST); memset(calculated_first_digest, 0, BYTES_PER_FIRST_DIGEST + BYTES_PER_PAD2); } /******************************************************************************/ DataStreamEncryption::~DataStreamEncryption(void) { if (input_data_Buffer != NULL) delete[] input_data_Buffer; } /******************************************************************************/ void DataStreamEncryption::SetDataStreamHeader(KeySource::Type keySource, uint32_t encryptedStreamByteLength, uint32_t* presBitHdr, uint32_t presBitHdrSize) { uint32_t encryptedKeySource = BBRAM_KEY_SOURCE; uint32_t keySourceOffset; uint32_t encryptionEnableOffset; uint32_t cbcOffset; uint32_t encryptLengthOffset; std::string test = EncryptionContext::aesFilename; if (presBitHdrSize == 0) { stream_header = (uint8_t*)malloc(BYTES_PER_STREAM_HEADER); keySourceOffset = ENCRYPTION_KEY_SRC_OFFSET; encryptionEnableOffset = ENCRYPTION_ENABLE_WORD_OFFSET; cbcOffset = CBC_WORD_OFFSET; encryptLengthOffset = ENCRYPTION_DATA_LENGTH_OFFSET; for (uint8_t i = 0, j = 0; iWriteData32(&stream_header[j], defaultStreamHeader[i]); } } else { uint32_t presBitHdrBytes = presBitHdrSize * sizeof(uint32_t); stream_header = (uint8_t*)malloc(BYTES_PER_FPGA_STREAM_HEADER + presBitHdrBytes); keySourceOffset = FPGA_ENCRYPTION_KEY_SRC_OFFSET + presBitHdrBytes; encryptionEnableOffset = FPGA_ENCRYPTION_ENABLE_WORD_OFFSET + presBitHdrBytes; cbcOffset = FPGA_CBC_WORD_OFFSET + presBitHdrBytes; encryptLengthOffset = FPGA_ENCRYPTION_DATA_LENGTH_OFFSET + presBitHdrBytes; uint32_t j = 0; for (uint32_t i = 0; iWriteData32(&stream_header[j], presBitHdr[i]); } for (uint32_t i = 0; iWriteData32(&stream_header[j], defaultFpgaStreamHeader[i]); } } /* Get the correct value for the encryption source. */ if (keySource == KeySource::EfuseRedKey) { encryptedKeySource = EFUSE_KEY_SOURCE; } else if (keySource == KeySource::BbramRedKey) { encryptedKeySource = BBRAM_KEY_SOURCE; } else { LOG_ERROR("Key source %d not supported", (int)keySource); } /*For bitstreams, the mask flag needs to be set before the actual control word 0x3000C001, // 32 Type1 write 1 words to MASK 0x00000040, // 36 data word 1 0x3000A001, // 40 Type1 write 1 words to CTL 0x00000040, // 44 dec The command to mask (0x3000C001) followed by the data which specifies which bits to mask. All the bits needs to be masked which are of significance in the next command transaction. The command to config (0x3000A001) is followed by the actual data to set. For EFUSE, the bit 31 should be set For BBRAM, the bit 31 should be clear For setting the bit 31 in case of efuse, corresponding mask bit should be set Example: For enabling EFUSE, 0x3000C001, // 32 Type1 write 1 words to MASK 0x80000040, // 36 efuse mask bit31 (0x80000000) 0x3000A001, // 40 Type1 write 1 words to CTL 0x80000040, // 44 set efuse bits Ideally this should be done for both Zynq & FPGAs. But as these bits are not of much significance in case of Zynq, as the key selection is done by BootROM, and in case of FPGAs the key selection depends on these bits. Inorder to maintain backward compatibility w.r.t earlier versions of Zynq images and not to disturb the current regression test suite, this mask setting is done only for FPGA arch and not Zynq arch. This flag tells whether to set the mask bits or not */ if (maskEfuseFlag) { dataMover->WriteData32(&stream_header[keySourceOffset], encryptedKeySource | ENCRYPTION_ENABLE); } /* Turn on encryption, and include the decryption key source. */ dataMover->WriteData32(&stream_header[encryptionEnableOffset], encryptedKeySource | ENCRYPTION_ENABLE); /* Update the CBC in the stream header */ const uint8_t* cbc = GetCbc(); for (uint8_t i = 0; iWriteData32(&stream_header[cbcOffset + i], ReadLittleEndian32(cbc + i)); } /* Finally, set the encrypted word length */ dataMover->WriteData32(&stream_header[encryptLengthOffset], encryptedStreamByteLength / sizeof(uint32_t)); } /******************************************************************************/ void DataStreamEncryption::InitializeInputDataStream(const uint8_t* inputData, uint32_t inputDataByteLength, bool isFPGAData) { /* If this is NOT FPGA data, add the special bit stream header that sends data through the PCAP "loop back" interface on Zynq. This needs changing when later architectures come along. */ // Add in the header if needed input_data_ByteLength = inputDataByteLength; if (isFPGAData == false) { input_data_ByteLength += sizeof(defaultPcapHeader); } /* Round up the length to the nearest 512 bit boundary for proper AES/HMAC encryption */ uint32_t misAlignedByteSize = input_data_ByteLength % (512 / BITS_IN_BYTE); if (misAlignedByteSize != 0) { misAlignedByteSize = (512 / BITS_IN_BYTE) - misAlignedByteSize; input_data_ByteLength += misAlignedByteSize; } /* Allocate a buffer to hold the user data plus any header and padding NOOPs */ input_data_Buffer = new uint8_t[input_data_ByteLength]; if (input_data_Buffer == NULL) { LOG_DEBUG(DEBUG_STAMP, "Out of memory"); LOG_ERROR("Ercryption error !!!"); } uint8_t* inputDataStreamPtr = input_data_Buffer; // Add the header if needed. if (isFPGAData == false) { // Set the user's data word length in the write to the PCAP transfer register. Cap it at 27 bits. uint32_t inputDataWordLength = (inputDataByteLength / sizeof(uint32_t)) & 0x7FFFFFF; // Assemble the Pcap commands WriteLittleEndian32(inputDataStreamPtr, defaultPcapHeader[0]); inputDataStreamPtr += sizeof(uint32_t); WriteLittleEndian32(inputDataStreamPtr, defaultPcapHeader[1] | inputDataWordLength); inputDataStreamPtr += sizeof(uint32_t); } // Copy the user data to the buffer. memmove(inputDataStreamPtr, inputData, inputDataByteLength); // Point to where pading NOOPs should start. inputDataStreamPtr += inputDataByteLength; // Add any alignment NOOPs to the end of the buffer, align to a HMAC 512 bit boundary. while (misAlignedByteSize > 0) { // Write the next padding NOOP. WriteLittleEndian32(inputDataStreamPtr, BIT_STREAM_NOOP_COMMAND); // Go to the next padding NOOP. misAlignedByteSize -= sizeof(uint32_t); inputDataStreamPtr += sizeof(uint32_t); } } /******************************************************************************/ void DataStreamEncryption::InitializeHMAC_ioPadData(uint8_t padByte, uint8_t* padBuffer) { /* Setup the ioPad buffer with it's default value. ioPad buffers are really 512 bits long, HMAC keys are only 256 bits long. So use the byte length times 2 to initialize the entire buffer. This will set the second half of the HMAC key to the default iPad or oPad value. */ memset(padBuffer, padByte, BYTES_PER_HMAC_KEY * 2); /* The HMAC key goes into the first half of the ioPad. (Was wrong and used to say "second half"). */ const uint8_t* HMACKeyPtr = GetHmacKey(); uint32_t* padBufferWordPtr = (uint32_t *)padBuffer; for (uint32_t index = 0; index < WORDS_PER_HMAC_KEY; index += 1) { // XOR the HMAC key into the ioPad. //padBufferWordPtr[ index ] ^= ReadLittleEndian32( HMACKeyPtr ); uint32_t temp; const uint8_t *temp1; temp = padBufferWordPtr[index] ^ ReadLittleEndian32(HMACKeyPtr); temp1 = (uint8_t*)padBufferWordPtr; //WriteBigEndian32(&padBufferWordPtr[index], temp); dataMover->WriteData32(&temp1[4 * index], temp); HMACKeyPtr += sizeof(uint32_t); } } /******************************************************************************/ void DataStreamEncryption::InitializePad1Data(uint32_t pad1DataByteLength) { // Make sure it's cleared out. memset(pad1_data, 0, BYTES_PER_PAD1); // Set the first bit in the pad 1 buffer. //WriteLittleEndian32( pad1_data, 0x80000000 ); dataMover->WriteData32(pad1_data, 0x80000000); // DataMovement // Set the length in bits. uint64_t length = pad1DataByteLength * BITS_IN_BYTE; //WriteLittleEndian32(&pad1_data[BYTES_PER_PAD1-2*sizeof(uint32_t)] ,(length>>32) & 0xFFFFFFFF); dataMover->WriteData32(&pad1_data[BYTES_PER_PAD1 - 2 * sizeof(uint32_t)], (length >> 32) & 0xFFFFFFFF); // DataMovement //WriteLittleEndian32(&pad1_data[BYTES_PER_PAD1-1*sizeof(uint32_t)] ,(length ) & 0xFFFFFFFF); dataMover->WriteData32(&pad1_data[BYTES_PER_PAD1 - 1 * sizeof(uint32_t)], (length) & 0xFFFFFFFF); // DataMovement } /******************************************************************************/ void DataStreamEncryption::InitializePad2Data(uint32_t pad2DataByteLength) { // Make sure it's cleared out. memset(pad2_data, 0, BYTES_PER_PAD2); // Set the first bit in the pad 2 buffer. //WriteLittleEndian32( pad2_data, 0x80000000 ); dataMover->WriteData32(pad2_data, 0x80000000); // DataMovement // Set the length in bits. uint64_t length = pad2DataByteLength * BITS_IN_BYTE; //WriteLittleEndian32(&pad2_data[BYTES_PER_PAD2-2*sizeof(uint32_t)], (length>>32) & 0xFFFFFFFF); dataMover->WriteData32(&pad2_data[BYTES_PER_PAD2 - 2 * sizeof(uint32_t)], (length >> 32) & 0xFFFFFFFF); // DataMovement //WriteLittleEndian32(&pad2_data[BYTES_PER_PAD2-1*sizeof(uint32_t)], (length) & 0xFFFFFFFF); dataMover->WriteData32(&pad2_data[BYTES_PER_PAD2 - 1 * sizeof(uint32_t)], (length) & 0xFFFFFFFF); // DataMovement } /******************************************************************************/ void DataStreamEncryption::EncryptDataStream(uint8_t* encryptedData) { InitKeySchedule(); AES_Encrypt(ipad_data, BYTES_PER_IPAD, encryptedData); encryptedData += BYTES_PER_IPAD; AES_Encrypt(input_data_Buffer, input_data_ByteLength, encryptedData); encryptedData += input_data_ByteLength; AES_Encrypt(pad1_data, BYTES_PER_PAD1, encryptedData); encryptedData += BYTES_PER_PAD1; AES_Encrypt(gap_2048, BYTES_PER_2048_GAP, encryptedData); encryptedData += BYTES_PER_2048_GAP; AES_Encrypt(opad_data, BYTES_PER_OPAD, encryptedData); encryptedData += BYTES_PER_OPAD; AES_Encrypt(first_digest_gap, BYTES_PER_FIRST_DIGEST, encryptedData); encryptedData += BYTES_PER_FIRST_DIGEST; AES_Encrypt(pad2_data, BYTES_PER_PAD2, encryptedData); encryptedData += BYTES_PER_PAD2; AES_Encrypt(HMAC_digest, BYTES_PER_HMAC_DIGEST, encryptedData); } /******************************************************************************/ void DataStreamEncryption::AESDataStreamEncrypt(KeySource::Type keySource, bool isFPGAData, const uint8_t *inputData, uint32_t inputDataByteLength, uint8_t *& encryptedData, uint32_t & encryptedDataByteLength, uint32_t* presBitHdr, uint32_t presBitHdrSize) { uint32_t streamHdrSize = 0; if (presBitHdrSize != 0) { streamHdrSize = BYTES_PER_FPGA_STREAM_HEADER + presBitHdrSize * sizeof(uint32_t); } else { streamHdrSize = BYTES_PER_STREAM_HEADER; } /* Check if message has correct block size */ if (((inputDataByteLength * BITS_IN_BYTE) % BITS_IN_A_WORD) != 0) { LOG_DEBUG(DEBUG_STAMP, "Incorrect message bit length %ld for encryption, needs be a multiple of %ld bits", (uint32_t)(inputDataByteLength * BITS_IN_BYTE), (uint32_t)BITS_IN_A_WORD); LOG_ERROR("Encryption error !!!"); } /* Prepare the user data to be encrypted, and add any padding that may be needed */ InitializeInputDataStream(inputData, inputDataByteLength, isFPGAData); /* Now that we know the final data length of the encrypted data stream, add that length to the stream header */ uint32_t encryptedStreamByteLength = BYTES_PER_IPAD + input_data_ByteLength + BYTES_PER_PAD1 + BYTES_PER_2048_GAP + BYTES_PER_OPAD + BYTES_PER_FIRST_DIGEST + BYTES_PER_PAD2 + BYTES_PER_HMAC_DIGEST; SetDataStreamHeader(keySource, encryptedStreamByteLength, presBitHdr, presBitHdrSize); /* Initalize the iPad data Ipad data is 512 bits long, with each filled with a 0x36, and the last 256 bit XOR'd with the HMAC key */ InitializeHMAC_ioPadData(HMAC_IPAD_BYTE, ipad_data); /* Default the 2048 bit gap to zero. This is to ensure that the first digest round (of the iPad and input data) is completed when the HW is calculating it */ memset(gap_2048, 0, BYTES_PER_2048_GAP); /* Initalize the oPad data Ipad data is 512 bits long, with each filled with a 0x5C, and the last 256 bit XOR'd with the HMAC key */ InitializeHMAC_ioPadData(HMAC_OPAD_BYTE, opad_data); /* Default the first digest gap to zero This gap repersents the HMAC digest of the iPad and input data stream, and will be replaced by the HW with the HW calculated first digest value */ memset(first_digest_gap, 0, BYTES_PER_FIRST_DIGEST); /* Initalize the pad1 data. It contains the bit length (from the byte values given here) of the iPad and input data stream */ InitializePad1Data(BYTES_PER_IPAD + input_data_ByteLength); /* Calculate the first digest. This is the HMAC digest of the iPad, input data stream, and pad1. This is used when the final digest is calculated at the same place as were the first_digest_gap is */ // Start off with the IPAD data. ComputeHMACDigest(ipad_data, BYTES_PER_IPAD, true, calculated_first_digest); // Add in the user data. ComputeHMACDigest(input_data_Buffer, input_data_ByteLength, false, calculated_first_digest); // Finally add in the PAD1 data. ComputeHMACDigest(pad1_data, BYTES_PER_PAD1, false, calculated_first_digest); /* Initalize the pad2 data. It contains the bit length (from the byte values given here) of the oPad and first digest gap. */ InitializePad2Data(BYTES_PER_OPAD + BYTES_PER_FIRST_DIGEST); /* Calculate the final HMAC digest. This is the HMAC digest of the oPad, input data stream, and pad2. This is by the HW to compare against to authenticate the entire data stream. Note: Also, a bit of a hack here. Both the first digest and pad2 are only 265 bits long, but for HMAC, the smallest unit can only 512 bits. So we double the size of the calculated digest field, and copy the pad2 to the second half so that the digest and pad2 can be HMAC'd together. */ ComputeHMACDigest(opad_data, BYTES_PER_OPAD, true, HMAC_digest); memcpy(calculated_first_digest + BYTES_PER_FIRST_DIGEST, pad2_data, BYTES_PER_PAD2); ComputeHMACDigest(calculated_first_digest, BYTES_PER_FIRST_DIGEST + BYTES_PER_PAD2, false, HMAC_digest); /* Create a new buffer that contains the entire data stream, plus 16 NOP commands at the end, and return it */ encryptedDataByteLength = encryptedStreamByteLength + streamHdrSize + (16 * sizeof(BIT_STREAM_NOOP_COMMAND)); /* Partitions must have the length 32 byte aligned because of a HW bug in the PCAP DMA engine. */ uint32_t dataStream32ByteMisalignment = 32 - encryptedDataByteLength % 32; /* Get a new buffer for the encrypted data and overhead */ encryptedData = new uint8_t[encryptedDataByteLength + dataStream32ByteMisalignment]; if (encryptedData == NULL) { LOG_DEBUG(DEBUG_STAMP, "Out of memory"); LOG_ERROR("Ercryption error !!!"); } uint8_t* ptr = encryptedData; /* Copy the data stream header to the return */ memcpy(ptr, stream_header, streamHdrSize); ptr += streamHdrSize; /* Encrypt the entire data stream from the iPad to the HMAC digest into the return buffer */ EncryptDataStream(ptr); ptr += encryptedStreamByteLength; /* Add 16 NOP commands to the end of the encrypted stream to ensure that the HMAC engine finishes verifiy the HMAC digest before the user checks the HMAC_Error bit. Also, add in any NOOPs needed to align the encrypted data size to 32 bytes */ uint32_t NOOPLimit = 16 + (dataStream32ByteMisalignment / sizeof(uint32_t)); for (uint32_t index = 0; index < NOOPLimit; index += 1) { //WriteLittleEndian32(ptr, BIT_STREAM_NOOP_COMMAND); dataMover->WriteData32(ptr, BIT_STREAM_NOOP_COMMAND); // DataMovement ptr += sizeof(BIT_STREAM_NOOP_COMMAND); } } xilinx-bootgen-2024.2/encryption-zynq.h000077500000000000000000000122271475706442400201370ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _ENCRYPTION_ZYNQ_CONTEXT_ #define _ENCRYPTION_ZYNQ_CONTEXT_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "encryption.h" #include "encryptutils.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqEncryptionContext : public EncryptionContext { public: ZynqEncryptionContext(); ZynqEncryptionContext(const EncryptionContext* other); ZynqEncryptionContext(uint32_t wordsPerAesBlock, uint32_t words_per_AES_key0); ~ZynqEncryptionContext(); Encryption::Type Type() { return Encryption::AES; } void ReadEncryptionKeyFile(const std::string& keyFileName); void GenerateEncryptionKeyFile(const std::string& baseFileName, Options& options); void WriteEncryptionKeyFile(const std::string& baseFileName, bool useOptionalKey = false, uint32_t blocks = 0); void Process(BootImage& bi, PartitionHeader* partition); void GenerateTempKeys(void); void EncryptKeys(const uint8_t* inputData, uint32_t inputDataByteLength, uint8_t* encryptedData); void ClearKeySchedule(void); void InitKeySchedule(void); void AES_Encrypt(const uint8_t* inputData, uint32_t inputDataByteLength, uint8_t* encryptedData); void ComputeHMACDigest(const uint8_t* data, const uint32_t dataByteLength, bool initializeNewDigest, uint8_t* digest); void GenerateAesKey(void); void SetAesKey(const uint8_t* binarykey); const uint8_t* GetAesKey(void); void GenerateCbc(void); void setCbcString(const std::string& ASCIIinitialVector); void SetCbc(const uint8_t * binaryinitialVector); const uint8_t* GetCbc(void); void GenerateHmacKey(void); void SetHmacKeyString(const std::string& asciiHMACKey); void SetHmacKey(const uint8_t * binaryHMACKey); const uint8_t* GetHmacKey(void); DataMover* dataMover; bool maskEfuseFlag; private: void AddRoundKey(uint32_t* int_array, uint32_t num_round); void ByteSubTransformation(uint32_t* int_array); void ShiftRowTransformation(uint32_t* int_array); void MixColumnTransformation(uint32_t* int_array); uint32_t CvtChars2Int(uint8_t value1, uint8_t value2, uint8_t value3, uint8_t value4); uint32_t Transform(uint32_t orig_col, uint32_t col_num, bool rotate_rcon); bool first_AES_block; uint32_t d_NumRounds; uint32_t wordsPerAesKey; uint32_t wordsPerAesBlock; uint32_t* working_AES_block; uint32_t* keySchedule; uint32_t* aesKey; uint8_t ivCbc[16]; uint32_t* hmacKey; }; /******************************************************************************/ class DataStreamEncryption : public ZynqEncryptionContext { public: DataStreamEncryption(uint32_t wordsPerAesBlock, uint32_t words_per_AES_key0); ~DataStreamEncryption(void); void AESDataStreamEncrypt(KeySource::Type keySource, bool isFPGAData, const uint8_t* inputData, uint32_t inputDataByteLength, uint8_t*& encryptedDataStream, uint32_t& encryptedBufferByteLength, uint32_t* presBitHdr, uint32_t presBitHdrSize); private: void SetDataStreamHeader(KeySource::Type keySource, uint32_t encryptedStreamByteLength, uint32_t* presBitHdr, uint32_t presBitHdrSize); void InitializeInputDataStream(const uint8_t* inputData, uint32_t inputDataByteLength, bool isFPGAData); void InitializeHMAC_ioPadData(uint8_t padByte, uint8_t * padBuffer); void InitializePad1Data(uint32_t pad1DataByteLength); void InitializePad2Data(uint32_t pad2DataByteLength); void EncryptDataStream(uint8_t* encryptedOutputData); uint8_t* stream_header; uint8_t ipad_data[BYTES_PER_IPAD]; uint8_t* input_data_Buffer; uint32_t input_data_ByteLength; uint8_t pad1_data[BYTES_PER_PAD1]; uint8_t gap_2048[BYTES_PER_2048_GAP]; uint8_t opad_data[BYTES_PER_OPAD]; uint8_t first_digest_gap[BYTES_PER_FIRST_DIGEST]; uint8_t pad2_data[BYTES_PER_PAD2]; uint8_t HMAC_digest[BYTES_PER_HMAC_DIGEST]; uint8_t calculated_first_digest[BYTES_PER_FIRST_DIGEST + BYTES_PER_PAD2]; }; #endif xilinx-bootgen-2024.2/encryption-zynqmp.cpp000077500000000000000000001313231475706442400210260ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------------------------ **************************************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------------------------ */ #include "encryption-zynqmp.h" #include "bootimage.h" #include "encryptutils.h" #include "options.h" #include "encryptutils.h" #include "fileutils.h" #include #include "obfskutil.h" /* ------------------------------------------------------------------------------------------------ ********************************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------------------------ */ /******************************************************************************/ ZynqMpEncryptionContext::ZynqMpEncryptionContext() : isBootloader(false) , aesSeedexits(false) , partNum(0) { encryptionAlgorithm = new AesGcmEncryptionContext(); }; /******************************************************************************/ ZynqMpEncryptionContext::ZynqMpEncryptionContext(const EncryptionContext* other) : isBootloader(false) , aesSeedexits(false) , partNum(0) { aesFilename = other->aesFilename; encryptionAlgorithm = new AesGcmEncryptionContext(); } /******************************************************************************/ ZynqMpEncryptionContext::~ZynqMpEncryptionContext() { if (encryptionAlgorithm) { delete encryptionAlgorithm; } if (aesKey) { delete aesKey; } if (aesIv) { delete aesIv; } if (aesSeed) { delete aesSeed; } if (outBufKDF) { delete outBufKDF; } if (fixedInputData) { delete fixedInputData; } }; /******************************************************************************/ void ZynqMpEncryptionContext::SetAesKey(const uint8_t* key) { aesKey = new uint32_t[WORDS_PER_AES_KEY]; for (uint32_t index = 0; index < WORDS_PER_AES_KEY; index++) { aesKey[index] = ReadBigEndian32(key); key += sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpEncryptionContext::SetAesSeedString(const std::string& key) { uint8_t hexData[256]; if (key.size() != (WORDS_PER_AES_KEY * 8)) { LOG_DEBUG(DEBUG_STAMP, "Seed size - %d", key.size()); LOG_ERROR("An AES Seed must be 256 bits long - %s", key.c_str()); } PackHex(key, hexData); SetAesSeed(hexData); } /******************************************************************************/ void ZynqMpEncryptionContext::GenerateAesKey(void) { uint32_t keysize = WORDS_PER_AES_KEY * sizeof(uint32_t); uint8_t newKey[BYTES_PER_AES_KEY]; RAND_bytes(newKey, keysize); SetAesKey(newKey); LOG_INFO("AES Key generated successfully"); } /******************************************************************************/ void ZynqMpEncryptionContext::GetEncryptionKeys(Options& options, uint8_t* aesKey, uint8_t* aesOptKey, uint8_t* aesIV) { const uint32_t* tmpKey = GetAesKey(); if (tmpKey != NULL) { memcpy_be(aesKey, tmpKey, AES_GCM_KEY_SZ); } else { LOG_ERROR("Encryption Error !!!\n Key 0 does not exist in the AES key file "); } if (options.bifOptions->GetAesOptKeyFlag()) { const uint32_t* tmpOptKey = GetAesOptKey(); if (tmpOptKey != NULL) { memcpy_be(aesOptKey, tmpOptKey, AES_GCM_KEY_SZ); } else { LOG_ERROR("Encryption Error !!!\n Operational Key 'Key Opt' does not exist in the AES key file "); } } const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { memcpy_be(aesIV, tmpIv, AES_GCM_IV_SZ); } else { LOG_ERROR("IV does not exist in the AES key file "); } } /******************************************************************************/ void ZynqMpEncryptionContext::WriteEncryptionKeyFile(const std::string & baseFileName, bool useOptionalKey, uint32_t blocks) { uint32_t x, y, index; /* Setup the file for writing */ std::string ext = StringUtils::GetExtension(baseFileName); std::string filename; if (ext == "") { filename = baseFileName + ".nky"; } else { filename = baseFileName; } std::ofstream keyFile(filename.c_str()); if (!keyFile) { LOG_ERROR("Failure writing AES key file", filename.c_str()); } /* Write device name */ if (deviceName != "") { keyFile << "Device " << deviceName << ";\n"; keyFile << "\n"; } /* Ko can then be used for key/iv pairs */ for (x = 0; x < blocks; x++) { keyFile << "Key " << std::dec << x; keyFile << " "; if (x == 0 && GetAesKey() != NULL) { for (index = 0; index < WORDS_PER_AES_KEY; ++index) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << aesKey[index]; } } else { for (y = 0; y < WORDS_PER_AES_KEY; y++) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << outBufKDF[11 * x + y]; } } keyFile << ";\n"; keyFile << "IV " << std::dec << x; keyFile << " "; if (x == 0 && GetIv() != NULL) { for (y = 0; y < WORDS_PER_IV; ++y) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << aesIv[y]; } } else { for (y = WORDS_PER_AES_KEY; y < WORDS_PER_AES_KEY + WORDS_PER_IV; y++) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << outBufKDF[11 * x + y]; } } keyFile << ";\n"; keyFile << "\n"; } if (useOptionalKey == true) { keyFile << "Key Opt "; if (GetAesOptKey() != NULL) { for (y = 0; y < WORDS_PER_AES_KEY; ++y) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << aesOptKey[y]; } } else { for (y = 0; y < WORDS_PER_AES_KEY; y++) { keyFile << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << outBufKDF[11 * x + y]; } } keyFile << ";\n"; } } /******************************************************************************/ void ZynqMpEncryptionContext::ReadEncryptionKeyFile(const std::string& inputFileName) { LOG_TRACE("Reading the AES key file"); int aesKeyNum = 0; int aesIvNum = 0; // Get the encryption key file name std::ifstream keyFile(inputFileName.c_str()); aesKeyVec.clear(); aesIvVec.clear(); if (!keyFile) { LOG_ERROR("Failure reading AES key file - %s", inputFileName.c_str()); } while (keyFile) { std::string word; keyFile >> word; // If file vacant if (word == "") { return; } char c = ' '; // First Word is "Key" if (word == "Key") { keyFile >> word; // Second Word is "Opt" if (word == "Opt") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (word == "pick") { GenerateAesOptKey(); } else { SetAesOptKeyString(word); } } // Second Word is "0" else if (word != "" && isalnum(word[0])) { int index = std::stoi(word); if (aesKeyNum != index) { LOG_DEBUG(DEBUG_STAMP, "Key order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesKeyNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } // Third Word is "pick" - then generate AES key, otherwise set the key specified if (word == "pick") { GenerateAesKey(); } else { if (aesKeyVec.size() == 0) { SetAesKeyString(word); } aesKeyVec.push_back(word); } } // Second Word other than "0", "StartCBC" or "HMAC" - throw error else { LOG_DEBUG(DEBUG_STAMP, "Unknown key type - '%s' in %s", word.c_str(), inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } } // If first word is not "Key" but "Device" else if (word == "Device") { word = ""; keyFile >> word; /*while( (keyFile >> c) && (isalnum(c) || c=='-' || c=='_') ) { word.push_back(c); }*/ c = word[word.size() - 1]; word.erase(word.size() - 1); deviceName = word; } else if (word == "IV") { keyFile >> word; if (word != "") { if (word.size() == ((BYTES_PER_IV * 2) + 1)) { c = word[word.size() - 1]; word.erase(word.size() - 1); SetIvString(word); } else { int index = std::stoi(word); if (aesIvNum != index) { LOG_DEBUG(DEBUG_STAMP, "Iv order incorrect."); LOG_ERROR("Error parsing AES key file - %s.", inputFileName.c_str()); } aesIvNum++; word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } if (word == "pick") { GenerateIv(); } else { if (aesIvVec.size() == 0) { SetIvString(word); } } } aesIvVec.push_back(word); } } else if (word == "Seed") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } SetAesSeedString(word); aesSeedexits = true; } else if (word == "Label") { LOG_ERROR("The input 'Label' is deprecated.\n\t Please construct a FixedInputData of 60 Bytes instead and provide the same in the nky file.This will be used along with Seed in KDF."); } else if (word == "Context") { LOG_ERROR("The input 'Context' is deprecated.\n\t Please construct a FixedInputData of 60 Bytes instead and provide the same in the nky file.This will be used along with Seed in KDF."); } else if (word == "FixedInputData") { word = ""; while ((keyFile >> c) && isalnum(c)) { word.push_back(c); } SetAesFixedInputDataString(word); fixedInputDataExits = true; } // If first word is neither "Key" nor "Device" else { LOG_DEBUG(DEBUG_STAMP, "'Key' or 'Device' identifier expected, '%s' found instead", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } // Semicolons expected at end of every line if (c != ';') { while ((keyFile >> c) && isspace(c)) { word.push_back(c); } } if (c != ';') { LOG_DEBUG(DEBUG_STAMP, "Terminating ';' expected. Last word read was '%s'", word.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if (deviceName == "") { LOG_DEBUG(DEBUG_STAMP, "Partname 'Device' missing in the key file - %s", inputFileName.c_str()); LOG_ERROR("Error parsing AES key file - %s", inputFileName.c_str()); } if ((aesKeyVec.size() > 1 || aesIvVec.size() > 1) && aesSeedexits) { LOG_ERROR("Seed is not expected with multiple keys/Iv."); } if (fixedInputDataExits && !aesSeedexits) { LOG_ERROR("Seed must be specified along with FixedInputData."); } } } /******************************************************************************/ void ZynqMpEncryptionContext::PackNextEncryptionKey(uint8_t* aesKeyNext, int aeskeyPtr) { uint8_t hexData[AES_GCM_KEY_SZ]; uint8_t* hexDataPtr = hexData; if (aesKeyVec[aeskeyPtr].length() != (WORDS_PER_AES_KEY * 8)) { LOG_DEBUG(DEBUG_STAMP, "AES key %d size - %d", aeskeyPtr, aesKeyVec[aeskeyPtr].length()); LOG_ERROR("An AES key must be 256 bits long - %s", aesKeyVec[aeskeyPtr].c_str()); } if (aesKeyVec[aeskeyPtr].length() & 1) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - does not have even no. of hex digits", aesKeyVec[aeskeyPtr].c_str()); LOG_ERROR("Error parsing encryption key"); } for (uint32_t i = 0; iGetAesOptKeyFlag(); } if (GetAesKey() == NULL && !aesSeedexits) { LOG_ERROR("Encryption Error !!!\n Key 0 does not exist in the AES key file "); } if (options.bifOptions->GetAesOptKeyFlag()) { if (GetAesOptKey() == NULL && !aesSeedexits) { LOG_ERROR("Encryption Error !!!\n Operational Key 'Key Opt' does not exist in the AES key file "); } } if (GetIv() == NULL && !aesSeedexits) { LOG_ERROR("IV does not exist in the AES key file "); } if (aesKeyVec.size() != aesIvVec.size()) { LOG_ERROR("Encryption Error !!!\n Number of Keys in the AES key file are not equal to the number of IVs. "); } // If only seed exists in the given in nky file => No key0/iv0 mentioned. +1 to generate key0/IV0 for SH if (GetAesKey() == NULL && aesSeedexits) { blocks = options.bifOptions->GetEncryptionBlocksList().size() + 1 + useOptionalKey; LOG_TRACE("Keys for encryption will be generated based on the seed"); } else { blocks = options.bifOptions->GetEncryptionBlocksList().size() + useOptionalKey; if (aesSeedexits) { LOG_TRACE("Keys for encryption will be generated based on the seed"); } else { LOG_TRACE("Keys for encryption will be generated based on Key 0"); } } if (GetAesSeed() == NULL) { aesSeed = new uint32_t[WORDS_PER_AES_KEY]; memset(aesSeed, 0, WORDS_PER_AES_KEY); GenerateAesSeed(); } if (GetFixedInputData() == NULL) { fixedInputData = new uint32_t[WORDS_PER_FID]; memset(fixedInputData, 0, WORDS_PER_FID); GenerateAesFixedInputData(); } uint32_t outBufBytes = blocks * (AES_GCM_KEY_SZ + AES_GCM_IV_SZ); outBufKDF = new uint32_t[outBufBytes]; SetKdfLogFile(options.GetEncryptionDumpFlag()); uint32_t ret = kdf->CounterModeKDF(aesSeed, fixedInputData, fixedInputDataByteLength, outBufKDF, outBufBytes); if (ret != 0) { LOG_ERROR("Error generating encryption keys from Counter Mode KDF."); } uint8_t aesKeyNext[AES_GCM_KEY_SZ]; uint8_t aesIvNext[AES_GCM_IV_SZ]; for (x = 0; x blockList = options.bifOptions->GetEncryptionBlocksList(); uint8_t *aesIv = new uint8_t[AES_GCM_IV_SZ]; uint8_t *aesKey = new uint8_t[AES_GCM_KEY_SZ]; uint8_t *aesOptKey = new uint8_t[AES_GCM_KEY_SZ]; uint8_t *aesIVNext = new uint8_t[AES_GCM_IV_SZ]; uint8_t *aesKeyNext = new uint8_t[AES_GCM_KEY_SZ]; GetEncryptionKeys(options, aesKey, aesOptKey, aesIv); GetNextKey(aesKeyNext, 1); GetNextIv(aesIVNext, 1); if (partNum > 0) { uint8_t *x = new uint8_t[AES_GCM_IV_SZ]; memset(x, 0, AES_GCM_IV_SZ); *(x + AES_GCM_IV_SZ - 1) = partNum; *(aesIv + AES_GCM_IV_SZ - 1) = *(aesIv + AES_GCM_IV_SZ - 1) + *(x + AES_GCM_IV_SZ - 1); delete[] x; } // Extract the first block size uint32_t nextBlkSize = (blockList.empty()) ? inLen : blockList[0]; nextBlkSize = (nextBlkSize > inLen) ? inLen : nextBlkSize + 0; uint8_t secureHdr_in[AES_GCM_KEY_SZ + AES_GCM_IV_SZ + NUM_BYTES_PER_WORD]; uint32_t charZero = 0; if (options.bifOptions->GetAesOptKeyFlag()) { //Write the optional key from .nky file memcpy(secureHdr_in, aesOptKey, AES_GCM_KEY_SZ); if (isBootloader == false) { /* If optional key is enabled, then aesKey (boot key) needs to be used only encrypt the secure header Next block is encrypted using Opt Key. For all partitions, other than bootloader, don't use aesKey (bootkey), always use optional key Reason: The main idea to use optional key is to minimize the time of bootkey usage during booting process */ memcpy(aesKey, aesOptKey, AES_GCM_KEY_SZ); memset(secureHdr_in, 0, AES_GCM_KEY_SZ); memcpy(secureHdr_in, aesKeyNext, AES_GCM_KEY_SZ); } } else { /*Security Vulnerability : Reusing same AES / IV Key Pair*/ //Write Dummy key memset(secureHdr_in, charZero, AES_GCM_KEY_SZ); //Write Next key if (isBootloader == false) { memcpy(secureHdr_in, aesKeyNext, AES_GCM_KEY_SZ); } } // Block 0 IV(random generated), and the Block0 word size memcpy(secureHdr_in + AES_GCM_KEY_SZ, aesIVNext, AES_GCM_IV_SZ); WriteLittleEndian32(secureHdr_in + AES_GCM_KEY_SZ + AES_GCM_IV_SZ, nextBlkSize / NUM_BYTES_PER_WORD); int ct_len; uint8_t gcm_tag[AES_GCM_TAG_SZ]; /* Encrypt the Secure Header with device key and starting IV */ LOG_TRACE("Encrypting the Secure Header"); uint8_t* ptr = outBuf; encryptionAlgorithm->AesGcm256Encrypt(secureHdr_in, SECURE_HDR_SZ, aesKey, aesIv, NULL, 0, ptr, ct_len, gcm_tag); /* Attach the AES-GCM generated Hash Tag to end of the block */ memcpy(outBuf + ct_len, gcm_tag, AES_GCM_TAG_SZ); uint32_t outPtr = ct_len + AES_GCM_TAG_SZ; uint8_t secureHdr_out[1024]; int pt_len; uint32_t length = 0; if (options.GetEncryptionDumpFlag()) { uint32_t i = 0; VERBOSE_OUT << std::endl << " Secure Header"; VERBOSE_OUT << std::endl << " AES Key : "; for (i = 0; iAesGcm256Decrypt(secureHdr_out, pt_len, aesKey, aesIv, NULL, 0, outBuf, SECURE_HDR_SZ, gcm_tag); int ret = memcmp(secureHdr_in, secureHdr_out, SECURE_HDR_SZ); if (ret == 0) { //VERBOSE_OUT << " Encrypted secure header was successfully decrypted and tag matched\n"; } } uint32_t bytesWritten = 0; uint32_t inPtr = 0; uint32_t blkPtr = 1; //Take the next random generated IV for encryption /* Secure Header and Block 0 will be using the same IV, to have equal number of Keys and IVs from Key File. */ /*Security Vulnerability : Reusing same AES / IV Key Pair*/ memcpy(aesIv, aesIVNext, AES_GCM_IV_SZ); if (options.bifOptions->GetAesOptKeyFlag()) { if (isBootloader == false) { memcpy(aesKey, aesKeyNext, AES_GCM_KEY_SZ); } else { memcpy(aesKey, aesOptKey, AES_GCM_KEY_SZ); } } else { if (isBootloader == false) { memcpy(aesKey, aesKeyNext, AES_GCM_KEY_SZ); } } while (bytesWritten < inLen) { //Update the block size for current block and extract the next block size uint32_t currBlkSize = nextBlkSize; bytesWritten += currBlkSize; nextBlkSize = (blockList.size() > blkPtr) ? blockList[blkPtr] : inLen - bytesWritten; nextBlkSize = ((nextBlkSize + bytesWritten) > inLen) ? (inLen - bytesWritten) : (nextBlkSize + 0); /* Get next key and IV(random for next key from keyfile) for next block */ if (nextBlkSize == 0) { memset(aesKeyNext, 0, AES_GCM_KEY_SZ); memset(aesIVNext, 0, AES_GCM_IV_SZ); } else { GetNextKey(aesKeyNext, blkPtr + 1); GetNextIv(aesIVNext, blkPtr + 1); } uint8_t *gcm_pt = new uint8_t[currBlkSize + AES_GCM_KEY_SZ + AES_GCM_IV_SZ + NUM_BYTES_PER_WORD]; //Prepare the buffer for encryption //Actual block data + Next Block Key + Next Block IV + Next Block Word Size memcpy(gcm_pt, inBuf + inPtr, currBlkSize); inPtr += currBlkSize; memcpy(gcm_pt + currBlkSize, aesKeyNext, AES_GCM_KEY_SZ); memcpy(gcm_pt + currBlkSize + AES_GCM_KEY_SZ, aesIVNext, AES_GCM_IV_SZ); WriteLittleEndian32(gcm_pt + currBlkSize + AES_GCM_KEY_SZ + AES_GCM_IV_SZ, nextBlkSize / NUM_BYTES_PER_WORD); //Encrypt the consolidated block LOG_TRACE("Encrypting the block %d of size 0x%x of partition number %d", blkPtr, currBlkSize, partNum); encryptionAlgorithm->AesGcm256Encrypt(gcm_pt, currBlkSize + SECURE_HDR_SZ, aesKey, aesIv, NULL, 0, outBuf + outPtr, ct_len, gcm_tag); memcpy(outBuf + outPtr + ct_len, gcm_tag, AES_GCM_TAG_SZ); uint8_t* inBuf_out = new uint8_t[ct_len + AES_GCM_TAG_SZ]; if (options.GetEncryptionDumpFlag()) { uint32_t i = 0; /*VERBOSE_OUT << std::endl << std::dec << "Unencrypted Bootimage Data - block-" << currBlk << " Length-" << (currBlkSize+SECURE_HDR_SZ) << std::endl; int size = currBlkSize+SECURE_HDR_SZ; for(i=0; i<(currBlkSize+SECURE_HDR_SZ); i++) VERBOSE_OUT << "0x" << std::setfill('0') << std::setw(2) << std::hex << uint32_t(gcm_pt[i]) << " "; VERBOSE_OUT << std::endl; */ VERBOSE_OUT << std::endl << " Block " << blkPtr - 1; VERBOSE_OUT << std::endl << " AES Key : "; for (i = 0; iAesGcm256Decrypt(inBuf_out, pt_len, aesKey, aesIv, NULL, 0, outBuf + outPtr, ct_len, gcm_tag); int ret = memcmp(gcm_pt, inBuf_out, pt_len); if (ret == 0) { //VERBOSE_OUT << std::dec << " Encrypted block " << currBlk++ << " was successfully decrypted and tag matched\n"; } else { //VERBOSE_OUT << std::dec << " Encrypted block " << currBlk++ << " was failed in decryption and tag matching\n"; } } //Update the current key & IV outPtr += ct_len + AES_GCM_TAG_SZ; memcpy(aesIv, aesIVNext, AES_GCM_IV_SZ); memcpy(aesKey, aesKeyNext, AES_GCM_KEY_SZ); delete[] gcm_pt; delete[] inBuf_out; blkPtr++; } outLen = outPtr; delete[] aesIv; delete[] aesKey; delete[] aesIVNext; delete[] aesKeyNext; delete[] aesOptKey; } /******************************************************************************/ void ZynqMpEncryptionContext::Process(BootImage& bi, PartitionHeader* partHdr) { Options& options = bi.options; static bool deviceKeyStored = false; LOG_INFO("Encrypting the partition - %s", partHdr->partition->section->Name.c_str()); std::vector encrBlocks = partHdr->imageHeader->GetEncrBlocksList(); uint32_t defEncrBlocks = partHdr->imageHeader->GetDefaultEncrBlockSize(); Binary::Length_t lastBlock = 0; uint32_t totalencrBlocks = GetTotalEncryptionBlocks(partHdr->partition->section->Length, encrBlocks, defEncrBlocks, &lastBlock); options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr = 0; itr < totalencrBlocks; itr++) { if (itr < encrBlocks.size()) { options.bifOptions->InsertEncryptionBlock(encrBlocks[itr]); } else if (defEncrBlocks != 0) { options.bifOptions->InsertEncryptionBlock(defEncrBlocks); } else if ((itr == totalencrBlocks - 1) && (lastBlock != 0)) { options.bifOptions->InsertEncryptionBlock(lastBlock); } } /* Get the key file or keys (Key0, StartCBC, HMAC) passed from command line */ SetAesFileName(partHdr->GetPartitionAesKeyFile()); LOG_INFO("Key file - %s", aesFilename.c_str()); if (partHdr->GenerateAesKeyFlag()) { std::ifstream keyFile(aesFilename); bool fileExists = keyFile.good(); if (!fileExists) { if (deviceKeyStored) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; aesIv = new uint32_t[AES_GCM_IV_SZ / 4]; aesOptKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.deviceKey, AES_GCM_KEY_SZ); memcpy(aesIv, bi.firstIv, AES_GCM_IV_SZ); memcpy(aesOptKey, bi.firstOptKey, AES_GCM_KEY_SZ); } GenerateEncryptionKeyFile(aesFilename, options); } } bi.InsertEncryptionKeyFile(aesFilename); CheckForSameAesKeyFiles(bi.GetEncryptionKeyFileVec()); ReadEncryptionKeyFile(aesFilename); options.SetDevicePartName(deviceName); CheckForExtraKeyIVPairs(totalencrBlocks, partHdr->partition->section->Name); if (!aesSeedexits && aesKeyVec.size() != 1) { if (totalencrBlocks + 1 > aesKeyVec.size()) { LOG_ERROR("AES Key file has less keys than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } if (totalencrBlocks + 1 > aesIvVec.size()) { LOG_ERROR("AES Key file has less IVs than the number of blocks to be encrypted in %s.", partHdr->partition->section->Name.c_str()); } } else { if (deviceKeyStored) { if (aesKey == NULL) { aesKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesKey, bi.deviceKey, AES_GCM_KEY_SZ); } if (aesKeyVec.size() == 0) { aesKeyVec.push_back(ConvertKeyIvToString((uint8_t *)aesKey, AES_GCM_KEY_SZ).c_str()); } if (aesIv == NULL) { aesIv = new uint32_t[AES_GCM_IV_SZ / 4]; memcpy(aesIv, bi.firstIv, AES_GCM_IV_SZ); } if (aesIvVec.size() == 0) { aesIvVec.push_back(ConvertKeyIvToString((uint8_t *)aesIv, AES_GCM_IV_SZ).c_str()); } if (aesOptKey == NULL) { aesOptKey = new uint32_t[AES_GCM_KEY_SZ / 4]; memcpy(aesOptKey, bi.firstOptKey, AES_GCM_KEY_SZ); } } GenerateRemainingKeys(options, aesFilename); } CheckForRepeatedKeyIVPairs(bi.GetEncryptionKeyFileVec(), true); if (!deviceKeyStored) { bi.deviceKey = new uint32_t[AES_GCM_KEY_SZ / 4]; bi.firstIv = new uint32_t[AES_GCM_IV_SZ / 4]; bi.firstOptKey = new uint32_t[AES_GCM_KEY_SZ / 4]; if (aesKey != NULL) { memcpy(bi.deviceKey, aesKey, AES_GCM_KEY_SZ); } if (aesIv != NULL) { memcpy(bi.firstIv, aesIv, AES_GCM_IV_SZ); } if (aesOptKey != NULL) { memcpy(bi.firstOptKey, aesOptKey, AES_GCM_KEY_SZ); } deviceKeyStored = true; } else { if ((aesKey != NULL) && memcmp(bi.deviceKey, aesKey, AES_GCM_KEY_SZ)) { LOG_ERROR("Key 0 should be same across all nky files - see 'bootgen -bif_help aeskeyfile' for more info."); } if ((aesIv != NULL) && memcmp(bi.firstIv, aesIv, AES_GCM_IV_SZ)) { LOG_ERROR("IV 0 should be same across all nky files - see 'bootgen -bif_help aeskeyfile' for more info."); } if ((aesOptKey != NULL) && memcmp(bi.firstOptKey, aesOptKey, AES_GCM_KEY_SZ)) { LOG_ERROR("Key Opt should be same across all nky files - see 'bootgen -bif_help aeskeyfile' for more info."); } } // For copying SCR HDR IV into Boot Header const uint32_t* tmpIv = GetIv(); if (tmpIv != NULL) { if (options.secHdrIv == NULL) { options.secHdrIv = (uint8_t*)malloc(BYTES_PER_IV); } memcpy_be(options.secHdrIv, tmpIv, BYTES_PER_IV); } uint32_t totalBlocksOverhead = (totalencrBlocks + 1) * 64; if (!Binary::CheckAddress(partHdr->partition->section->Length)) { LOG_ERROR("Partition too large to encrypt"); } isBootloader = partHdr->imageHeader->IsBootloader(); partNum = partHdr->GetpartitionNum(); if (options.GetEncryptionDumpFlag()) { bi.options.aesLogFile.open(bi.options.aesLogFilename, std::fstream::app); VERBOSE_OUT << std::endl << "------------------------------------"; VERBOSE_OUT << std::endl << " Partition No. : " << partNum; VERBOSE_OUT << std::endl << " Partition Name : " << partHdr->partition->section->Name; VERBOSE_OUT << std::endl << " Key file : " << StringUtils::BaseName(aesFilename); VERBOSE_OUT << std::endl << "------------------------------------"; } /* Encrypt the stream */ if (isBootloader && partHdr->imageHeader->GetPmuFwSizeIh() != 0) { // PMU Encryption uint32_t encrPmuByteLength; uint32_t estimatedEncrPmuLength = partHdr->imageHeader->GetPmuFwSizeIh() + totalBlocksOverhead; uint8_t* encrPmuDataBuffer = new uint8_t[estimatedEncrPmuLength]; LOG_INFO("Encrypting the PMU Firmware"); ChunkifyAndEncrypt(options, partHdr->partition->section->Data, partHdr->imageHeader->GetPmuFwSizeIh(), encrPmuDataBuffer /* out*/, encrPmuByteLength /* out */); if (estimatedEncrPmuLength < encrPmuByteLength) { LOG_ERROR("Encryption Error!!! - PMU Buffer overflow"); } // FSBL Encryption uint32_t encrFsblByteLength; uint32_t estimatedEncrFsblLength = partHdr->imageHeader->GetFsblFwSizeIh() + totalBlocksOverhead; uint8_t* encrFsblDataBuffer = new uint8_t[estimatedEncrFsblLength]; LOG_INFO("Encrypting the FSBL"); ChunkifyAndEncrypt(options, partHdr->partition->section->Data + partHdr->imageHeader->GetPmuFwSizeIh(), partHdr->imageHeader->GetFsblFwSizeIh(), encrFsblDataBuffer /* out*/, encrFsblByteLength /* out */); if (estimatedEncrFsblLength < encrFsblByteLength) { LOG_ERROR("Encryption Error!!! - FSBL Buffer overflow"); } partHdr->partition->section->IncreaseLengthAndPadTo(encrPmuByteLength + encrFsblByteLength, 0x0); memcpy(partHdr->partition->section->Data, encrPmuDataBuffer, encrPmuByteLength); memcpy(partHdr->partition->section->Data + encrPmuByteLength, encrFsblDataBuffer, encrFsblByteLength); partHdr->imageHeader->SetTotalPmuFwSizeIh(encrPmuByteLength); partHdr->imageHeader->SetTotalFsblFwSizeIh(encrFsblByteLength); partHdr->partition->section->Length = encrFsblByteLength + encrPmuByteLength; LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encrFsblDataBuffer; delete[] encrPmuDataBuffer; return; } else { uint32_t encryptedLength; uint32_t estimatedEncrLength = partHdr->partition->section->Length + totalBlocksOverhead; uint8_t* encryptedDataBuffer = new uint8_t[estimatedEncrLength]; ChunkifyAndEncrypt(options, partHdr->partition->section->Data, (uint32_t)partHdr->partition->section->Length, encryptedDataBuffer /* out*/, encryptedLength /* out */); partHdr->partition->section->IncreaseLengthAndPadTo(encryptedLength, 0x0); memcpy(partHdr->partition->section->Data, encryptedDataBuffer, encryptedLength); partHdr->partition->section->Length = encryptedLength; partHdr->imageHeader->SetTotalFsblFwSizeIh(encryptedLength); LOG_INFO("Encrypted the partition - %s", partHdr->partition->section->Name.c_str()); bi.options.CloseEncryptionDumpFile(); delete[] encryptedDataBuffer; return; } } /******************************************************************************/ void ZynqMpEncryptionContext::GenerateGreyKey() { #ifdef ENABLE_OBFUSCATED_KEY ReadEncryptionKeyFile(aesFilename); uint8_t *bhIv = new uint8_t[AES_GCM_IV_SZ]; uint8_t *redKey = new uint8_t[AES_GCM_KEY_SZ]; if (aesKey != NULL) { memcpy_be(redKey, aesKey, AES_GCM_KEY_SZ); } else { LOG_ERROR("Encryption Error !!!\n Key 0 does not exist in the AES key file "); } ReadBhIv(bhIv); std::string filename = "obfuscatedkey.txt"; obfs key(redKey, bhIv, metalFile.c_str(), filename.c_str()); obfsk((void*)&key); LOG_TRACE("Obfuscated key file : '%s' generated successfully", filename.c_str()); LOG_INFO("Obfuscated Key generated successfully"); delete[] bhIv; delete[] redKey; #else LOG_ERROR("Obfuscated Key generation is not supported. Please refer to README on how to enable the same."); #endif } /******************************************************************************/ void ZynqMpEncryptionContext::ReadBhIv(uint8_t* bhIv) { FileImport fileReader; uint8_t* ivData = new uint8_t[AES_GCM_IV_SZ]; memset(ivData, 0, AES_GCM_IV_SZ); if (bhKekIVFile != "") { if (!fileReader.LoadHexData(bhKekIVFile, ivData, AES_GCM_IV_SZ)) { LOG_ERROR("Invalid data bytes for BH IV.\n Expected length for BH IV is 12 bytes"); } memcpy(bhIv, ivData, AES_GCM_IV_SZ); } else { LOG_ERROR("Key Generation Error !!!\n BH IV must be specified in BIF file for obfuscated key generation. Use '[bh_key_iv]'"); } delete[] ivData; } xilinx-bootgen-2024.2/encryption-zynqmp.h000077500000000000000000000062461475706442400205000ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _ENCRYPTION_ZYNQMP_CONTEXT_ #define _ENCRYPTION_ZYNQMP_CONTEXT_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "encryption.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpEncryptionContext : public EncryptionContext { public: ZynqMpEncryptionContext(); ZynqMpEncryptionContext(const EncryptionContext * other); ~ZynqMpEncryptionContext(); Encryption::Type Type() { return Encryption::AES; } void ReadEncryptionKeyFile(const std::string& keyFileName); void WriteEncryptionKeyFile(const std::string& baseFileName, bool useOptionalKey, uint32_t blocks); void Process(BootImage& bi, PartitionHeader* partition); void GenerateAesKey(void); void SetAesSeedString(const std::string & key); void SetAesSeed(const uint8_t * key); const uint32_t* GetAesSeed(void); void SetAesKey(const uint8_t* binarykey); const uint32_t* GetAesKey(void); void SetIv(const uint8_t* iv); void SetIvString(const std::string& IV); void GenerateIv(void); const uint32_t* GetIv(void); void SetAesOptKey(const uint8_t* binarykey); void SetAesOptKeyString(const std::string& key); void GenerateAesOptKey(void); const uint32_t* GetAesOptKey(void); void PackNextEncryptionKey(uint8_t* aesKeyNext, int aeskeyPtr); void PackNextIv(uint8_t * aesIvNext, int aesIvPtr); void GetNextKey(uint8_t* keyNext, int ptr); void GetNextIv(uint8_t* keyNext, int ptr); void GetEncryptionKeys(Options& options, uint8_t* aesKey, uint8_t* aesOptKey, uint8_t* aesIV); void GenerateRemainingKeys(Options& options, std::string aesFilename); protected: bool isBootloader; bool aesSeedexits; int partNum; void ChunkifyAndEncrypt(Options& options, const uint8_t *inBuf, uint32_t inLen, uint8_t* outBuf, uint32_t& outLen); void GenerateGreyKey(); void ReadBhIv(uint8_t * bhIv); AesGcmEncryptionContext* encryptionAlgorithm; }; #endif xilinx-bootgen-2024.2/encryption.cpp000077500000000000000000000522021475706442400174700ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "encryption.h" #include "bootimage.h" #include "encryptutils.h" #include "options.h" #include "bifoptions.h" #include "encryptutils.h" #include /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void EncryptionContext::GenerateEncryptionKeyFile(const std::string & baseFileName, Options & options) { static bool kdfVersion = false; if (!kdfVersion) { LOG_INFO("KDF Version : %s", kdf->GetVersion().c_str()); kdfVersion = true; } LOG_TRACE("Generating the AES key file"); std::string devicePartName = options.GetDevicePartName(); if (devicePartName != "") { SetDeviceName(devicePartName); } else { LOG_ERROR("Partname must be specified with -p option in command line for generating a key file"); } if (GetAesSeed() == NULL) { aesSeed = new uint32_t[WORDS_PER_AES_KEY]; memset(aesSeed, 0, WORDS_PER_AES_KEY); } GenerateAesSeed(); if (GetFixedInputData() == NULL) { fixedInputData = new uint32_t[WORDS_PER_FID]; memset(fixedInputData, 0, WORDS_PER_FID); } GenerateAesFixedInputData(); bool useOptionalKey = options.bifOptions->GetAesOptKeyFlag(); /* The extra 1 Key pair is for Secure Header */ uint32_t outBufBytes = (options.bifOptions->GetEncryptionBlocksList().size() + useOptionalKey + 1) * (AES_GCM_KEY_SZ + AES_GCM_IV_SZ); outBufKDF = new uint32_t[outBufBytes]; SetKdfLogFile(options.GetEncryptionDumpFlag()); uint32_t ret = kdf->CounterModeKDF(aesSeed, fixedInputData, fixedInputDataByteLength, outBufKDF, outBufBytes); if (ret != 0) { LOG_ERROR("Error generating encryption keys from Counter Mode KDF."); } WriteEncryptionKeyFile(baseFileName, useOptionalKey, options.bifOptions->GetEncryptionBlocksList().size() + 1); } /******************************************************************************/ void EncryptionContext::SetDeviceName(const std::string& deviceName0) { deviceName = deviceName0; } /******************************************************************************/ void EncryptionContext::PackHex(const std::string& hexString, uint8_t* hexData) { uint32_t hexStringLength = (uint32_t)hexString.size(); if (hexStringLength & 1) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - does not have even no. of hex digits", hexString.c_str()); LOG_ERROR("Error parsing encryption key"); } for (uint32_t i = 0; i < hexStringLength; i += 2) { std::string byte = hexString.substr(i, 2); if (!isxdigit(byte[0]) || !isxdigit(byte[1])) { LOG_DEBUG(DEBUG_STAMP, "Hex String - %s - is has a non hex digit", hexString.c_str()); LOG_ERROR("Error parsing encryption key"); } *hexData++ = (uint8_t)strtoul(byte.c_str(), NULL, 16); } } /******************************************************************************/ void EncryptionContext::SetAesKeyString(const std::string& key) { uint8_t hexData[256]; if (key.size() != (WORDS_PER_AES_KEY * 8)) { LOG_DEBUG(DEBUG_STAMP, "AES key size - %d", key.size()); LOG_ERROR("An AES key must be 256 bits long - %s", key.c_str()); } PackHex(key, hexData); SetAesKey(hexData); } /******************************************************************************/ std::string EncryptionContext::ConvertKeyIvToString(uint8_t * keyIv, uint8_t size) { std::stringstream keyIvString; for (uint32_t i = 0; i < size; i++) { keyIvString << std::setfill('0') << std::setw(2) << std::hex << uint32_t(keyIv[i]); } return keyIvString.str(); } /******************************************************************************/ void EncryptionContext::SetAesFileName(std::string file) { aesFilename = file; } /******************************************************************************/ void EncryptionContext::SetMetalKeyFile(std::string file) { metalFile = file; } /******************************************************************************/ void EncryptionContext::SetBHKekIVFile(std::string file) { bhKekIVFile = file; } /******************************************************************************/ void EncryptionContext::SetBbramKekIVFile(std::string file) { bbramKekIVFile = file; } /******************************************************************************/ void EncryptionContext::SetEfuseKekIVFile(std::string file) { efuseKekIVFile = file; } /******************************************************************************/ void EncryptionContext::SetEfuseUserKek0IVFile(std::string file) { efuseUserKek0IVFile = file; } /******************************************************************************/ void EncryptionContext::SetEfuseUserKek1IVFile(std::string file) { efuseUserKek1IVFile = file; } /******************************************************************************/ std::string EncryptionContext::GetAesFileName() { return aesFilename; } /******************************************************************************/ std::string EncryptionContext::GetMetalKeyFile(void) { return metalFile; } /******************************************************************************/ std::string EncryptionContext::GetBHKekIVFile(void) { return bhKekIVFile; } /******************************************************************************/ std::string EncryptionContext::GetBbramKekIVFile(void) { return bbramKekIVFile; } /******************************************************************************/ std::string EncryptionContext::GetEfuseKekIVFile(void) { return efuseKekIVFile; } /******************************************************************************/ std::string EncryptionContext::GetEfuseUserKek0IVFile(void) { return efuseUserKek0IVFile; } /******************************************************************************/ std::string EncryptionContext::GetEfuseUserKek1IVFile(void) { return efuseUserKek1IVFile; } /******************************************************************************/ void EncryptionContext::GenerateAesSeed(void) { uint8_t seed[BYTES_PER_AES_KEY]; RAND_bytes(seed, WORDS_PER_AES_KEY * sizeof(uint32_t)); SetAesSeed(seed); static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("Seed needed for KDF is generated using RAND_Bytes. To have a secure keying material, we encourage the users to provide the Seed. \n\t Refer to UG1283 for more details"); warningGiven = true; } } /******************************************************************************/ void EncryptionContext::SetAesFixedInputData(const uint8_t* key, uint32_t bytes) { fixedInputData = new uint32_t[bytes/4]; fixedInputDataByteLength = bytes; for (uint32_t index = 0; index < bytes/4; index++) { fixedInputData[index] = ReadBigEndian32(key); key += sizeof(uint32_t); } } /******************************************************************************/ void EncryptionContext::SetAesFixedInputDataString(const std::string& key) { if (key.size() / 2 != 60) { LOG_DEBUG(DEBUG_STAMP, "Fixed Input Data size - %d", key.size() / 2); LOG_ERROR("An AES Fixed Input Data must be 60 Bytes long - %s", key.c_str()); } uint8_t* hexData = new uint8_t[key.size()]; PackHex(key, hexData); SetAesFixedInputData(hexData, key.size() / 2); delete[] hexData; } /******************************************************************************/ void EncryptionContext::GenerateAesFixedInputData(void) { uint8_t fixedInputData[BYTES_PER_FID]; RAND_bytes(fixedInputData, BYTES_PER_FID); SetAesFixedInputData(fixedInputData, BYTES_PER_FID); static bool warningGiven = false; if (!warningGiven) { LOG_WARNING("Fixed Input Data needed for KDF is generated using RAND_Bytes. To have a secure keying material, we encourage the users to provide the Fixed Input Data. \n\t Refer to UG1283 for more details"); warningGiven = true; } } /******************************************************************************/ void EncryptionContext::SetRandomSeed() { /* Start the pseudo random sequence based on the passage of time so that we never get the same pseudo random sequence twice. This is done by XOR'ing the current time (which increments in seconds) with the number of CPU clocks (either microseconds or CPU clock ticks). This will create a number that will never repeat again (the date), but will be different every time this function is called (based on CPU clocks). */ static int temp_var = 0; clock_t currentClocks = clock(); time_t currentTime = time(NULL); uint32_t randomSeed = (uint32_t)(currentTime ^ currentClocks); randomSeed += temp_var++; srand(randomSeed); } /******************************************************************************/ static uint32_t GetRandomValue(uint32_t maxValue) { uint32_t returnValue; do { returnValue = (rand() / (int)(((unsigned)RAND_MAX + 1) / maxValue)); } while (returnValue > maxValue); return returnValue; } /******************************************************************************/ void EncryptionContext::SetKdfLogFile(bool encrdump) { if (encrdump) { static bool kdfLogInit = false; if (!kdfLogInit) { kdfLogInit = true; std::ofstream remove("kdf_log.txt"); kdf->SetKdfLogFilename("kdf_log.txt"); } } } /******************************************************************************/ void EncryptionContext::GetRandomData(uint8_t* randomData, uint32_t randomDataByteLength) { uint8_t randomSequenceNibble; uint8_t randomSequenceByte; uint8_t lastRandomSequenceByte; uint32_t randomByteLocation; uint32_t byteCount; uint32_t index; // Zero out the return buffer; for (index = 0; index < randomDataByteLength; index += 1) { randomData[index] = 0; } // Get pseudo random byte values to fill the return buffer. byteCount = randomDataByteLength; while (byteCount > 0) { // Never get the same byte value twice in a row. lastRandomSequenceByte = 0; do { // Combine two pseudo random nibbles into a byte. randomSequenceByte = 0; // Exclude a byte value of zero. while (randomSequenceByte == 0) { for (index = 0; index < 2; index += 1) { // Get a pseudo random nibble between 0x0 and 0xF. randomSequenceNibble = (uint8_t)GetRandomValue(0x10); // Combine the two nibbles together into a bytes. randomSequenceByte <<= 4; randomSequenceByte |= randomSequenceNibble; } } } while (lastRandomSequenceByte == randomSequenceByte); lastRandomSequenceByte = randomSequenceByte; /* Set the pseudo random bytes values in random byte location order by getting a random byte location index of a byte location that hasn't been set yet */ do { randomByteLocation = GetRandomValue(randomDataByteLength); } while (randomData[randomByteLocation] != 0); // Set the pseudo random byte value into the return buffer. randomData[randomByteLocation] = randomSequenceByte; // Prepare for the next byte loop interation. byteCount -= 1; } } /******************************************************************************/ uint32_t EncryptionContext::GetTotalEncryptionBlocks(Binary::Length_t partitionSize, std::vector encrBlocks, uint32_t defEncrBlockSize, Binary::Length_t* lastBlock) { uint32_t defEncrBlocksCount = 0; /* Calculate the Size of partition covered with given blocks */ Binary::Length_t encrBlocksSize = 0; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; } /* Calculate the number encryption blocks with the def block size given using (*), else would be a single block */ if (partitionSize > encrBlocksSize) { if (defEncrBlockSize != 0) { defEncrBlocksCount = ((partitionSize - encrBlocksSize) / defEncrBlockSize); bool lastBlockExists = (((partitionSize - encrBlocksSize) % defEncrBlockSize) == 0 ? 0 : 1); if (lastBlockExists) { defEncrBlocksCount++; *lastBlock = (partitionSize - encrBlocksSize - ((defEncrBlocksCount - 1)*defEncrBlockSize)); } } else { defEncrBlocksCount = 1; *lastBlock = partitionSize - encrBlocksSize; } } uint32_t totalencrBlocks = defEncrBlocksCount + encrBlocks.size(); LOG_TRACE("Total no. of blocks to encrypt - %d", totalencrBlocks); return totalencrBlocks; } /******************************************************************************/ void EncryptionContext::CheckForSameAesKeyFiles(std::vector aesKeyFileVec) { uint32_t count = 0; for (uint32_t i = 0; i < aesKeyFileVec.size(); i++) { if (aesFilename.compare(aesKeyFileVec[i]) == 0) { count++; } } if (count > 1) { LOG_ERROR("Same .nky file is used to provide keys across multiple partitions.\n Reuse of keys or key/IV pairs, both of which can create security vulnerability."); } } /******************************************************************************/ void EncryptionContext::CheckForExtraKeyIVPairs(uint32_t totalencrBlocks, std::string name) { static bool extraKeys = false; static bool extraIvs = false; if (totalencrBlocks + 1 < aesKeyVec.size()) { extraKeys = true; aesKeyVec.resize(totalencrBlocks + 1); } if (totalencrBlocks + 1 < aesIvVec.size()) { extraIvs = true; aesIvVec.resize(totalencrBlocks + 1); } if (extraKeys && extraIvs) { LOG_WARNING("AES Key file has more Keys/IVs than the number of blocks to be encrypted in %s. \n Extra keys/Ivs will be ignored.", name.c_str()); } else if (extraKeys) { LOG_WARNING("AES Key file has more Keys than the number of blocks to be encrypted in %s. \n Extra Keys will be ignored.", name.c_str()); } else if (extraIvs) { LOG_WARNING("AES Key file has more IVs than the number of blocks to be encrypted in %s. \n Extra Ivs will be ignored.", name.c_str()); } } /******************************************************************************/ void EncryptionContext::CheckForRepeatedKeyIVPairs(std::vector aesKeyFileVec, bool maskKey0IV0) { static std::vector > aesKeyMasterVec; static std::vector > aesIvMasterVec; aesKeyMasterVec.push_back(aesKeyVec); aesIvMasterVec.push_back(aesIvVec); bool repeatedKey = false; bool repeatedIV = false; for (uint32_t i = 0; i < aesKeyVec.size(); i++) { for (uint32_t j = i + 1; j < aesKeyVec.size(); j++) { if (aesKeyVec[i] == aesKeyVec[j]) { repeatedKey = true; } if (aesIvVec[i] == aesIvVec[j]) { repeatedIV = true; } if (repeatedKey && repeatedIV) { LOG_MSG(" Key : %s", aesKeyVec[i].c_str()); LOG_MSG(" IV : %s", aesIvVec[i].c_str()); LOG_ERROR("Repeated usage of Key/IV pair is observed in %s.\n Reuse of Key/IV pair creates security vulnerability.", aesFilename.c_str()); } else { repeatedKey = repeatedIV = false; } } } if (maskKey0IV0) { aesKeyMasterVec[aesKeyMasterVec.size() - 1].erase(aesKeyMasterVec[aesKeyMasterVec.size() - 1].begin()); aesIvMasterVec[aesIvMasterVec.size() - 1].erase(aesIvMasterVec[aesIvMasterVec.size() - 1].begin()); } for (uint32_t i = 0; i < aesKeyMasterVec.size(); i++) { uint32_t j = aesKeyMasterVec.size() - 1; if (i != j) { for (uint32_t x = 0; x < aesKeyMasterVec[i].size(); x++) { for (uint32_t y = 0; y < aesKeyMasterVec[j].size(); y++) { if (aesKeyMasterVec[i][x] == aesKeyMasterVec[j][y]) { repeatedKey = true; } if (aesIvMasterVec[i][x] == aesIvMasterVec[j][y]) { repeatedIV = true; } if (repeatedKey && repeatedIV) { LOG_MSG(" Key : %s", aesKeyMasterVec[i][x].c_str()); LOG_MSG(" IV : %s", aesIvMasterVec[j][y].c_str()); LOG_ERROR("Repeated usage of Key/IV pair is observed in %s, %s.\n Reuse of Key/IV pair creates security vulnerability.", aesKeyFileVec[i].c_str(), aesKeyFileVec[j].c_str()); } else { repeatedKey = repeatedIV = false; } } } } } } /******************************************************************************/ void AesGcmEncryptionContext::AesGcm256Encrypt(unsigned char* gcm_pt, int pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int& ct_len, unsigned char* gcm_tag) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; ctx = EVP_CIPHER_CTX_new(); /* Set cipher type and mode */ EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length to 96 bits or 12 bytes */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL); /* Initialise key and IV */ EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); /* Specify any AAD only if it is non-zero length*/ if ((gcm_aad) && aad_len) { EVP_EncryptUpdate(ctx, NULL, &outlen, gcm_aad, aad_len); } /* Encrypt plaintext */ EVP_EncryptUpdate(ctx, gcm_ct, &outlen, gcm_pt, pt_len); /* Finalise GCM */ EVP_EncryptFinal_ex(ctx, gcm_ct + outlen, &tmplen); /* Get GCM tag */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, gcm_tag); EVP_CIPHER_CTX_free(ctx); ct_len = outlen + tmplen; } /******************************************************************************/ void AesGcmEncryptionContext::AesGcm256Decrypt(unsigned char* gcm_pt, int& pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int ct_len, unsigned char* gcm_tag) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; ctx = EVP_CIPHER_CTX_new(); /* Select cipher */ EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length, omit for 96 bits */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL); /* Specify key and IV */ EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); #if 1 /* Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier required the tag before any AAD or ciphertext */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, gcm_tag); #endif /* Specify any AAD only if it is non-zero length*/ if ((gcm_aad) && aad_len > 0) { EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, aad_len); } /* Decrypt plaintext */ EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, ct_len); #if 0 /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, gcm_tag); #endif /* Finalise: GCM */ (void)EVP_DecryptFinal_ex(ctx, gcm_pt + outlen, &tmplen); EVP_CIPHER_CTX_free(ctx); pt_len = outlen + tmplen; }xilinx-bootgen-2024.2/encryption.h000077500000000000000000000164521475706442400171440ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _ENCRYPTION_CONTEXT_ #define _ENCRYPTION_CONTEXT_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include "kdf.h" #include "bootgenenum.h" #include "options.h" /* Forward Class References */ class PartitionHeader; class Options; class DataMover; class BootImage; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define WORDS_PER_AES_BLOCK 4 #define WORDS_PER_AES_KEY 8 #define BYTES_PER_AES_KEY 32 #define BYTES_PER_FID 60 #define WORDS_PER_FID 15 #define ENCRYPTION_ENABLE 0x00000040 #define EFUSE_KEY_SOURCE 0x80000000 #define BBRAM_KEY_SOURCE 0x00000000 #define ENCRYPTION_KEY_SRC_OFFSET 36 #define ENCRYPTION_ENABLE_WORD_OFFSET 44 #define CBC_WORD_OFFSET 116 #define ENCRYPTION_DATA_LENGTH_OFFSET 136 #define FPGA_ENCRYPTION_KEY_SRC_OFFSET 4 #define FPGA_ENCRYPTION_ENABLE_WORD_OFFSET 12 #define FPGA_CBC_WORD_OFFSET 84 #define FPGA_ENCRYPTION_DATA_LENGTH_OFFSET 104 #define WORDS_PER_IV 3 #define BYTES_PER_IV 12 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class EncryptionContext { public: EncryptionContext() : deviceName("") , metalFile("") , bhKekIVFile("") , bbramKekIVFile("") , efuseKekIVFile("") , efuseUserKek0IVFile("") , efuseUserKek1IVFile("") , aesFilename("") , aesKey(NULL) , aesOptKey(NULL) , aesIv(NULL) , aesSeed(NULL) , outBufKDF(NULL) , fixedInputDataByteLength(0) , fixedInputData(NULL) , fixedInputDataExits(false) { kdf = new Kdf(); }; virtual ~EncryptionContext() { if(kdf) { delete kdf; } }; virtual Encryption::Type Type() { return Encryption::None; } virtual void Process(BootImage& bi, PartitionHeader* partition) {}; virtual void ChunkifyAndProcess(BootImage & bi, PartitionHeader * partHdr) {}; virtual void Process(BootImage& bi) {}; virtual void WriteEncryptionKeyFile(const std::string& baseFileName, bool useOptionalKey, uint32_t blocks) {}; virtual void ReadEncryptionKeyFile(const std::string& keyFileName) {}; virtual void GenerateEncryptionKeyFile(const std::string& baseFileName, Options& options); virtual void GenerateAesKey(void) {}; virtual void SetAesKey(const uint8_t* binarykey) {}; virtual void ReadBhIv(uint8_t* bhIv) {}; virtual void GenerateGreyKey() {}; virtual void GenerateRemainingKeys() {}; void SetAesFileName(std::string); void SetMetalKeyFile(std::string file); void SetBHKekIVFile(std::string file); void SetBbramKekIVFile(std::string file); void SetEfuseKekIVFile(std::string file); void SetEfuseUserKek0IVFile(std::string file); void SetEfuseUserKek1IVFile(std::string file); void SetDeviceName(const std::string& deviceName0); void PackHex(const std::string & hexString, uint8_t * hexData); void SetRandomSeed(void); void SetAesKeyString(const std::string& ASCIIkey); std::string ConvertKeyIvToString(uint8_t *keyIv, uint8_t size); void SetKdfLogFile(bool encrdump); void GetRandomData(uint8_t* randomData, uint32_t randomDatabyteLength); uint32_t static GetTotalEncryptionBlocks(Binary::Length_t partitionSize, std::vector encrBlocks, uint32_t defEncrBlockSize, Binary::Length_t * lastBlock); void CheckForSameAesKeyFiles(std::vector); void CheckForExtraKeyIVPairs(uint32_t, std::string name); void CheckForRepeatedKeyIVPairs(std::vector aesKeyFileVec, bool maskKey0IV0); std::string GetAesFileName(void); std::string GetMetalKeyFile(void); std::string GetBHKekIVFile(void); std::string GetBbramKekIVFile(void); std::string GetEfuseKekIVFile(void); std::string GetEfuseUserKek0IVFile(void); std::string GetEfuseUserKek1IVFile(void); virtual void SetAesSeed(const uint8_t * key) {}; void GenerateAesSeed(void); virtual const uint32_t* GetAesSeed(void) { return NULL; }; void SetAesFixedInputDataString(const std::string & key); void SetAesFixedInputData(const uint8_t * key, uint32_t bytes); void GenerateAesFixedInputData(void); uint32_t* GetFixedInputData(void) { return fixedInputData; }; std::string aesFilename; Kdf* kdf; protected: uint32_t* aesKey; uint32_t* aesOptKey; uint32_t* aesIv; std::vector aesKeyVec; std::vector aesIvVec; uint32_t* aesSeed; uint32_t* outBufKDF; uint32_t* fixedInputData; uint32_t fixedInputDataByteLength; std::string deviceName; std::string metalFile; std::string bhKekIVFile; std::string bbramKekIVFile; std::string efuseKekIVFile; std::string efuseUserKek0IVFile; std::string efuseUserKek1IVFile; bool fixedInputDataExits; }; /******************************************************************************/ class NoneEncryptionContext : public EncryptionContext { public: Encryption::Type Type() { return Encryption::None; } }; /******************************************************************************/ class AesGcmEncryptionContext { public: AesGcmEncryptionContext() { }; ~AesGcmEncryptionContext() { }; void AesGcm256Encrypt(unsigned char* gcm_pt, int pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int& ct_len, unsigned char* gcm_tag); void AesGcm256Decrypt(unsigned char* gcm_pt, int& pt_len, unsigned char* gcm_key, unsigned char* gcm_iv, unsigned char* gcm_aad, int aad_len, unsigned char* gcm_ct, int ct_len, unsigned char* gcm_tag); }; #endif xilinx-bootgen-2024.2/encryptutils.cpp000077500000000000000000000106241475706442400200450ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include "encryptutils.h" #include "fileutils.h" #include "stringutils.h" #include "systemutils.h" static const uint8_t reverse8BitValueTable[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, // 0x00 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, // 0x10 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, // 0x20 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, // 0x30 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, // 0x40 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, // 0x50 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, // 0x60 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, // 0x70 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, // 0x80 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, // 0x90 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, // 0xA0 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, // 0xB0 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, // 0xC0 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, // 0xD0 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, // 0xE0 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF // 0xF0 }; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void memcpy_be(uint8_t* dst, const uint32_t* src, size_t size) { uint32_t value = 0; uint8_t *addr; for(uint32_t i=0; i 0) { valueBitLength -= BITS_IN_BYTE; reversedValue |= (reverse8BitValueTable[value & 0xFF] << valueBitLength); value >>= BITS_IN_BYTE; } return reversedValue; } /******************************************************************************/ void reverse_copy(uint8_t* dst, uint64_t value, size_t size) { int8_t ix = 1; do { dst[size - ix] = value & 0xFF; value = value >> (ix * 8); ix++; } while (value > 0); } xilinx-bootgen-2024.2/encryptutils.h000077500000000000000000000125311475706442400175110ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _ENCRYPTUTILS_H_ #define _ENCRYPTUTILS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "encryption.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define BYTES_PER_STREAM_HEADER 140 #define BYTES_PER_FPGA_STREAM_HEADER 108 #define BYTES_PER_IPAD 64 #define BYTES_PER_PAD1 64 #define BYTES_PER_2048_GAP 256 #define BYTES_PER_OPAD 64 #define BYTES_PER_FIRST_DIGEST 32 #define BYTES_PER_PAD2 32 #define BYTES_PER_HMAC_DIGEST 32 #define AES_GCM_IV_SZ 12 #define AES_GCM_KEY_SZ 32 #define WORDS_PER_AES_BLOCK 4 #define WORDS_PER_AES_KEY 8 #define SECURE_HDR_SZ 48 #define AES_GCM_TAG_SZ 16 #define NUM_BYTES_PER_WORD 4 #define VERBOSE_FILE 1 #ifdef VERBOSE_FILE #define VERBOSE_OUT options.aesLogFile #define VERBOSE_OUT_MH bi.options.aesLogFile #else #define VERBOSE_OUT std::cout #define VERBOSE_OUT_MH std::cout #endif static const uint32_t defaultStreamHeader [BYTES_PER_STREAM_HEADER / sizeof(uint32_t)] = { 0xFFFFFFFF, // 0 Dummy Word 0xFFFFFFFF, // 4 Dummy Word 0x000000BB, // 8 BusWidth Word 0x11220044, // 12 32/08/16 bits 0xFFFFFFFF, // 16 Dummy Word 0xFFFFFFFF, // 20 Dummy Word 0xAA995566, // 24 Sync Word 0x20000000, // 28 Type1 NO OP 0x3000C001, // 32 Type1 write 1 words to MASK 0x00000040, // 36 data word 1 0x3000A001, // 40 Type1 write 1 words to CTL 0x00000040, // 44 dec 0x20000000, // 48 Type1 NO OP 0x20000000, // 52 Type1 NO OP 0x20000000, // 56 Type1 NO OP 0x20000000, // 60 Type1 NO OP 0x20000000, // 64 Type1 NO OP 0x20000000, // 68 Type1 NO OP 0x20000000, // 72 Type1 NO OP 0x20000000, // 76 Type1 NO OP 0x20000000, // 80 Type1 NO OP 0x20000000, // 84 Type1 NO OP 0x20000000, // 88 Type1 NO OP 0x20000000, // 92 Type1 NO OP 0x20000000, // 96 Type1 NO OP 0x20000000, // 100 Type1 NO OP 0x20000000, // 104 Type1 NO OP 0x20000000, // 108 Type1 NO OP 0x30016004, // 112 Type1 write 4 words to CBC 0x00000000, // 116 data word 1 0x00000000, // 120 data word 2 0x00000000, // 124 data word 3 0x00000000, // 128 data word 4 0x30034001, // 132 Type1 write 1 words to DWC 0x00000000 // 136 data word 1 }; static const uint32_t defaultFpgaStreamHeader [BYTES_PER_FPGA_STREAM_HEADER / sizeof(uint32_t)] = { 0x3000C001, // 0 Type1 write 1 words to MASK 0x00000040, // 4 data word 1 0x3000A001, // 8 Type1 write 1 words to CTL 0x00000040, // 12 dec 0x3001C001, // 16 Type1 NO OP 0x00000000, // 20 Type1 NO OP 0x20000000, // 24 Type1 NO OP 0x20000000, // 28 Type1 NO OP 0x20000000, // 32 Type1 NO OP 0x20000000, // 36 Type1 NO OP 0x20000000, // 40 Type1 NO OP 0x20000000, // 44 Type1 NO OP 0x20000000, // 48 Type1 NO OP 0x20000000, // 52 Type1 NO OP 0x20000000, // 56 Type1 NO OP 0x20000000, // 60 Type1 NO OP 0x20000000, // 64 Type1 NO OP 0x20000000, // 68 Type1 NO OP 0x20000000, // 72 Type1 NO OP 0x20000000, // 76 Type1 NO OP 0x30016004, // 80 Type1 write 4 words to CBC 0x00000000, // 84 data word 1 0x00000000, // 88 data word 2 0x00000000, // 92 data word 3 0x00000000, // 96 data word 4 0x30034001, // 100 Type1 write 1 words to DWC 0x00000000 // 104 data word 1 }; static const uint32_t defaultPcapHeader[] = { 0x3001E000, // 56 Type1 write of 0 words to PCAP reg 0x50000000 // 60 Type2 write of length word to PCAP reg }; void memcpy_be(uint8_t* dst, const uint32_t* src, size_t size); uint32_t reverseDataBits(uint32_t value); void reverse_copy(uint8_t* dst, uint64_t value, size_t size); #endif xilinx-bootgen-2024.2/fileutils.h000077500000000000000000000107071475706442400167470ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _FILEUTILS_H_ #define _FILEUTILS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ByteFile { public: ByteFile(const std::string& name) { std::ifstream fl(name.c_str(), std::ios::binary); if (!fl) { LOG_ERROR("Cannot read file - %s", name.c_str()); } fl.seekg(0, std::ios::end); if(!fl) { LOG_ERROR("Cannot seek to end of file - %s", name.c_str()); } if(fl.bad() || fl.fail()) { LOG_ERROR("Cannot seek to end of file - %s", name.c_str()); } if(! fl.good()) { LOG_ERROR("Cannot seek to end of file - %s", name.c_str()); } len = fl.tellg(); bytes = new uint8_t[len]; fl.seekg(0, std::ios::beg); fl.read((char*)bytes, len); fl.close(); } ~ByteFile() { if (bytes) { delete [] bytes; } bytes = 0; } uint8_t* bytes; size_t len; }; /******************************************************************************/ class FileImport { public: bool LoadHexData(const std::string& fileName, uint8_t* dataArray, int count) { FILE* f; int datum, ret, nbytes; nbytes = 0; memset(dataArray, 0, count); f = fopen(fileName.c_str(), "r"); if ((ret = fscanf(f, "%2X", &datum)) == EOF) { fclose(f); LOG_ERROR("File is empty - %s", fileName.c_str()); } fclose(f); f = fopen(fileName.c_str(), "r"); if(f) { while ((ret = fscanf(f, "%2X", &datum)) != EOF) { if (ret == 1) { if (datum < 0 || datum > 255) { fclose(f); LOG_ERROR("Bad hex character %x in file - %s", datum, fileName.c_str()); } if (nbytes == count) { fclose(f); return false; } dataArray[nbytes++] = datum; } else { fclose(f); LOG_ERROR("Unable to read hex characters from file - %s", fileName.c_str()); } } if (nbytes < count) { fclose(f); return false; } } else { LOG_ERROR("Unable to open file - %s", fileName.c_str()); } fclose(f); return true; } }; class FileUtils { public: static uint32_t GetFileSize(std::string filename) { FILE *p_file = NULL; uint32_t size = 0; p_file = fopen(filename.c_str(), "rb"); if (p_file) { fseek(p_file, 0, SEEK_END); size = ftell(p_file); } else { LOG_ERROR("Unable to open file - %s", filename.c_str()); } fclose(p_file); return size; } }; #endif xilinx-bootgen-2024.2/hash.cpp000077500000000000000000000072361475706442400162300ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "hash.h" #include "Keccak-compact-versal.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ uint8_t HashSha2::GetHashLength(void) { return SHA2_LENGTH_BYTES; } /******************************************************************************/ uint8_t HashSha2::UpdateHash(const void* data, size_t length) { uint8_t errorCode = SHA256_Update(&ctx, data, length); /* Send the inverted error code, to be consistent with the SHA3 algo */ return (!errorCode); } /******************************************************************************/ uint8_t HashSha2::FinalHash(uint8_t* hashout) { uint8_t errorCode = SHA256_Final(hashout, &ctx); /* Send the inverted error code, to be consistent with the SHA3 algo */ return (!errorCode); } /******************************************************************************/ void HashSha2::CalculateHash(bool flag, const uint8_t *data, size_t length, uint8_t* out) { SHA256(data, length, out); } /******************************************************************************/ std::string HashSha2::GetHashFileExtension(void) { return ".sha256"; } /******************************************************************************/ uint8_t HashSha3::GetHashLength(void) { return SHA3_LENGTH_BYTES; } /******************************************************************************/ uint8_t HashSha3::UpdateHash(const void* data, size_t length) { size_t length_in_bits = length * 8; return Update(&ctx, (BitSequence*)data, length_in_bits); } /******************************************************************************/ uint8_t HashSha3::FinalHash(uint8_t* hashout) { return Final(&ctx, hashout, SHA3_LENGTH_BYTES); } /******************************************************************************/ void HashSha3::CalculateHash(bool nist, const uint8_t *data, size_t length, uint8_t* out) { if (nist) { crypto_hash_NIST_SHA3(out, data, length); } else { crypto_hash(out, data, length); } } /******************************************************************************/ void HashSha3::CalculateVersalHash(bool nist, const uint8_t *data, size_t length, uint8_t* out) { Versalcrypto_hash(out, data, length, nist); } /******************************************************************************/ std::string HashSha3::GetHashFileExtension(void) { return ".sha384"; } xilinx-bootgen-2024.2/hash.h000077500000000000000000000066451475706442400157000ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _HASH_H_ #define _HASH_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "Keccak-compact.h" #include "bootgenenum.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define SHA2_LENGTH_BYTES 32 #define SHA3_LENGTH_BYTES 48 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Hash { public: Hash() : hashLength(0) { }; virtual ~Hash() {} virtual void InitHash(void) = 0; virtual uint8_t GetHashLength(void) = 0; virtual uint8_t UpdateHash(const void*, size_t) = 0; virtual uint8_t FinalHash(uint8_t*) = 0; virtual void CalculateHash(bool flag, const uint8_t*, size_t, uint8_t*) = 0; virtual void CalculateVersalHash(bool flag, const uint8_t*, size_t, uint8_t*) {} virtual std::string GetHashFileExtension(void) = 0; protected: uint8_t hashLength; }; /******************************************************************************/ class HashSha2 : public Hash { public: HashSha2() { ctx.md_len = 0; ctx.num = 0; ctx.Nl = 0; ctx.Nh = 0; } ~HashSha2() {} uint8_t GetHashLength(void); void InitHash(void) { SHA256_Init(&ctx); } uint8_t UpdateHash(const void*, size_t); uint8_t FinalHash(uint8_t*); void CalculateHash(bool flag, const uint8_t*, size_t, uint8_t*); std::string GetHashFileExtension(void); private: SHA256_CTX ctx; }; /******************************************************************************/ class HashSha3 : public Hash { public: HashSha3() { ctx.bitsInQueue = 0; } ~HashSha3() {} uint8_t GetHashLength(void); void InitHash(void) { Init(&ctx); } uint8_t UpdateHash(const void*, size_t); uint8_t FinalHash(uint8_t*); void CalculateHash(bool flag, const uint8_t*, size_t, uint8_t*); void CalculateVersalHash(bool flag, const uint8_t*, size_t, uint8_t*); std::string GetHashFileExtension(void); private: hashState ctx; }; #endif xilinx-bootgen-2024.2/help-versal.h000077500000000000000000003130341475706442400171700ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _HELP_VERSAL_H_ #define _HELP_VERSAL_H_ #include /*********************************************************************************************** * Option : init * Description : Register Initialization ************************************************************************************************/ #define HV_BIF_INIT_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | init |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Register initialization block at the end of the bootloader, |\n\ | built by parsing the .int file specification. Maximum of 256 |\n\ | address-value init pairs are allowed. The int files have |\n\ | a specific format. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | init = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | init = test.ini |\n\ | { type = bootloader, file = /path/to/plm.elf } |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Sample .int file - test.ini |\n\ | .set. 0xF8000120 = 0x1F000200; |\n\ | .set. 0xF8000720 = 0x00000202; |\n\ | .set. 0xF800014C = 0x00000521; |\n\ -------------+----------------------------------------------------------------+\n" /*********************************************************************************************** * Option : aeskeyfile * Description : Encryption Key File ************************************************************************************************/ #define HV_BIF_AES_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | aeskeyfile |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | The path to the AES keyfile. The keyfile contains AES key used |\n\ | to encrypt the partitions. The contents of the key file needs |\n\ | to written to efuse or bbram. |\n\ | If the key file is not present in the path specified, a new key|\n\ | is generated by bootgen, which is used for encryption. |\n\ | Key file should be specified for each partition. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | aeskeyfile = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /*********************************************************************************************** * Option : ppkfile * Description : Encryption Key File ************************************************************************************************/ #define HV_BIF_PPK_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | ppkfile, pskfile, spkfile, sskfile |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | These keys are used to authenticate partitions in the bootimage|\n\ | A pair of keys, Primary & Secondary are used in the |\n\ | authentication process. |\n\ | The primary keys authenticate the secondary keys and the |\n\ | secondary keys authenticate the partitions. |\n\ | PPK - Primary Public Key |\n\ | PSK - Primary Secret Key |\n\ | SPK - Secondary Public Key |\n\ | SSK - Secondary Secret Key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ppkfile = |\n\ | pskfile = |\n\ | spkfile = |\n\ | sskfile = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | boot_config {bh_auth_enable} |\n\ | pskfile = /path/to/primary0.pem |\n\ | sskfile = /path/to/secondary0.pem |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | authentication = rsa, |\n\ | file = /path/to/apu.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" //#define HV_BIF_SPKSIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | spksignature |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports SPK signature into authentication certificate. This can|\n\ | be used incase the user does't want to share the secret key PSK|\n\ | The user can create a signature and provide it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | spksignature = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | headersignature = /path/to/header.sig |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key.pem, |\n\ | spksignature = /path/to/secondary-key.pem.sig, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key-2.pem, |\n\ | spksignature = /path/to/secondary-key-2.pem.sig, |\n\ | file = /path/to/apu.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" //#define HV_BIF_HDRSIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | headersignature |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports Header signature into authentication certificate. This |\n\ | can be used incase the user does't want to share the secret key|\n\ | The user can create a signature and provide it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | headersignature = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | headersignature = /path/to/header.sig |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key.pem, |\n\ | spksignature = /path/to/secondary-key.pem.sig, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key-2.pem, |\n\ | spksignature = /path/to/secondary-key-2.pem.sig, |\n\ | file = /path/to/apu.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BI_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bootimage |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies that the following file specification is a |\n\ | bootimage that was created by Bootgen, being reused as input. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { type = bootimage } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | { type = bootimage, file = base_pdi.bin } |\n\ | { type = cdo, file = ps_cdo.bin} |\n\ | { core = a72 - 0, file = a72_app.elf} |\n\ | { core = r5 - 0, file = r5_app.elf} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bootloader |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition is a bootloader (PLM). This |\n\ | attribute is specified with along with other partition bif |\n\ | attributes. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { type = bootloader } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_ENCR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | encryption |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be encrypted. |\n\ | AES-GCM is the encryption algorithm used |\n\ | Versal : AES-GCM |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { encryption = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : Partition not encrypted |\n\ | aes : Partition encrypted using AES algorithm |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" #define HV_BIF_AUTH_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | authentication |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be authenticated. |\n\ | Authentication Algorithms: RSA-4096, ECDSA |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { authenication = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : Partition not authenticated |\n\ | rsa : Partition authenticated using RSA algorithm |\n\ | ecdsa : Partition authenticated using RSA algorithm |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | boot_config{ bh_auth_enable } |\n\ | pskfile = primary0.pem |\n\ | sskfile = secondary0.pem |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | { |\n\ | type = cdo, |\n\ | authentication = rsa, |\n\ | file = ps_cdo.bin |\n\ | } |\n\ | { |\n\ | core = a72-0, |\n\ | authentication = rsa, |\n\ | file = a72_app.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_CHKSM_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | checksum |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be checksummed. |\n\ | Checksum Algorithms: SHA3 |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { checksum = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : no checksum operation |\n\ | sha3 : SHA3 checksum operation |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | init = reginit.ini |\n\ | image |\n\ | { |\n\ | { type=bootloader, checksum=sha3, file=plm.elf } |\n\ | { type=pmcdata, load=0xf2000000, file=pmc_cdo.bin} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n\ NOTE | Checksum operation is not supported along with authentication |\n\ | and encryption. |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_POWNER_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | owner |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Owner of the partition which is responsible to load the |\n\ | partition. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { owner = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *plm : PLM loads this partition |\n\ | non-plm : PLM ignores this partition, someone else loads |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | owner = non-plm, |\n\ | file = /path/to/hello.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" //#define HV_BIF_PRESIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | presign |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports partition signature into partition authenticate |\n\ | certificate. |\n\ | This can be used incase the user does't want to share the |\n\ | secret key(SSK). The user can create a signature and provide |\n\ | it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { presign = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | ppkfile = /path/to/primary0.pem |\n\ | headersignature = /path/to/headers.sha256.sig |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | spkfile = /path/to/secondary-key.pem, |\n\ | spksignature = /path/to/sec-key.pem.sha384.sig, |\n\ | presign = /path/to/plm.sha384.sig, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_OFFSET_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | offset |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the absolute offset of the partition in the boot image. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { offset = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_data.cdo } |\n\ | { type=cdo, file=ddr.rnpi } |\n\ | { core=psm, file=psm.elf } |\n\ | { type=cdo, file=ps_data.cdo } |\n\ | { type=cdo, file=subsystem.cdo } |\n\ | { file=u-boot.elf } |\n\ | { load=0x1000, offset=0xa00000, file=system.dtb } |\n\ | { core=a72-0, exception_level=el-3, file=bl31.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_LOAD_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | load |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the load address for the partition in memory. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { load = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | { type=bootloader, checksum=sha3, file=plm.elf } |\n\ | { type=pmcdata, load=0xf2000000, file=pmc_cdo.bin} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_KEYSRC_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | keysrc |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Key source for encryption |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { keysrc = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | efuse_red_key : Red Key stored in efuse |\n\ | bbram_red_key : Red Key stored in bbram |\n\ | efuse_gry_key : Grey (Obfuscated) Key stored in efuse |\n\ | bbram_gry_key : Grey (Obfuscated) Key stored in bbram |\n\ | bh_gry_key : Grey (Obfuscated) Key stored in boot header |\n\ | efuse_blk_key : Black Key stored in efuse |\n\ | bbram_blk_key : Black Key stored in bbram |\n\ | bh_blk_key : Black Key stored in boot header |\n\ | kup_key : User Key in boot header |\n\ | user_key0 : User Key 0 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_PMCCONFIG_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | boot_config |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | These parameters are used to configure the bootimage |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | boot_config { } |\n\ -------------+---------------------+------------------------------------------+\n\ OPTIONS | Options | Description |\n\ +---------------------+------------------------------------------+\n\ | bh_auth_enable | Boot Header Authentication Enable: |\n\ | | Authentication of the bootimage will |\n\ | | be done excluding the verification of |\n\ | | PPK hash and SPK ID. |\n\ +---------------------+------------------------------------------+\n\ | pufhd_bh | PUF helper data is stored in BH. |\n\ | | (Default is efuse) |\n\ | | PUF helper data file is passed to bootgen|\n\ | | using the option [puf_file]. |\n\ +---------------------+------------------------------------------+\n\ | puf4kmode | PUF is tuned to use in 4k bit syndrome |\n\ | | configuration. |\n\ | | (Default is 12k bit) |\n\ +---------------------+------------------------------------------+\n\ | shutter = | 32 bit PUF_SHUT register value to |\n\ | | configure PUF for shutter offset time |\n\ | | and shutter open time. |\n\ +---------------------+------------------------------------------+\n\ | smap_width = | 8, 16, 32 |\n\ | | Default is 32-bit |\n\ -------------+---------------------+------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | bh_auth_enable_smap_width: |\n\ | { |\n\ | boot_config { bh_auth_enable, smap_width=16 } |\n\ | pskfile = /path/to/primary0.pem |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key.pem, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_DESTCPU_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | core |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies which core will execute the partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { core = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | * a72-0 |\n\ | a72-1 |\n\ | r5-0 |\n\ | r5-1 |\n\ | psm |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | offset = 0x500000, |\n\ | file = /path/to/apu.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_TYPE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | type |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the type of partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { type = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | bootloader |\n\ | pmcdata |\n\ | cdo |\n\ | cfi |\n\ | bootimage |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_EL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | exception_level |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Exception level for which the core should be configured |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { exception_level = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | el-0 |\n\ | el-1 |\n\ | el-2 |\n\ | *el-3 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | exception_level = el-3, |\n\ | trustzone = secure, |\n\ | file = /path/to/bl31.elf |\n\ | } |\n\ | { |\n\ | id = 0x00000001, |\n\ | core = a72-0, |\n\ | exception_level = el-2, |\n\ | file = /path/to/u-boot.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_TZ_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | trustzone |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Configures the core to be Trustzone secure or nonsecure |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { trustzone = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *secure |\n\ | nonsecure |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | exception_level = el-3, |\n\ | trustzone = secure, |\n\ | file = /path/to/bl31.elf |\n\ | } |\n\ | { |\n\ | id = 0x00000001, |\n\ | core = a72-0, |\n\ | exception_level = el-2, |\n\ | file = /path/to/u-boot.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BOOTDEV_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | boot_device |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Secondary Boot Attributes |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | boot_device { , address=
} |\n\ | - To specify the secondary boot device. |\n\ | address - To specify the address at which the image is |\n\ | present in the secondary boot device. |\n\ | Default address is 0. |\n\ -------------+----------------------------------------------------------------|\n\ OPTIONS | qspi32 |\n\ | qspi24 |\n\ | nand |\n\ | sd0 |\n\ | sd1 |\n\ | sd-ls |\n\ | mmc |\n\ | usb |\n\ | ethernet |\n\ | pcie |\n\ | sata |\n\ | ospi |\n\ | smap |\n\ | sbi |\n\ | sd0-raw |\n\ | sd1-raw |\n\ | sd-ls-raw |\n\ | mmc-raw |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF 1 - test.bif |\n\ | all: |\n\ | { |\n\ | boot_device { qspi32, address = 0x10000 } |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_data.cdo |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BHKEY_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bh_keyfile |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | 256-bit obfuscated key to be stored in boot header |\n\ | This is only valid, when [keysrc_encryption] bh_gry_key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bh_keyfile = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bh_gry_key, |\n\ | bh_keyfile = obfuscated_key.txt |\n\ | bh_key_iv = obfuscated_iv.txt |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BHIV_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bh_key_iv |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Initialization vector used when decrypting the obfuscated key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bh_key_iv = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bh_gry_key, |\n\ | bh_keyfile = obfuscated_key.txt |\n\ | bh_key_iv = obfuscated_iv.txt |\n\ | aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_METAL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | familykey |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specify family key to generate obfuscated key from red key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | familykey = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | aeskeyfile = encr.nky |\n\ | bh_key_iv = bh_iv.txt |\n\ | familykey = familykey.txt |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_BLOCKS_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | blocks |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specify block sizes for key-rolling feature in encrytion. |\n\ | Each module is encrypted using its own unique key. The initial |\n\ | key is stored at the key source on the device, while keys for |\n\ | each successive module are encrypted (wrapped) in the previous |\n\ | module. |\n\ | mentioned will be taken in Bytes. If X(*) is specified, |\n\ | then all the remaining blocks would of the size 'X'. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { blocks = ; ; ...; <*> } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | blocks= 512(2); 65536; 8192(*) |\n\ | file = plm.elf |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n\ | In the above example, the first two blocks are of 512 bytes, |\n\ | next block is of 65536 bytes, the rest of the partition into |\n\ | blocks of 8192 bytes. |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_DELAYHNDOFF_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | delay_handoff |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | With this flag specified, the handoff to subsystem is delayed |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { delay_handoff } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = subsys_1, id = 0x1c000000, delay_handoff |\n\ | { type = cdo, file = apu_cdo.cdo } |\n\ | { core = a72-0, file = apu.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_DELAYLOAD_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | delay_load |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | With this flag specified, the loading of subsystem is delayed |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { delay_load } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = subsys_1, id = 0x1c000000, delay_load |\n\ | { type = cdo, file = apu_cdo.cdo } |\n\ | { core = a72-0, file = apu.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_PARTITION_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | partition |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define a partition |\n\ | It is an optional attribute to make the BIF short and readable |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | partition { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = WDI_FLAT, id = 0x1c000000 |\n\ | partition |\n\ | { |\n\ | id = 0x1 |\n\ | type = bootloader |\n\ | file = plm.elf |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x9 |\n\ | type = pmcdata, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x3 |\n\ | type = cdo |\n\ | file = bitstream.rcdo |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x4 |\n\ | file = bitstream.rcfi |\n\ | } |\n\ | } |\n\ | } |\n\ | |\n\ | The same BIF can be written in shorter format as: |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = WDI_FLAT, id = 0x1c000000 |\n\ | { id = 0x1, type = bootloader, file = plm.elf } |\n\ | { id = 0x9, type = pmcdata, file = pmc_cdo.bin } |\n\ | { id = 0x3, type = cdo, file = bitstream.rcdo } |\n\ | { id = 0x4, file = bitstream.rcfi } |\n\ | } |\n\ | } |\n\ | |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_IMAGE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | image |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define a subsytem/image |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | image { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = PMC_SS, id = 0x1c000000 |\n\ | { id = 0x1, type = bootloader, file = plm.elf } |\n\ | { id = 0x9, type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = PL_SS, id = 0x1c000004 |\n\ | { id = 0x3, type = cdo, file = bitstream.rcdo } |\n\ | { id = 0x4, file = bitstream.rcfi } |\n\ | { id = 0x4, file = bitstream.rnpi } |\n\ | } |\n\ | } |\n\ | |\n\ | Here two subsystems/images are created: |\n\ | 1. PMC_SS (0x1c000000) |\n\ | 2. PL_SS (0x1c000004) |\n\ -------------+----------------------------------------------------------------|\n" #define HV_BIF_METAHDR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | metahdr |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define encryption, authentication |\n\ | attributes for meta headers like keys, key sources etc. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | metahdr { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | metaheader |\n\ | { |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = headerkey.nky, |\n\ | authentication = rsa |\n\ | } |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | blocks = 8192(*), |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------|\n" #define HV_BIF_RES_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | reserve |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Reserves the memory and padded after the partition. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { reserve = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_data.cdo } |\n\ | { reserve = 0x1000, file = system.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_COPY_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | copy |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Copies the image to memory at specified address. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { copy = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { id = 0x1, type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = subsys_1, id = 0x1c000000, copy = 0x30000 |\n\ | { core = psm, file = psm.elf } |\n\ | { type = cdo, file = ps_data.cdo } |\n\ | { core = a72 - 0, file = a72_app.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_STARTUP_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | startup |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Provides the start/execution address in case of binary file |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { startup = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf} |\n\ | { type = pmcdata, file = pmc_cdo.bin} |\n\ | { core = psm, file = psm_fw.elf} |\n\ | { type = cdo, file = ps_cdo.bin} |\n\ | { core = a72-0, load = 0x20000, startup = 0x20000, |\n\ | file = a72_app.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_PARENTID_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | parent_id |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the ID for the parent PDI. This is used to identify |\n\ | the relationship between a partial PDI and its corresponding |\n\ | Boot PDI |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | parent_id = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | parent_id = 0x2 |\n\ | image |\n\ | { |\n\ | name = psm_ss, id = 0x1c000001 |\n\ | { core = psm, file = psm_fw.elf } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_ss, id = 0x1c000002 |\n\ | { type = cdo, file = ps_cdo.bin } |\n\ | { core = a72-0, file = a72_app.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_ID_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | id |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the following IDs based on the place its defined: |\n\ | * pdi id - within outermost/pdi paranthesis |\n\ | * image id - within image paranthesis |\n\ | * partition id - within partition paranthesis |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | id = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 // PDI ID |\n\ | image |\n\ | { |\n\ | name = pmc_ss, |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | type = bootloader, |\n\ | id = 0x1, // Partition ID |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = psm_ss, |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | core = psm, |\n\ | id = 0x3, // Partition ID |\n\ | file = psm_fw.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_ss, |\n\ | id = 0x1c000002 // Image ID |\n\ | { |\n\ | type = cdo, |\n\ | id = 0x4, // Partition ID |\n\ | file = apu_cdo.bin |\n\ | } |\n\ | { |\n\ | core = a72-0, |\n\ | id = 0x5, // Partition ID |\n\ | file = a72_app.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_NAME_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | name |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the name of the image/subsystem |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | name = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 // PDI ID |\n\ | image |\n\ | { |\n\ | name = pmc_ss, // Image name |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | type = bootloader, |\n\ | id = 0x1, // Partition ID |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_FILE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | file |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the file for creating the partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { file = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf} |\n\ | { type = pmcdata, file = pmc_cdo.bin} |\n\ | { core = psm, file = psm_fw.elf} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_PMCDATA_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | pmcdata |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the PMC CDO file which is stiched along with PLM to |\n\ | form a single partition loaded by BootRoM |\n\ | This data is encrypted separately but authenticated as a single|\n\ | partition along with PLM |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { type = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf} |\n\ | { type = pmcdata, file = pmc_cdo.bin} |\n\ | { core = psm, file = psm_fw.elf} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #endif xilinx-bootgen-2024.2/help.h000077500000000000000000010405251475706442400157010ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _HELP_H_ #define _HELP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include /****************************************************************************** enable authentication optimization ******************************************************************************/ #define ENABLEAUTHOPTHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | enable_auth_opt |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -enable_auth_opt |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Enables authentication optimization |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -help enable_auth_opt |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | boot.bin generated have meta header and partition hashes |\n\ | stored as part of optional data |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** arch ******************************************************************************/ #define ARCHHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | arch |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Device architecture for which the bootimage needs to be created|\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -arch [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | *zynq : Image is targeted for ZYNQ architecture |\n\ | zynqmp : Image is targeted for ZYNQ MP SoC architecture |\n\ | versal : Image is targeted for VERSAL ACAP architecture |\n\ | fpga : Image is targeted for other FPGA architectures |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynq -image test.bif -o boot.bin |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | boot.bin generated is a Zynq boot image |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bif_help ******************************************************************************/ #define BIFHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | bif_help |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to list all the supported BIF file |\n\ | attributes. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -bif_help [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | Any of the bif attributes |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | 1. bootgen -bif_help |\n\ | 2. bootgen -bif_help aeskeyfile |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Usage 1: All the bif file attributes are listed |\n\ | Usage 2: Detailed explanation of the attribute aeskeyfile with |\n\ | example |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** dual_ospi_mode ******************************************************************************/ #define DOSPIHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | dual_ospi_mode |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option generates output files as per the configuration |\n\ | specified by the Dual OSPI mode |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -dual_ospi_mode [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | stacked : |\n\ | The OSPI configuration is Dual Stacked. |\n\ | Generates 2 output files, in sequential fashion. |\n\ | - Size of flash in MB (16/32/64/128) |\n\ | Both the flashes can then be programmed independently. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o -boot.bin |\n\ | -dual_ospi_mode stacked 64 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Suppose the output bootimage content is around 120MB |\n\ | Two files are generated boot_1.bin & boot_2.bin of |\n\ | 64MB & 56MB |\n\ |----------------------------------------------------------------|\n\ | Suppose the output bootimage content is around 50MB |\n\ | Only one file is generated boot_1.bin of 50MB |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** dual_qspi_mode ******************************************************************************/ #define DQSPIHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | dual_qspi_mode |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option generates output files as per the configuration |\n\ | specified by the Dual QSPI mode |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -dual_qspi_mode [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | parallel : |\n\ | The QSPI configuration is Dual Parallel |\n\ | Generates 2 output files, the actual output is written to |\n\ | two different files in bit-by-bit fashion. |\n\ | stacked : |\n\ | The QSPI configuration is Dual Stacked. |\n\ | Generates 2 output files, in sequential fashion. |\n\ | - Size of flash in MB (16/32/64/128) |\n\ | Both the flashes can then be programmed independently. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | 1. bootgen -image test.bif -o -boot.bin |\n\ | -dual_qspi_mode parallel |\n\ |----------------------------------------------------------------|\n\ | 2. bootgen -image test.bif -o -boot.bin |\n\ | -dual_qspi_mode stacked 64 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Suppose the output bootimage content is around 120MB |\n\ | Usage 1: Two files are generated boot_1.bin & boot_2.bin of |\n\ | 60MB each |\n\ | Usage 2: Two files are generated boot_1.bin & boot_2.bin of |\n\ | 64MB & 56MB |\n\ |----------------------------------------------------------------|\n\ | Suppose the output bootimage content is around 50MB |\n\ | Usage 1: Two files are generated boot_1.bin & boot_2.bin of |\n\ | 25MB each |\n\ | Usage 2: Only one file is generated boot_1.bin of 50MB |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** dump ******************************************************************************/ #define DUMPHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | dump |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to dump partitions, bootheader and SSIT |\n\ | slave PDIs as binary files. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -dump [arguments] |\n\ | The files are dumped from the PDI mentioned with |\n\ ------------------------------------------------------------------------------|\n\ ARGUMENTS | boot_files : Dumps all boot files(Boot header, PLM and PMC CDO)|\n\ | plm : Dumps the plm partition |\n\ | pmc_cdo : Dumps pmc_cdo partition |\n\ | |\n\ | Note : When no arguments are specifed, all the partitions are |\n\ | dumped. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -dump [arguments] |\n\ | This must used while generating the PDI, and the files are |\n\ | dumped along with the PDI |\n\ ------------------------------------------------------------------------------|\n\ ARGUMENTS | bh : Dumps the Boot Header |\n\ | slave_pdis : Dumps slave PDIs for SSIT devices |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | 1. bootgen -arch versal -dump test.pdi |\n\ | 2. bootgen -arch versal -dump test.pdi boot_files |\n\ | 3. bootgen -arch versal -image test.bif -w on -o |\n\ | test.pdi -dump slave_pdis |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | 1. The partitions in the PDI are dumped as binary files. |\n\ | 2. Dumps all boot files - Boot header, PLM and PMC CDO, as |\n\ | binary files. |\n\ | 3. Slave PDIs for SSIT devices are dumped as binary files. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** dump_dir ******************************************************************************/ #define DUMPDIRHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | dump_dir |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used with dump option to dump partitions in the |\n\ | directory specified here. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -dump_dir |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch versal -dump -dump_dir |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The partitions in the PDI are dumped as binary files in the |\n\ | dump directory. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** efuseppkbits ******************************************************************************/ #define EFUSEPPKBITSHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | efuseppkbits |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies the name of the efuse file to be written |\n\ | to contain the PPK hash. This option generates a direct hash |\n\ | without any padding. |\n\ | Zynq - Hashing done by SHA2 |\n\ | ZynqMP & Versal - Hashing done by SHA3 |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -efuseppkbits |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o boot.bin |\n\ | -efuseppkbits efusefile.txt |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | efusefile.txt file gets generated, which contains the hash of |\n\ | the PPK key. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** encrypt ******************************************************************************/ #define ENCRYPTHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | encrypt |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, fpga |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies how to do encryption, where the keys are |\n\ | stored. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -encrypt [key source args] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | Key source arguments: |\n\ | efuse : The AES key is stored in EFUSE |\n\ | bbram : The AES key is stored in BBRAM |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o boot.bin -encrypt efuse |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The .nky key file is passed through BIF file attribute |\n\ | [aeskeyfile]. Only source is specified through command line. |\n\ -------------+----------------------------------------------------------------+\n\ NOTE | For other devices, key source is specified using BIF attribute |\n\ | keysrc_encryption or keysrc |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** encryption_dump ******************************************************************************/ #define ENCRDUMPHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | encryption_dump |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Generates encryption log file, aes_log.txt |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -encryption_dump |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -arch zynqmp -image test.bif -encryption_dump] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [bootloader, encryption=aes, aeskeyfile=test.nky] fsbl.elf |\n\ | [encryption=aes,aeskeyfile=test2.nky] hello.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | aes_log.txt generated has the details of AES Key/IV pairs used |\n\ | for encrypting each block of data. It also logs the partition |\n\ | and the aes key file used to encrypt it. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** fill ******************************************************************************/ #define FILLHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | fill |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies the byte to use for filling extra memory |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -fill |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -arch zynq -image test.bif -fill 0xAB -o boot.bin] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Byte 0xAB is padded in the header tables instead of 0xFF when |\n\ | fill is specified. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** generate_hashes ******************************************************************************/ #define GENERATEHASHESHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | generate_hashes |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option generates file containing padded hash |\n\ | Zynq - SHA-2 with PKCS#1v1.5 padding scheme |\n\ | ZynqMP - SHA-3 with PKCS#1v1.5 padding scheme |\n\ | Versal - SHA-3 with PSS padding scheme |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -generate_hashes |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -generate_hashes |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | To generate a SPK hash |\n\ | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [spkfile]secondary.pub |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** generate_keys ******************************************************************************/ #define GENKEYSHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | generate_keys |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option generates keys. |\n\ | . Generates authentication keys in rsa/pem format. |\n\ | . Generate Obfuscated Key for encryption. |\n\ | BIF File should have the paths of all the keys. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | For authentication : |\n\ | -generate_keys [arguments] |\n\ | For encryption : |\n\ | -generate_keys obfuscatedkey |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | Format of authentication keys |\n\ | rsa : RSA format keys |\n\ | pem : PEM format keys |\n\ | ecdsa-p384 : ecdsap384 keys |\n\ | ecdsa-p521 : ecdsap521 keys |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | For authentication : |\n\ | bootgen -image test.bif -generate_keys rsa |\n\ | bootgen -image test.bif -generate_keys ecdsa-p384 |\n\ | bootgen -image test.bif -generate_keys ecdsa-p521 |\n\ | For encryption : |\n\ | bootgen -image test.bif -generate_keys obfuscatedkey |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | For authentication : |\n\ | Contents of BIF file: test.bif |\n\ | image: |\n\ | { |\n\ | [ppkfile] |\n\ | [pskfile] |\n\ | [spkfile] |\n\ | [sskfile] |\n\ | } |\n\ | The key files are generated in the paths mentioned above |\n\ |----------------------------------------------------------------|\n\ | For encryption : |\n\ | image: |\n\ | { |\n\ | [aeskeyfile] aes.nky |\n\ | [bh_key_iv] bhkeyiv.txt |\n\ | [familykey] familykey.txt |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n\ NOTES | PEM Key Format: |\n\ | -----BEGIN RSA PRIVATE KEY----- |\n\ | MIIEpAIBAAKCAQEAmlJyPcZVXltASHrtm/YnOMxskf0k2RZrIajqymqZptnG |\n\ | kyBMalXaqmGb1kqGCgGZVvQt3FSRO3yXa.... |\n\ | -----END RSA PRIVATE KEY----- |\n\ | |\n\ | -----BEGIN EC PRIVATE KEY----- |\n\ | MIGkAgEBBDAqm8l04lfuEOFZI988uJ8b5UcP45hFIDk/OmsXItT3vk0SJM/ |\n\ | HILiz4ZPnphfDt4egBwYFK4EEACKhZANiAAQiLcPBptJyMq4J+1/6wkUIrYY |\n\ | iTfiGTxRRZ7ZaejZQH/kcojjv6yqkHqkxt44f16nqwHCAkb4yb+2tDbqi9uMnf|\n\ | 5roGFnDx+6xkXn7ZCeldcLF2gdajH08AiXjXKgxTM0= |\n\ | -----END EC PRIVATE KEY----- |\n\ | |\n\ |----------------------------------------------------------------|\n\ | RSA Key Format: |\n\ | N = c6b9a521234567890abc4d4567e99f1234567891235987564.... |\n\ | E = 10001 |\n\ | D = 37c80c81234567890abcdef1234567890abcdef1234567790.... |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** image ******************************************************************************/ #define IMAGEHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | image |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Input BIF file name |\n\ | BIF file specifies each component of the boot image in order of|\n\ | boot and allows optional attributes to be specified to each |\n\ | image component. Each image component is usually mapped to a |\n\ | partition, but in some cases an image component can be mapped |\n\ | to more than one partition if the image component is not |\n\ | contiguous in memory |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -image |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -arch zynq -image test.bif -o boot.bin] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | test.bif is the input BIF file |\n\ | Sample BIF file is shown below |\n\ | test: |\n\ | { |\n\ | [init] init_data.int |\n\ | [bootloader] Fsbl.elf |\n\ | Partition1.bit |\n\ | Partition2.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** log ******************************************************************************/ #define LOGHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | log |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This command generates log while generating the bootimage. |\n\ | There are various options for choosing the level of information|\n\ | The information is displayed on the console as well as log file|\n\ | named 'bootgen_log.txt' in the current working directory. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -log [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | error : Only the error information is captured. |\n\ |*warning : The warnings & error information is captured. |\n\ | info : The general info and all the above info is captured. |\n\ | debug : The debugging info in case of errors is captured in |\n\ | in detail and all the above info is captured. |\n\ | trace : More detailed information is captured along with the |\n\ | above |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o -boot.bin -log trace |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The detailed info is described while creating the bootimage. |\n\ | The file 'bootgen_log.txt' is generated. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** nonbooting ******************************************************************************/ #define NONBOOTINGHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | nonbooting |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Used for generating an intermediate boot image. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -nonbooting |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynq -image test.bif -o test.bin -nonbooting |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [ppkfile]primary.pub |\n\ | [spkfile]secondary.pub |\n\ | [spksignature]secondary.pub.sha256.sig |\n\ | [bootimage,authentication=rsa, |\n\ | presign=fsbl_0.elf.0.sha256.sig]fsbl_e.bin |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | An intermediate image test.bin is generated as output even in |\n\ | the absence of secret key, which is actually needed to generate|\n\ | an authenticated image. |\n\ | This intermediate image cannot be booted. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** o ******************************************************************************/ #define OHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | o |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies the name of the output image file with |\n\ | bin or mcs extension. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -o |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynq -image test.bif -o boot.mcs |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The output image is generated with name boot.mcs |\n\ | The format of the output image is decided based on the file |\n\ | extension of the file given with '-o' option |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** overlay_cdo ******************************************************************************/ #define OVERLAYCDO "\ -------------+----------------------------------------------------------------+\n\ OPTION | overlay_cdo |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | CDO overlay option provides a way to modify CDO files |\n\ | after they are generated. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -overlay_cdo |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch versal -image test.bif |\n\ | -o test.bin -overlay_cdo ovl.cdo |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The input file used with overlay_cdo command would have markers|\n\ | and content which needs to be overlayed. |\n\ | Bootgen searches for similar markers in all the cdo files |\n\ | present inside BIF, when found the content in that cdo will be |\n\ | replaced with the content from overlay cdo. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** p ******************************************************************************/ #define PHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | p |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies the partname of the Device. |\n\ | This is needed for generating a encryption key. It is copied |\n\ | verbatim to the *.nky file in the 'Device' line. |\n\ | This is applicable only with encryption is enabled. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -p |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o boot.bin -p xc7z020clg484 |\n\ | -encrypt efuse |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | If the key file is not present in the path specified in BIF |\n\ | file, then a new encryption key is generated in the same path |\n\ | and xc7z020clg484 is copied along side the 'Device' field in |\n\ | the nky file. The generated image is an encrypted image. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** padimageheader ******************************************************************************/ #define PADHDRHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | padimageheader |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option pads the Image Header Table and Partition Header |\n\ | Table to maximum partitions allowed, to force alignment of |\n\ | following partitions. This feature is enabled by default. |\n\ | Specifying a 0, disables this feature |\n\ | Zynq : Maximum Partitions - 14 |\n\ | ZynqMP : Maximum Partitions - 32 |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -padimageheader [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | *1 : Pad the header tables to max partitions |\n\ | 0 : Do not pad the header tables |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -w on -o boot.bin -padimageheader 0 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | boot.bin has the image header tables and partition header |\n\ | tables in actual and no extra tables are padded. If nothing is |\n\ | specified or if '-padimageheader 1' is used, then total image |\n\ | header tables and partition header tables are padded |\n\ | to max partitions. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** post_process ******************************************************************************/ #define POSTPROCESSHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | post_process |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used for post processing of CDO files. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -post_process |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -arch versal -image test.bif -o test.bin |\n\ | -post_process 3] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | 1, 2, 3, 4, cfi-write, cfi-dma-write, cfi-dma-write-keyhole, |\n\ | iso-all |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** process_bitstream ******************************************************************************/ #define PROCESSBITHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | process_bitstream |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Processes only bitstream from the BIF, and output as an MCS or |\n\ | a BIN file. |\n\ | For example: If encryption is selected for bitstream in the BIF|\n\ | file, the output is an encrypted bitstream. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -process_bitstream [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | bin : Output in bin format |\n\ | mcs : Output in mcs format |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynq -image test.bif -process_bitstream bin |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | system.bit |\n\ | } |\n\ | Output generated is bitstream in BIN format. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** read ******************************************************************************/ #define READHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | read |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This options reads the bootimage and dumps the header tables in|\n\ | readable form. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -read [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | bh : Reads boot header |\n\ | iht : Reads image header table |\n\ | ih : Reads image headers |\n\ | pht : Reads partition header tables |\n\ | ac : Reads authentication certificates |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | 1. bootgen -image test.bif -o boot.bin -read |\n\ | 2. bootgen -image test.bif -o boot.bin -read pht |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | 1. Reads all the headers and dump on console |\n\ | 2. Reads partition header tables and dump on console |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** securedebugimage ******************************************************************************/ #define SECUREDEBUGHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | authenticatedjtag |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to enable JTAG during secure boot |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -authenticatedjtag [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | rsa : Image created using RSA |\n\ | ecdsa : Image created using ECDSA |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch versal -image test.bif -authenticatedjtag rsa |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** split ******************************************************************************/ #define SPLITHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | split |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option outputs each data partition with headers as a new |\n\ | file in MCS or BIN format. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -split [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | bin : Output files generated in bin format |\n\ | mcs : Output files generated in mcs format |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -arch zynq -image test.bif -split bin] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Consider the sample bif |\n\ | test: |\n\ | { |\n\ | [bootloader] Fsbl.elf |\n\ | Partition1 |\n\ | Partition2 |\n\ | } |\n\ | Output files generated are: |\n\ | 1. Bootheader + Image Headers + Partition Headers + Fsbl.elf |\n\ | 2. Partition1.bit |\n\ | 3. Partition2.elf |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** spksignature ******************************************************************************/ #define SPKSIGNHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | spksignature |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to generate the SPK signature file. This |\n\ | option must be used only when [spkfile] & [pskfile] are |\n\ | specified in BIF |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -spksignature |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootgen -image test.bif -w on -o boot.bin |\n\ | -spksignature spksignfile.txt] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The SPK signature file (spksignfile.txt) is generated. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** verify ******************************************************************************/ #define VERIFYHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | verify |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used for verifying authentication of a bootimage|\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -verify |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynqmp -verify boot.bin |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | All the authentication certificates in a boot image will be |\n\ | verified against the available partitions. |\n\ | The verification process is done as below - |\n\ | 1. Verify Header Authentication Certificate |\n\ | verify SPK Signature |\n\ | verify Header Signature |\n\ | 2. Verify Bootloader Authentication Certificate |\n\ | verify Boot Header Signature |\n\ | verify SPK Signature |\n\ | verify Bootloader Signature |\n\ | 3. Verify Partition Authentication Certificate |\n\ | verify SPK Signature |\n\ | verify Partition Signature |\n\ | This is repeated for all partitions in the given boot image.|\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** verify_kdf ******************************************************************************/ #define VERIFYKDFHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | verify_kdf |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to validate the Counter Mode KDF used in |\n\ | bootgen for generation of AES keys.. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -verify |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynqmp -verify_kdf testvector.txt |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The format of the testvector.txt file is as below. |\n\ | L = 256 |\n\ | KI = d54b6fd94f7cf98fd955517f937e9927f9536caebe148...... |\n\ | FixedInputDataByteLen = 60 |\n\ | FixedInputData = 94c4a0c69526196c1377cebf0a2ae0fb4b57797.... |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** w ******************************************************************************/ #define WHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | w |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies whether to overwrite an existing file or |\n\ | not. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -w [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | on : Overwrite the existing file |\n\ | *off : Don't overwrite the existing file |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -w on -o boot.bin or |\n\ | bootgen -image test.bif -w -o boot.bin |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | If the file boot.bin already exists in the path, then it is |\n\ | overwritten. |\n\ | Options '-w on' & '-w' are treated as same |\n\ | If the '-w' option is not specified, the file will not be |\n\ | overwritten by default |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** zynqmpes1 ******************************************************************************/ #define ZYNQMPES1HELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | zynqmpes1 |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option specifies that the image generated will be used |\n\ | on ES1(1.0). |\n\ | This option makes a difference only when generating |\n\ | authenticated image, else ignored. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -zynqmpes1 |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -image test.bif -o boot.bin -zynqmpes1 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | The authentication padding scheme will be as per ES1(1.0). |\n\ | The default padding scheme is for (2.0)ES2 and above. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** out_type ******************************************************************************/ #define OUTTYPEHELP "\ -------------+----------------------------------------------------------------+\n\ OPTION | out_type |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option create output file in MCS or BIN format |\n\ | depending on input argument to option. |\n\ -------------+----------------------------------------------------------------+\n\ SYNOPSIS | -out_type [arguments] |\n\ -------------+----------------------------------------------------------------+\n\ ARGUMENTS | bin : Output file generated in bin format |\n\ | mcs : Output file generated in mcs format |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | bootgen -arch zynq -image test.bif -w on -o test.bin |\n\ | -out_type bin |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Output file can be generated using this option and |\n\ | it can be of BIN or MCS format. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** aarch32_mode ******************************************************************************/ #define H_BIF_AARCH32_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | aarch32_mode |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the partition is to be executed in 32-bit mode. |\n\ | Only valid for binary partitions. |\n\ | For elf files, bootgen automatically detects the execution |\n\ | mode from elf header. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [aarch32_mode] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { aarch32_mode, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] zynqmp_fsbl.elf |\n\ | [destination_cpu=a53-0, aarch32_mode] hello.bin |\n\ | [destination_cpu=r5-0] hello_world.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, aarch32_mode, file=apu.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /****************************************************************************** alignment ******************************************************************************/ #define H_BIF_ALIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | alignment |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the byte alignment. The partition will be padded to be |\n\ | aligned to a multiple of this value. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [alignment=] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { alignment=, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | [alignment=64] u-boot.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, alignment=64, file=uboot.elf } |\n\ | } |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Note: Cannot be used with offset. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** big_endian ******************************************************************************/ #define H_BIF_BIGENDIAN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | big_endian |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the partition in big endian |\n\ | Only valid for binary partitions. |\n\ | For elf files, bootgen automatically detects the endianness |\n\ | from elf header. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [big_endian] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { big_endian, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] zynqmp_fsbl.elf |\n\ | [destination_cpu=a53-0, big_endian] hello.bin |\n\ | [destination_cpu=r5-0] hello_world.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, big_endian, file=apu.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /****************************************************************************** blocks ******************************************************************************/ #define H_BIF_BLOCKS_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | blocks |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specify block sizes for key-rolling feature in encrytion. |\n\ | Each module is encrypted using its own unique key. The initial |\n\ | key is stored at the key source on the device, while keys for |\n\ | each successive module are encrypted (wrapped) in the previous |\n\ | module. |\n\ | mentioned will be taken in Bytes. If X(*) is specified, |\n\ | then all the remaining blocks would of the size 'X'. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [blocks = ;;...;<*>] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { blocks = ;...;<*>, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [bootloader, encryption=aes, destination_cpu=a53-0, |\n\ | blocks=4096(2);1024;2048(2);4096(*), |\n\ | aeskeyfile=encr.nky] fsbl.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, encryption=aes, |\n\ | blocks==4096(2);1024;2048(2);4096(*), |\n\ | aeskeyfile=encr1.nky,file=plm.elf } |\n\ | { type=pmcdata, aeskeyfile=encr2.nky, file=pmc_cdo.bin } |\n\ | } |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | In the above example, the first two blocks are of 4096 bytes, |\n\ | second block is of 1024 bytes, the next two blocks are of |\n\ | 2048 bytes, the rest of the blocks are of 4096 bytes. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bootimage ******************************************************************************/ #define H_BIF_BOOTIMAGE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bootimage |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies that the following file specification is a |\n\ | bootimage that was created by Bootgen, being reused as input. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [bootimage] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { type=bootimage, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootimage] fsbl.bin |\n\ | [bootimage] system.bin |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootimage, file=boot.pdi } |\n\ | { core=a72-0, file=apu.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bootloader ******************************************************************************/ #define H_BIF_BL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bootloader |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition is a bootloader (FSBL). This |\n\ | attribute is specified with along with other partition bif |\n\ | attributes. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [bootloader] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { type=bootloader, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | hello.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bootvectors ******************************************************************************/ #define H_BIF_BOOTVEC_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bootvectors |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the vector table for XIP |\n\ | By default, bootgen populates XIP elf vector table below - |\n\ | - 0xEAFFFFFE: for Cortex R5 and Cortex A53 (32-bit) |\n\ | - 0x14000000: for Cortex A53 (64-bit) |\n\ | To specify a different vector table, bootvectors can be used. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bootvectors] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [bootvectors] 0x14000000,0x14000000,0x14000000,0x14000000, |\n\ | 0x14000000,0x14000000,0x14000000,0x14000000 |\n\ | [bootloader,destination_cpu=a53-0] fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** boot_device ******************************************************************************/ #define H_BIF_BOOTDEV_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | boot_device |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the secondary boot device. Indicates the device on |\n\ | which the partition is present. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [boot_device] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | boot_device { , address=
} |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | ZYNQMP: |\n\ | qspi32, qspi24, nand, sd0, sd1, sd-ls, mmc, usb, ethernet |\n\ | pcie, sata |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | qspi32, qspi24, nand, sd0, sd1, sd-ls, mmc, usb, ethernet, |\n\ | pcie, sata, ospi, smap, sbi, sd0-raw, sd1-raw, sd-ls-raw, |\n\ | mmc-raw, mmc0, mmc0-raw, imagestore |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [boot_device] sd0 |\n\ | [bootloader,destination_cpu=a53-0] fsbl.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | boot_device { qspi32, address=0x10000 } |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define H_BIF_BOOTCONFIG_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | boot_config |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | These parameters are used to configure the bootimage |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | boot_config { } |\n\ -------------+---------------------+------------------------------------------+\n\ OPTIONS | Options | Description |\n\ +---------------------+------------------------------------------+\n\ | bh_auth_enable | Boot Header Authentication Enable: |\n\ | | Authentication of the bootimage will |\n\ | | be done excluding the verification of |\n\ | | PPK hash and SPK ID. |\n\ +---------------------+------------------------------------------+\n\ | a_hwrot | Asymmetric Hardware Root of Trust |\n\ | | (A-HWRoT) Boot Mode : |\n\ | | Bootgen checks aganist the design rules |\n\ | | for A-HWRoT Boot Mode. |\n\ | | Valid only for Production PDIs |\n\ +---------------------+------------------------------------------+\n\ | s_hwrot | Symmetric Hardware Root of Trust |\n\ | | (S-HWRoT) Boot Mode : |\n\ | | Bootgen checks aganist the design rules |\n\ | | for S-HWRoT Boot Mode. |\n\ | | Valid only for Production PDIs |\n\ +---------------------+------------------------------------------+\n\ | pufhd_bh | PUF helper data is stored in BH. |\n\ | | (Default is efuse) |\n\ | | PUF helper data file is passed to bootgen|\n\ | | using the option [puf_file]. |\n\ +---------------------+------------------------------------------+\n\ | puf4kmode | PUF is tuned to use in 4k bit syndrome |\n\ | | configuration. |\n\ | | (Default is 12k bit) |\n\ +---------------------+------------------------------------------+\n\ | shutter = | 32 bit PUF_SHUT register value to |\n\ | | configure PUF for shutter offset time |\n\ | | and shutter open time. |\n\ +---------------------+------------------------------------------+\n\ | smap_width = | 8, 16, 32 |\n\ | | Default is 32-bit |\n\ -------------+---------------------+------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | bh_auth_enable_smap_width: |\n\ | { |\n\ | boot_config { bh_auth_enable, smap_width=16 } |\n\ | pskfile = /path/to/primary0.pem |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | authentication = rsa, |\n\ | sskfile = /path/to/secondary-key.pem, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | } |\n\ +----------------------------------------------------------------|\n\ | dpacm_enable: |\n\ | { |\n\ | boot_config { dpacm_enable } |\n\ | image |\n\ | { |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, blocks = 4096(*), |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | core = psm, |\n\ | encryption = aes, blocks = 4096(*), |\n\ | keysrc = bbram_red_key, aeskeyfile = key3.nky, |\n\ | file = psm.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** checksum ******************************************************************************/ #define H_BIF_CHKSM_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | checksum |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be checksummed. |\n\ | Checksum Algorithms: |\n\ | Zynq : MD5 |\n\ | ZynqMP & Versal : SHA3 |\n\ |----------------------------------------------------------------|\n\ | Note: |\n\ | 1. In Zynq, checksum opertations is not supported for |\n\ | bootloaders. |\n\ | 2. Checksum operation is not supported with secure features |\n\ | like authentication and encryption |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [checksum = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { checksum = , file= } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : no checksum operation |\n\ | md5 : MD5 checksum operation (Zynq) |\n\ | sha3 : SHA3 checksum operation (ZynqMP & Versal) |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | [checksum=md5] hello.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------+\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, checksum=sha3, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** copy ******************************************************************************/ #define H_BIF_COPY_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | copy |\n\ -------------+----------------------------------------------------------------+\n\ + DEPRECTAED |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** core ******************************************************************************/ #define H_BIF_CORE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | core |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies which core will execute the partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { core = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *a72-0 |\n\ | a72-1 |\n\ | r5-0 |\n\ | r5-1 |\n\ | psm |\n\ | aie |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** delay_handoff ******************************************************************************/ #define H_BIF_DELAY_HANDOFF_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | delay_handoff |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute specifies that the handoff to the subsystem is |\n\ | delayed. |\n\ | This is a image specific attribute and needs to be defined at |\n\ | image level and not partition level. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | delay_handoff |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | boot_device { qspi32, address=0x10000 } |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = image2, id = 0x1c000002, delay_handoff |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** delay_load ******************************************************************************/ #define H_BIF_DELAY_LOAD_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | delay_load |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute specifies that the loading the subsystem is |\n\ | delayed. |\n\ | This is a image specific attribute and needs to be defined at |\n\ | image level and not partition level. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | delay_load |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | boot_device { qspi32, address=0x10000 } |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = image2, id = 0x1c000002, delay_load |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** destination_cpu ******************************************************************************/ #define H_BIF_DESTCPU_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | destination_cpu |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies which core will execute the partition |\n\ |----------------------------------------------------------------|\n\ | Note: |\n\ | * FSBL can run either on A53-0 or R5-0 only. |\n\ | * PMU loaded by FSBL: [destination_cpu=pmu] pmu.elf |\n\ | In this flow, BootROM loads FSBL first, and then FSBL loads |\n\ | PMU fw. |\n\ | * PMU loaded by BootROM: [pmufw_image] pmu.elf |\n\ | In this flow, BootROM loads PMU first and then the FSBL |\n\ | So PMU does the power management tasks, before the FSBL comes|\n\ | up. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [destination_cpu=] |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *a53-0 |\n\ | a53-1 |\n\ | a53-2 |\n\ | a53-3 |\n\ | r5-0 |\n\ | r5-1 |\n\ | r5-lockstep |\n\ | pmu |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [destination_cpu=r5-0] app.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | This specifies that FSBL will be excuted on A53-0 core and |\n\ | application on R5-0 core. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** destination_device ******************************************************************************/ #define H_BIF_DESTDEV_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | destination_device |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the destination of the partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [destination_device=] |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *ps : The partition is targetted for PS (default) |\n\ | pl : The partition is targetted for PL, for bitstreams |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [destination_device=pl] system.bit |\n\ | [destination_cpu=r5-1] app.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** early_handoff ******************************************************************************/ #define H_BIF_ELYHNDOFF_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | early_handoff |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This flag will ensure, the handoff to applications which are |\n\ | critical, immediatley after partition is loaded. Otherwise all |\n\ | the partitions are loaded sequentially and handoff also happens|\n\ | in sequenctial fashion |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [early_handoff] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53_0] fsbl.elf |\n\ | [destination_cpu=r5-0] app1.elf |\n\ | [destination_cpu=r5-1, early_handoff] app2.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Note: In the above scenario, the FSBL loads app1, then app2 |\n\ | and immediately handsoff the control to app2 before app1. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** exception_level ******************************************************************************/ #define H_BIF_EL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | exception_level |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Exception level for which the core should be configured |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [exception_level=] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { exception_level=, file= } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | el-0 |\n\ | el-1 |\n\ | el-2 |\n\ | *el-3 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [destination_cpu=a53-0, exception_level=el-3] bl31.elf |\n\ | [destination_cpu=a53-0, exception_level=el-2] u-boot.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=uboot.elf } |\n\ | { core=a72-0, exception_level=el-3, file=bl31.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** file ******************************************************************************/ #define H_BIF_FILE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | file |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the file for creating the partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { file = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.cdo, file=topology.cdo } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Multiple CDO files can be merged together into one partition |\n\ | by specifying multiple 'file' attributes as shown above for |\n\ | pmc_cdo.cdo and topology.cdo |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** fsbl_config ******************************************************************************/ #define H_BIF_FSBLCFG_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | fsbl_config |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | These parameters are used to configure the bootimage |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [fsbl_config] |\n\ -------------+---------------------+------------------------------------------+\n\ OPTIONS | Options | Description |\n\ +---------------------+------------------------------------------+\n\ | bh_auth_enable | Boot Header Authentication Enable: |\n\ | | RSA authentication of the bootimage will |\n\ | | be done excluding the verification of |\n\ | | PPK hash and SPK ID. |\n\ +---------------------+------------------------------------------+\n\ | auth_only | Boot image is only RSA signed. |\n\ | | FSBL should not be decrypted. |\n\ +---------------------+------------------------------------------+\n\ | opt_key | Optional key is used for block-0 |\n\ | | decryption. Secure Header has the opt key|\n\ +---------------------+------------------------------------------+\n\ | pufhd_bh | PUF helper data is stored in BH. |\n\ | | (Default is efuse) |\n\ | | PUF helper data file is passed to bootgen|\n\ | | using the option [puf_file]. |\n\ +---------------------+------------------------------------------+\n\ | puf4kmode | PUF is tuned to use in 4k bit syndrome |\n\ | | configuration. |\n\ | | (Default is 12k bit) |\n\ +---------------------+------------------------------------------+\n\ | shutter = | 32 bit PUF_SHUT register value to |\n\ | | configure PUF for shutter offset time |\n\ | | and shutter open time. |\n\ -------------+---------------------+------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [fsbl_config] bh_auth_enable |\n\ | [pskfile] primary.pem |\n\ | [sskfile] secondary.pem |\n\ | [bootloader,destination_cpu=a53-0,authentication=rsa]fsbl.elf|\n\ | } |\n\ |----------------------------------------------------------------|\n\ | FSBL which should run on A53 in 64-bit mode, is authenticated |\n\ | using RSA with SHA3 hashing, in Boot Header authentication mode|\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** hivec ******************************************************************************/ #define H_BIF_HIVEC_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | hivec |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the location of Exception Vector Table as hivec. |\n\ | Default is taken as lovec. |\n\ | This is applicable with a53(32 bit) and r5 cores only. |\n\ | hivec: exception vector table at 0xFFFF0000. |\n\ | lovec: exception vector table at 0x00000000. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [hivec] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { hivec, file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53_0] fsbl.elf |\n\ | [destination_cpu=r5-0,hivec] app1.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=r5-0, hivec, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** init ******************************************************************************/ #define H_BIF_ID_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | id |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the following IDs based on the place its defined: |\n\ | * pdi id - within outermost/pdi paranthesis |\n\ | * image id - within image paranthesis |\n\ | * partition id - within partition paranthesis |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | id = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 // PDI ID |\n\ | image |\n\ | { |\n\ | name = pmc_ss, |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | type = bootloader, |\n\ | id = 0x1, // Partition ID |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = psm_ss, |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | core = psm, |\n\ | id = 0x3, // Partition ID |\n\ | file = psm_fw.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_ss, |\n\ | id = 0x1c000002 // Image ID |\n\ | { |\n\ | type = cdo, |\n\ | id = 0x4, // Partition ID |\n\ | file = apu_cdo.bin |\n\ | } |\n\ | { |\n\ | core = a72-0, |\n\ | id = 0x5, // Partition ID |\n\ | file = a72_app.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** image ******************************************************************************/ #define H_BIF_IMAGE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | image |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define a subsytem/image |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | image { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = PMC_SS, id = 0x1c000000 |\n\ | { id = 0x1, type = bootloader, file = plm.elf } |\n\ | { id = 0x9, type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = PL_SS, id = 0x1c000004 |\n\ | { id = 0x3, type = cdo, file = system.rcdo } |\n\ | { id = 0x4, file = bitstream.rnpi } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------|\n" /****************************************************************************** init ******************************************************************************/ #define H_BIF_INIT_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | init |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Register initialization block at the end of the bootloader, |\n\ | built by parsing the .int file specification. Maximum of 256 |\n\ | address-value init pairs are allowed. The int files have |\n\ | a specific format. |\n\ |----------------------------------------------------------------|\n\ | Sample .int file - test.int |\n\ | .set. 0xF8000120 = 0x1F000200; |\n\ | .set. 0xF8000720 = 0x00000202; |\n\ | .set. 0xF800014C = 0x00000521; |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [init] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | init = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [init] test.int |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | init = reginit.int |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** load ******************************************************************************/ #define H_BIF_LOAD_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | load |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the load address for the partition in memory. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [load = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { load = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | u-boot.elf |\n\ | [load=0x3000000, offset=0x500000] uImage.bin |\n\ | [load=0x2A00000, offset=0xa00000] devicetree.dtb |\n\ | [load=0x2000000, offset=0xc00000] uramdisk.image.gz |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, load=0xf2000000, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=hello.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** metahdr ******************************************************************************/ #define H_BIF_METAHDR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | metaheader |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define encryption, authentication |\n\ | attributes for meta headers like keys, key sources etc. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | metaheader { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | metaheader |\n\ | { |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = headerkey.nky, |\n\ | authentication = rsa |\n\ | } |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, |\n\ | keysrc = bbram_red_key, |\n\ | aeskeyfile = key1.nky, |\n\ | blocks = 8192(*), |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------|\n" /****************************************************************************** name ******************************************************************************/ #define H_BIF_NAME_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | name |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the name of the image/subsystem |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | name = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 // PDI ID |\n\ | image |\n\ | { |\n\ | name = pmc_ss, // Image name |\n\ | id = 0x1c000001 // Image ID |\n\ | { |\n\ | type = bootloader, |\n\ | id = 0x1, // Partition ID |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** owner ******************************************************************************/ #define H_BIF_POWNER_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTES | partition_owner, owner |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Owner of the partition which is responsible to load the |\n\ | partition. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [partition_owner = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { owner = , file= } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | ZYNQ/ZYNQMP: |\n\ | *fsbl : FSBL loads this partition |\n\ | uboot : UBOOT loads this partition |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | *plm : PLM loads this partition |\n\ | non-plm : PLM ignores this partition, someone else loads |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | uboot.elf |\n\ | [partition_owner=uboot] hello.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | id = 0x00010000, |\n\ | type = bootloader, |\n\ | file = /path/to/plm.elf |\n\ | } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_subsys, id = 0x1c000003 |\n\ | { |\n\ | id = 0x00000000, |\n\ | core = a72-0, |\n\ | owner = non-plm, |\n\ | file = /path/to/image.ub |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** offset ******************************************************************************/ #define H_BIF_OFFSET_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | offset |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the absolute offset of the partition in the boot image. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [offset = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { offset = , file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | ZYNQ/ZYNQMP: |\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | u-boot.elf |\n\ | [load=0x3000000, offset=0x500000] uImage.bin |\n\ | [load=0x2A00000, offset=0xa00000] devicetree.dtb |\n\ | [load=0x2000000, offset=0xc00000] uramdisk.image.gz |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { offset=0x8000, file=data.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** parent_id ******************************************************************************/ #define H_BIF_PARENTID_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | parent_id |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the ID for the parent PDI. This is used to identify |\n\ | the relationship between a partial PDI and its corresponding |\n\ | Boot PDI |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | parent_id = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | parent_id = 0x2 |\n\ | image |\n\ | { |\n\ | name = psm_ss, id = 0x1c000001 |\n\ | { core = psm, file = psm_fw.elf } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = apu_ss, id = 0x1c000002 |\n\ | { type = cdo, file = ps_cdo.bin } |\n\ | { core = a72-0, file = a72_app.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** partition ******************************************************************************/ #define H_BIF_PARTITION_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | partition |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to define a partition |\n\ | It is an optional attribute to make the BIF more readable |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | partition { } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = WDI_FLAT, id = 0x1c000000 |\n\ | partition |\n\ | { |\n\ | id = 0x1 |\n\ | type = bootloader |\n\ | file = plm.elf |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x9 |\n\ | type = pmcdata, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x3 |\n\ | type = cdo |\n\ | file = system.rcdo |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x4 |\n\ | file = system.rnpi |\n\ | } |\n\ | } |\n\ | } |\n\ | |\n\ | The same BIF can be written in shorter format as: |\n\ | test: |\n\ | { |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = WDI_FLAT, id = 0x1c000000 |\n\ | { id = 0x1, type = bootloader, file = plm.elf } |\n\ | { id = 0x9, type = pmcdata, file = pmc_cdo.bin } |\n\ | { id = 0x3, type = cdo, file = system.rcdo } |\n\ | { id = 0x4, file = system.rnpi } |\n\ | } |\n\ | } |\n\ | |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** pid ******************************************************************************/ #define H_BIF_PID_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | pid |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This is used to specify an id to which the partition is |\n\ | associated with. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [pid = ] |\n\ | is an integer value, representing the partition number. |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [encryption=aes,aeskeyfile=test.nky,pid=1] hello.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | While creating an image bootgen by default assigns an id to |\n\ | every partition, which is in line with the order of partitions |\n\ | given in the bif. |\n\ | To assign a different id to any partition, pid can be used. |\n\ | During encryption, the IV is incremented by this value to avoid|\n\ | security vulneribilities. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** pmufw_image ******************************************************************************/ #define H_BIF_PFW_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | pmufw_image |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | PMU Firmware image to be loaded by BootROM, before loading the |\n\ | FSBL. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [pmufw_image] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [pmufw_image] pfw.elf |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [destination_cpu=r5-1] app.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Note: |\n\ |----------------------------------------------------------------|\n\ | PMU loaded by BootROM: [pmufw_image] pmu.elf |\n\ | In this flow, BootROM loads PMU first and then the FSBL |\n\ | So PMU does the power management tasks, before the FSBL comes |\n\ | up. |\n\ |----------------------------------------------------------------|\n\ | PMU loaded by FSBL: [destination_cpu=pmu] pmu.elf |\n\ | In this flow, BootROM loads FSBL first, and then FSBL loads the|\n\ | PMU fw. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** reserve ******************************************************************************/ #define H_BIF_RES_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | reserve |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Reserves the memory and padded after the partition. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [reserve = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { reserve = , file= } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | [reserve=0x1000] test.bin |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { reserve=0x1000, file=data.bin } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** slr ******************************************************************************/ #define H_BIF_SLR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | slr |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This attribute is used to specify the SLR identity to partition|\n\ | It is valid for SSIT devices |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { slr = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | master_pdi: |\n\ | { |\n\ | id=2 |\n\ | /* PMC Subsystem for Master SLR */ |\n\ | image |\n\ | { |\n\ | name=pmc_subsys, id=0x1c000001 |\n\ | { id=0x1, type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, load=0xf2000000, file=pmc_cdo.cdo } |\n\ | } |\n\ | /* Slave SLR Boot PDIs */ |\n\ | image |\n\ | { |\n\ | name=slr_boot_subsys, id=0x1c000000, type=slr-boot |\n\ | { file=slr_boot.cdo } |\n\ | } |\n\ | /* Other images/partitions of Master SLR */ |\n\ | image |\n\ | { |\n\ | name=psm_subsys, id=0x1c000002 |\n\ | { id=0x2, core=psm, file=psm.elf } |\n\ | } |\n\ | /* Slave SLR Config PDIs */ |\n\ | image |\n\ | { |\n\ | name=slr_config_subsys, id=0x1c000000, type=slr-config |\n\ | /* Slave SLR config PDIs */ |\n\ | { slr=1, file=slr1_config.pdi } |\n\ | { slr=2, file=slr2_config.pdi } |\n\ | { slr=3, file=slr3_config.pdi } |\n\ | /* Master SLR PL config partition */ |\n\ | { slr=0, file=/path/to/system.cdo } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** split ******************************************************************************/ #define H_BIF_SPLIT_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | split |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Splits the image into parts based on mode. |\n\ | Slaveboot mode splits as below. |\n\ | 1. Boot Header + Bootloader |\n\ | 2. Image and Partition Headers |\n\ | 3. Rest of the partitions. |\n\ | Normal mode splits as below. |\n\ | 1. Bootheader + Image Headers + |\n\ | Partition Headers + Bootloader |\n\ | 2. Partiton1 |\n\ | 3. Partition2 ... |\n\ | Slaveboot is supported only for ZynqMP, normal is suppoted |\n\ | for both Zynq and ZynqMP. |\n\ | Along with the split mode, output format can also be |\n\ | specified as bin or mcs. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [split] mode = |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | slaveboot |\n\ | normal |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [split] mode=slaveboot, fmt=bin |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [destination_device=pl] system.bit |\n\ | [destination_cpu=r5-1] app.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Note: The option split mode normal is same as the command line |\n\ | option split. This command line option will be deprecated soon.|\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** startup ******************************************************************************/ #define H_BIF_STARTUP_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | startup |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the entry address for the partition, after it is loaded. |\n\ | This is ignored for partitions that do not execute. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [startup = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { startup = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader] fsbl.elf |\n\ | [startup=0x1000000] app.bin |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, load=0x1000,startup=0x1000, file=hello.bin }|\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** trustzone ******************************************************************************/ #define H_BIF_TZ_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | trustzone |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Configures the core to be Trustzone secure or nonsecure |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [trustzone = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { trustzone = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | secure |\n\ | nonsecure |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [bootloader, destination_cpu=a53-0] fsbl.elf |\n\ | [exception_level=el-3, trustzone = secure] bl31.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = image1, id = 0x1c000001 |\n\ | { type=bootloader, file=plm.elf } |\n\ | { type=pmcdata, file=pmc_cdo.bin } |\n\ | { type=cdo, file=fpd_data.cdo } |\n\ | { core=psm, file=psm.elf } |\n\ | { core=a72-0, file=uboot.elf } |\n\ | { core=a72-0, exception_level=el-3, trustzone=secure, |\n\ | file=bl31.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** type ******************************************************************************/ #define H_BIF_TYPE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | type |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specifies the type of partition |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { type = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | bootloader |\n\ | pmcdata |\n\ | cdo |\n\ | cfi |\n\ | cfi-gsc |\n\ | bootimage |\n\ | slr-boot |\n\ | slr-config |\n\ | slr-slave-boot |\n\ | slr-slave-config |\n\ | elf |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, |\n\ | load = 0xf2000000, |\n\ | file = pmc_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** udf_bh ******************************************************************************/ #define H_BIF_UDFBH_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | udf_bh |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports a file of data to be copied to the User Defined Field |\n\ | of the Boot Header. The input user defined data is provided |\n\ | through a text file in the form of a hex string. |\n\ | Total no. of bytes in UDF: |\n\ | Zynq : 76 bytes |\n\ | ZynqMP : 40 bytes |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [udf_bh] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [udf_bh] test.txt |\n\ | [bootloader] fsbl.elf |\n\ | hello.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Sample input file for udf_bh - test.txt |\n\ | 123456789abcdef85072696e636530300301440408706d616c6c6164000508 |\n\ | 266431530102030405060708090a0b0c0d0e0f101112131415161718191a1b |\n\ | 1c1d1 |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** xip_mode ******************************************************************************/ #define H_BIF_XIP_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | xip_mode |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Indicates 'eXecute In Place' for FSBL to be executed directly |\n\ | from QSPI flash. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [xip_mode] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [bootloader, xip_mode] fsbl.elf |\n\ | application.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Note: This attribute is only applicable for FSBL partition. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** aeskeyfile ******************************************************************************/ #define H_BIF_AES_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | aeskeyfile |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | The path to the AES keyfile. The keyfile contains AES key used |\n\ | to encrypt the partitions. The contents of the key file needs |\n\ | to be written to key source |\n\ | If the key file is not present in the path specified, a new key|\n\ | is generated by bootgen, which is used for encryption. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/FPGA: |\n\ | [aeskeyfile] |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ | [aeskeyfile = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { aeskeyfile = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [aeskeyfile] test.nky |\n\ | [bootloader, encryption=aes] fsbl.elf |\n\ | [encryption=aes] hello.elf |\n\ | } |\n\ | The partitions fsbl.elf & hello.elf are encrypted using |\n\ | test.nky key file. |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [bootloader,encryption=aes,aeskeyfile=test.nky] fsbl.elf |\n\ | [encryption=aes,aeskeyfile=test1.nky] hello.elf |\n\ | [encryption=aes,aeskeyfile=test2.nky] app.elf |\n\ | } |\n\ | * Each partition being encrypted needs its own aeskeyfile. |\n\ | * Key0, IV0 and Key Opt should be the same accross all nky |\n\ | files that will be used. |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, encryption = aes, |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | type=cdo, encryption = aes, |\n\ | keysrc = efuse_red_key, aeskeyfile = key3.nky, |\n\ | file=fpd_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /****************************************************************************** bh_keyfile ******************************************************************************/ #define H_BIF_BHKEY_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bh_keyfile |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | 256-bit obfuscated key to be stored in boot header |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [bh_keyfile] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | bh_keyfile = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bh_gry_key |\n\ | [bh_keyfile] obfuscated_key.txt |\n\ | [bh_key_iv] obfuscated_iv.txt |\n\ | [bootloader, encryption=aes, aeskeyfile = encr.nky, |\n\ | destination_cpu=a53-0]fsbl.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | bh_keyfile = bh_key1.txt |\n\ | bh_kek_iv = blk_iv.txt |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, encryption = aes, |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | type=cdo, encryption = aes, |\n\ | keysrc = bh_blk_key, aeskeyfile = key3.nky, |\n\ | file=fpd_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bh_key_iv ******************************************************************************/ #define H_BIF_BHIV_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bh_key_iv |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Initialization vector used when decrypting the obfuscated key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bh_key_iv] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bh_gry_key |\n\ | [bh_keyfile] obfuscated_key.txt |\n\ | [bh_key_iv] obfuscated_iv.txt |\n\ | [bootloader, encryption=aes, aeskeyfile=encr.nky, |\n\ | destination_cpu=a53-0]fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** userkeys ******************************************************************************/ #define H_BIF_USERKEYS_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | userkeys |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | The path to the user keyfile. The keyfile contains user keys |\n\ | used to encrypt the partitions. |\n\ | The size of user key can be 128 or 256 bits. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | userkeys = |\n\ -------------+----------------------------------------------------------------+\n\ FILE FORMAT | user_key0 |\n\ | user_key1 |\n\ | user_key2 |\n\ | user_key3 |\n\ | user_key4 |\n\ | user_key5 |\n\ | user_key6 |\n\ | user_key7 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | new_bif: |\n\ | { |\n\ | userkeys = userkeyfile.txt |\n\ | id_code = 0x04ca8093 |\n\ | extended_id_code = 0x01 |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys |\n\ | id = 0x1c000001 |\n\ | partition |\n\ | { |\n\ | id = 0x01 |\n\ | type = bootloader |\n\ | file = plm.elf |\n\ | } |\n\ | partition |\n\ | { |\n\ | id = 0x09 |\n\ | type = pmcdata, load = 0xf2000000 |\n\ | file = topology_xcvc1902.v2.cdo |\n\ | file = bd_70da_ps_pmc_0_pmc_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /****************************************************************************** encryption ******************************************************************************/ #define H_BIF_ENCR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | encryption |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be encrypted. |\n\ | Encryption Algorithms |\n\ | Zynq : AES-CBC |\n\ | ZynqMP & Versal : AES-GCM |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP/FPGA: |\n\ | [encryption = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | { encryption = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : Partition not encrypted |\n\ | aes : Partition encrypted using AES algorithm |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [aeskeyfile] test.nky |\n\ | [bootloader, encryption=aes] fsbl.elf |\n\ | [encryption=aes] hello.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, encryption = aes, |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | type=cdo, encryption = aes, |\n\ | keysrc = efuse_red_key, aeskeyfile = key3.nky, |\n\ | file=fpd_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+" /****************************************************************************** familykey ******************************************************************************/ #define H_BIF_METAL_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | familykey |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | fpga, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Specify Family Key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [familykey] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [aeskeyfile] encr.nky |\n\ | [bh_key_iv] bh_iv.txt |\n\ | [familykey] familykey.txt |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** keysrc_encryption ******************************************************************************/ #define H_BIF_KEYSRCENCR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | keysrc_encryption |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Key source for encryption |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [keysrc_encrption] |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | efuse_red_key : Red Key stored in efuse |\n\ | bbram_red_key : Red Key stored in bbram |\n\ | efuse_gry_key : Grey (Obfuscated) Key stored in efuse |\n\ | bh_gry_key : Grey (Obfuscated) Key stored in boot header |\n\ | bh_blk_key : Black Key stored in boot header |\n\ | efuse_blk_key : Black Key stored in efuse |\n\ | kup_key : User Key |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [keysrc_encryption] bbram_red_key |\n\ | [bootloader, encryption=aes, aeskeyfile=encr.nky |\n\ | destination_cpu=a53-0]fsbl.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | FSBL is encrypted using the key encr.nky, which is stored in |\n\ | bbram in the device for decryption purpose. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** keysrc ******************************************************************************/ #define H_BIF_KEYSRC_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | keysrc |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Key source for encryption |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { keysrc = , file = } |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | Key sources applicable for bootloader, metaheader & partitions:|\n\ | efuse_red_key |\n\ | efuse_blk_key |\n\ | bbram_red_key |\n\ | bbram_blk_key |\n\ | bh_blk_key |\n\ | Additional key sources applicable only for partitions: |\n\ | user_key0 |\n\ | user_key1 |\n\ | user_key2 |\n\ | user_key3 |\n\ | user_key4 |\n\ | user_key5 |\n\ | user_key6 |\n\ | user_key7 |\n\ | efuse_user_key0 |\n\ | efuse_user_blk_key0 |\n\ | efuse_user_key1 |\n\ | efuse_user_blk_key1 |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, encryption = aes, |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | type=cdo, encryption = aes, |\n\ | keysrc = efuse_red_key, aeskeyfile = key3.nky, |\n\ | file=fpd_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** dpacm_enable ******************************************************************************/ #define H_DPACM_ENABLE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | dpacm_enable |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Sets the DPA Counter Measure bit in the Partition Header Table |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | { dpacm_enable } |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------|\n\ | dpacm_enable: |\n\ | { |\n\ | image |\n\ | { |\n\ | { |\n\ | type = bootloader, |\n\ | encryption = aes, blocks = 4096(*), |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | dpacm_enable, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, |\n\ | file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | core = psm, |\n\ | encryption = aes, blocks = 4096(*), |\n\ | keysrc = bbram_red_key, aeskeyfile = key3.nky, |\n\ | dpacm_enable, |\n\ | file = psm.elf |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** puf_file ******************************************************************************/ #define H_BIF_PUFDATA_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | puf_file |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp, versal |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | PUF helper data file. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQMP: |\n\ | [puf_file] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | puf_file = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [fsbl_config] pufhd_bh |\n\ | [puf_file] pufhelperdata.txt |\n\ | [bh_keyfile] black_key.txt |\n\ | [bh_key_iv] bhkeyiv.txt |\n\ | [bootloader,destination_cpu=a53-0,encryption=aes]fsbl.elf |\n\ | } |\n\ +----------------------------------------------------------------|\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | boot_config {puf4kmode} |\n\ | puf_file = pufhd_file_4K.txt |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { |\n\ | type = bootloader, encryption = aes, |\n\ | keysrc = bbram_red_key, aeskeyfile = key1.nky, |\n\ | file = plm.elf |\n\ | } |\n\ | { |\n\ | type = pmcdata, load = 0xf2000000, |\n\ | aeskeyfile = key2.nky, file = pmc_cdo.bin |\n\ | } |\n\ | { |\n\ | type=cdo, encryption = aes, |\n\ | keysrc = efuse_red_key, aeskeyfile = key3.nky, |\n\ | file=fpd_data.cdo |\n\ | } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** tcmboot ******************************************************************************/ #define H_BIF_TCMBOOT_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | tcmboot |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This option is used to enable R52 to boot from TCM |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | all: |\n\ | { |\n\ | id_code = 0x4ca8093 |\n\ | extended_id_code = 0x1 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | {type = bootloader, file = plm_secure.elf} |\n\ | } |\n\ | image |\n\ | { |\n\ | name = rpu, id = 0x1c000000 |\n\ | {tcmboot, core = r52-0, cluster = 1, file = rpu.elf} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** optionaldata ******************************************************************************/ #define H_BIF_OPTIONALDATA_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | optionaldata |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Optional Data is a binary data placed in the PDI after |\n\ | Image Header Table (IHT) |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versal |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | new_bif: |\n\ | { |\n\ | id_code = 0x04ca8093 |\n\ | extended_id_code = 0x01 |\n\ | id = 0x2 |\n\ | |\n\ | optionaldata {data2.bin, id=33} |\n\ | optionaldata {data3.bin, id=34} |\n\ | |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | partition {id = 0x01, type = bootloader, file = plm.elf} |\n\ | partition {id = 0x09, type = pmcdata, load = 0xf2000000, |\n\ | file = pmc_data.cdo} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** authentication ******************************************************************************/ #define H_BIF_AUTH_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | authentication |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | This specifies the partition needs to be authenticated. |\n\ | Authentication Algorithms: |\n\ | Zynq & FPGA : RSA-2048 |\n\ | ZynqMP : RSA-4096 |\n\ | Versal : RSA-4096 & ECDSA |\n\ | Note : p384 and p521 curves are supported for ECDSA |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP/FPGA: |\n\ | [authenication = ] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | {authenication=, file=} |\n\ -------------+----------------------------------------------------------------+\n\ OPTIONS | *none : Partition not authenticated |\n\ | rsa : Partition authenticated using RSA |\n\ | ecdsa-p384 : Partition authenticated using ECDSA(P384 Curve) |\n\ | ecdsa-p521 : Partition authenticated using ECDSA(P521 Curve) |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [ppkfile] ppk.txt |\n\ | [spkfile] spk.txt |\n\ | [bootloader, authentication=rsa] fsbl.elf |\n\ | [authentication=rsa] hello.elf |\n\ | } |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | boot_config {bh_auth_enable} |\n\ | pskfile = primary0.pem |\n\ | sskfile = secondary0.pem |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | {type=bootloader, authentication=rsa, file=plm.elf} |\n\ | {type=pmcdata, load=0xf2000000, file=pmc_cdo.bin} |\n\ | {type=cdo, authentication=rsa, file=fpd_cdo.bin} |\n\ | {core=psm, authentication=rsa, file=psm.elf} |\n\ | {core=a72-0, authentication=rsa, file = apu.elf} |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** auth_params ******************************************************************************/ #define H_BIF_AUTHPARAM_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | auth_params |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Extra options for authentication |\n\ | ppk_select - 2 PPKs supported. |\n\ | spk_select - To differentiate spk and user efuses. |\n\ | Default will be spk-efuse. |\n\ | spk_id - ID to differentiate SPKs. |\n\ | header_auth - To authenticate headers when no partition is |\n\ | authenticated. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [auth_params] header_auth; ppk_select=<0/1>; spk_id=; |\n\ | spk_select= |\n\ |----------------------------------------------------------------|\n\ | Notes: |\n\ | - ppk_select is unique for the image. |\n\ | - Each partition can have its own spk_select and spk_id. |\n\ | spk-efuse id is unique accross the image, but user-efuse id |\n\ | can vary between partitions. |\n\ | - spk_select/spk_id outside the partition scope will be used |\n\ | for headers and any other partition that does not have |\n\ | these specifications as partition attributes. |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF 1 - test.bif |\n\ | all: |\n\ | { |\n\ | [auth_params] ppk_select=0;spk_select=user-efuse;spk_id=0x22 |\n\ | [pskfile] primary.pem |\n\ | [sskfile] secondary.pem |\n\ | [ |\n\ | bootloader, |\n\ | authentication = rsa |\n\ | ] fsbl.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Sample BIF 2 - test.bif |\n\ | all: |\n\ | { |\n\ | [auth_params] ppk_select=1; spk_select= user-efuse; |\n\ | spk_id=0x22; header_auth |\n\ | [pskfile] primary.pem |\n\ | [sskfile] secondary.pem |\n\ | [destination_cpu=a53-0] test.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [auth_params] ppk_select=1;spk_select=user-efuse;spk_id=0x22|\n\ | [pskfile] primary.pem |\n\ | [sskfile] secondary0.pem |\n\ | |\n\ | /* FSBL - Partition-0) */ |\n\ | [ |\n\ | bootloader, |\n\ | destination_cpu = a53-0, |\n\ | authentication = rsa, |\n\ | spk_id = 0x12345678, |\n\ | spk_select = spk-efuse, |\n\ | sskfile = secondary1.pem |\n\ | ] fsbla53.elf |\n\ | |\n\ | /* Partition-1 */ |\n\ | [ |\n\ | destination_cpu = a53-1, |\n\ | authentication = rsa, |\n\ | spk_id = 0x24, |\n\ | spk_select = user-efuse, |\n\ | sskfile = secondary2.pem |\n\ | ] hello.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** bhsignature ******************************************************************************/ #define H_BIF_BHSIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | bhsignature |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports Boot Header signature into authentication certificate. |\n\ | This can be used incase the user does't want to share the |\n\ | secret key PSK. |\n\ | The user can create a signature and provide it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [bhsignature] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [ppkfile] ppk.txt |\n\ | [spkfile] spk.txt |\n\ | [spksignature] spk.txt.sha384.sig |\n\ | [bhsignature] bootheader.sha384.sig |\n\ | [bootloader, authentication=rsa] fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** headersignature ******************************************************************************/ #define H_BIF_HDRSIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | headersignature |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports Header signature into authentication certificate. This |\n\ | can be used incase the user does't want to share the secret key|\n\ | The user can create a signature and provide it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [headersignature] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [ppkfile] ppk.txt |\n\ | [spkfile] spk.txt |\n\ | [headersignature] headers.sha256.sig |\n\ | [spksignature] spk.txt.sha256.sig |\n\ | [bootloader, authentication=rsa] fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** ppkfile, pskfile, spkfile, sskfile ******************************************************************************/ #define H_BIF_PPK_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | ppkfile, pskfile, spkfile, sskfile |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | These keys are used to authenticate partitions in the bootimage|\n\ | A pair of keys, Primary & Secondary are used in the |\n\ | authentication process. |\n\ | The primary keys authenticate the secondary keys and the |\n\ | secondary keys authenticate the partitions. |\n\ | PPK - Primary Public Key |\n\ | PSK - Primary Secret Key |\n\ | SPK - Secondary Public Key |\n\ | SSK - Secondary Secret Key |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | ZYNQ/ZYNQMP: |\n\ | [ppkfile] |\n\ | [pskfile] |\n\ | [spkfile] |\n\ | [sskfile] |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ | ppkfile = |\n\ | pskfile = |\n\ | spkfile = |\n\ | sskfile = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF 1 - test.bif |\n\ +----------------------------------------------------------------+\n\ | ZYNQ/ZYNQMP: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | [pskfile] primarykey.pem |\n\ | [sskfile] secondarykey.pem |\n\ | [bootloader, authentication=rsa] fsbl.elf |\n\ | [authentication=rsa] hello.elf |\n\ | } |\n\ |----------------------------------------------------------------|\n\ | Sample BIF 2 - test.bif |\n\ | all: |\n\ | { |\n\ | [pskfile] primary.pem |\n\ | [sskfile] secondary0.pem |\n\ | |\n\ | /* FSBL (Partition-0) */ |\n\ | [ |\n\ | bootloader, destination_cpu = a53-0, authentication = rsa, |\n\ | sskfile = secondary1.pem |\n\ | ]fsbla53.elf |\n\ | |\n\ | /* Partition-1 */ |\n\ | [ |\n\ | destination_cpu = a53-0, |\n\ | authentication = rsa |\n\ | ] hello.elf |\n\ | } |\n\ | For ZynqMP: |\n\ | - PPK/PSK cannot be specific to partition. |\n\ | - Each partition can have its own SPK/SSK.(Refer sample BIF 2)|\n\ | The SPKs can be differentiated using the spk_id. |\n\ | - SPK/SSK outside the partition scope is mandatory for |\n\ | authentication. These keys will be used to authenticate |\n\ | headers and any other partition that does not have a |\n\ | specific SPK/SSK. |\n\ +----------------------------------------------------------------+\n\ | VERSAL: |\n\ +----------------------------------------------------------------|\n\ | all: |\n\ | { |\n\ | boot_config {bh_auth_enable} |\n\ | image |\n\ | { |\n\ | name = pmc_ss, id = 0x1c000001 |\n\ | { type=bootloader, authentication=rsa, file=plm.elf, |\n\ | pskfile=primary0.pem, sskfile=secondary0.pem } |\n\ | { type = pmcdata, load = 0xf2000000, file=pmc_cdo.bin } |\n\ | { type=cdo, authentication=rsa, file=fpd_cdo.bin, |\n\ | pskfile = primary1.pem, sskfile = secondary1.pem } |\n\ | } |\n\ | } |\n\ | For Versal: |\n\ | PPK/PSK can be specific to partition. |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** presign ******************************************************************************/ #define H_BIF_PRESIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | presign |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports partition signature into partition authenticate |\n\ | certificate. |\n\ | This can be used incase the user does't want to share the |\n\ | secret key(SSK). The user can create a signature and provide |\n\ | it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [presign = ] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [ppkfile] ppk.txt |\n\ | [spkfile] spk.txt |\n\ | [headersignature] headers.sha256.sig |\n\ | [spksignature] spk.txt.sha256.sig |\n\ | [bootloader, authentication=rsa, presign=fsbl.sig] fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** spksignature ******************************************************************************/ #define H_BIF_SPKSIGN_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | spksignature |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports SPK signature into authentication certificate. This can|\n\ | be used incase the user does't want to share the secret key PSK|\n\ | The user can create a signature and provide it to Bootgen. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | [spksignature] |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [ppkfile] ppk.txt |\n\ | [spkfile] spk.txt |\n\ | [spksignature] spk.txt.sha256.sig |\n\ | [bootloader, authentication=rsa] fsbl.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" /****************************************************************************** udf_data ******************************************************************************/ #define H_BIF_UDF_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | udf_data |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | zynq, zynqmp |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | Imports a file containing up to 56 bytes of data into User |\n\ | Defined Field of Authentication Certificate. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | udf_data = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | all: |\n\ | { |\n\ | [pskfile]primary0.pem |\n\ | [sskfile]secondary0.pem |\n\ | [bootloader,destination_cpu=a53-0,authentication=rsa, |\n\ | udf_data=udf.txt]fsbl.elf |\n\ | [destination_cpu=a53-0, authentication=rsa] hello.elf |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HVN_BIF_PCR_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | pcr |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versalnet |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the PCR register number where PLM can store the |\n\ | calculated hash of a given image |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | pcr = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = subsys_1, id = 0x1c000000, pcr = 3 |\n\ | { type = cdo, file = apu_cdo.cdo } |\n\ | { core = a72-0, file = apu.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HVN_BIF_PCR_MINDEX_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | pcr_mindex |\n\ -------------+----------------------------------------------------------------+\n\ SUPPORTED | versalnet |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the PCR measurement index where PLM can store the |\n\ | extended hash of a given image. |\n\ | This must be specified along with pcr. |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | pcr_mindex = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | test: |\n\ | { |\n\ | id = 2 |\n\ | image |\n\ | { |\n\ | name = pmc_subsys, id = 0x1c000001 |\n\ | { type = bootloader, file = plm.elf } |\n\ | { type = pmcdata, file = pmc_cdo.bin } |\n\ | } |\n\ | image |\n\ | { |\n\ | name = subsys_1, id = 0x1c000000 |\n\ | pcr = 3, pcr_mindex = 10 |\n\ | { type = cdo, file = apu_cdo.cdo } |\n\ | { core = a72-0, file = apu.elf } |\n\ | } |\n\ | } |\n\ -------------+----------------------------------------------------------------+\n" #define HV_BIF_IMAGESTORE_H "\ -------------+----------------------------------------------------------------+\n\ ATTRIBUTE | imagestore |\n\ -------------+----------------------------------------------------------------+\n\ DESCRIPTION | To specify the ID of the PDI to add to Image Store |\n\ -------------+----------------------------------------------------------------+\n\ USAGE | imagestore = |\n\ -------------+----------------------------------------------------------------+\n\ EXPLANATION | Sample BIF - test.bif |\n\ | write_imagestore_pdi: |\n\ | { |\n\ | id_code = 0x04d14093 |\n\ | extended_id_code = 0x01 |\n\ | id = 0xb |\n\ | image |\n\ | { |\n\ | name = pl_noc, id = 0x18700000 |\n\ | partition |\n\ | { |\n\ | id = 0xb05, type = cdo, file = imagestore.rnpi |\n\ | } |\n\ | } |\n\ | } |\n\ | master: |\n\ | { |\n\ | id_code = 0x04d14093 |\n\ | extended_id_code = 0x01 |\n\ | id = 0x2 |\n\ | image |\n\ | { |\n\ | name = IMAGE_STORE, id = 0x18700000 |\n\ | partition |\n\ | { |\n\ | id = 0xb15, imagestore = 0x1 |\n\ | section = write_imagestore_pdi |\n\ | } |\n\ | } |\n\ | } |\n\ ------------+----------------------------------------------------------------+\n" #endif xilinx-bootgen-2024.2/imageheadertable-versal.cpp000077500000000000000000005541231475706442400220440ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable-versal.h" #include "authentication-versal.h" #include "bootimage.h" #include "bootheader-versal.h" #include "elftools.h" #include #include #include "stringutils.h" #include "fileutils.h" #include "bitutils.h" #include "bitutils-versal.h" #include "partitionheadertable-versal.h" #include "encryptutils.h" #include "cJSON.h" #include extern "C" { #include "cdo-npi.h" #include "cdo-source.h" #include "cdo-command.h" #include "cdo-binary.h" #include "cdo-load.h" #include "cdo-overlay.h" }; static uint8_t bufferIndex = 0; std::list VersalImageHeader::cdoSections; uint64_t slr_sbi_base_array[4] = { PMC_SBI_BUF_ADDR, SLR1_SBI_BUF_BASE_ADDR, SLR2_SBI_BUF_BASE_ADDR, SLR3_SBI_BUF_BASE_ADDR }; #define POWER_LPD 0x4210002 #define POWER_FPD 0x420c003 #define POWER_PLD 0x4220006 #define POWER_SPD 0x4214004 //POWER_NOC /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ CdoSsitSyncMaster* CdoCmdWriteSsitSyncMaster() { CdoSsitSyncMaster* cdoCmd = new CdoSsitSyncMaster; cdoCmd->header.reserved = 0x00; cdoCmd->header.length = 0x0; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::SSIT_SYNC_MASTER; LOG_TRACE("CDO_CMD_SSIT_SYNC_MASTER"); return cdoCmd; } /******************************************************************************/ CdoCommandNop* CdoCmdNoOperation2(size_t size) { CdoCommandNop* cdoCmd = new CdoCommandNop; uint32_t length = size - CDO_CMD_NOP_SIZE - 4; /* consider the NOP command header and length as 2 NOPs */ cdoCmd->header.reserved = 0x00; cdoCmd->header.length = 0xff; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::NOP; cdoCmd->length = (length / CDO_CMD_NOP_SIZE); LOG_TRACE(" CDO_CMD_NOP - %d", cdoCmd->length + 2); return cdoCmd; } /******************************************************************************/ VersalImageHeaderTable::VersalImageHeaderTable() : kekIvMust(false) , bootDevice(0) , creatorId(0) , parentId(0) , pdiId(0) , idCode(0) , extendedIdCode(0) , bypassIdCode(false) , prebuilt(false) , dpacm(DpaCM::DpaCMDisable) { section = new Section("MetaHeader", sizeof(VersalImageHeaderTableStructure)); iHTable = (VersalImageHeaderTableStructure*)section->Data; } /******************************************************************************/ VersalImageHeaderTable::VersalImageHeaderTable(std::ifstream& src) { prebuilt = true; section = new Section("MetaHeader", sizeof(VersalImageHeaderTableStructure)); iHTable = (VersalImageHeaderTableStructure*)section->Data; /* Import the Image Header Table from a boot image file */ src.read((char*)section->Data, section->Length); creatorId = (iHTable->imageHeaderTableAttributes >> vihtImageCreatorIdShift) & vihtImageCreatorIdMask; parentId = iHTable->parentId; pdiId = iHTable->pdiId; idCode = iHTable->idCode; extendedIdCode = iHTable->extendedIdCode; iht_optional_data_length = iHTable->optionalDataSize * 4; bypassIdCode = (iHTable->imageHeaderTableAttributes >> vihtSiliconRevisionIdCodeCheckShift) & vihtSiliconRevisionIdCodeCheckMask; bootDevice = (iHTable->imageHeaderTableAttributes >> vihtSecBootDeviceShift) & vihtSecBootDeviceMask; dpacm = ((iHTable->imageHeaderTableAttributes >> vihtDpacmEnableShift) & vihtDpacmEnableMask) == 3 ? DpaCM::DpaCMEnable : DpaCM::DpaCMDisable; pufHDLoc = ((iHTable->imageHeaderTableAttributes >> vihtPufHDLocationShift) & vihtPufHDLocationMask) == 3 ? PufHdLoc::PUFinBH : PufHdLoc::PUFinEFuse; idCodeCheck = (iHTable->imageHeaderTableAttributes >> vihtIdCodeCheckShift) & vihtIdCodeCheckMask; kekIvMust = false; } /******************************************************************************/ VersalImageHeaderTable::~VersalImageHeaderTable() { if (section != NULL) { delete section; } } /******************************************************************************/ void VersalImageHeaderTable::Build(BootImage& bi, Binary& cache) { bool isApuOrRpuSubsystem = false; if (section != NULL) { cache.Sections.push_back(section); } if (!prebuilt) { pdiId = bi.bifOptions->GetPdiId(); parentId = bi.bifOptions->GetParentId(); idCode = bi.bifOptions->GetIdCode(); extendedIdCode = bi.bifOptions->GetExtendedIdCode(); bypassIdCode = bi.bifOptions->GetBypassIdcodeFlag(); bootDevice = bi.bifOptions->GetBootDevice(); SetImageHeaderTableVersion(VERSION_v4_00_VERSAL); SetHeaderTablesSize(); SetTotalMetaHdrLength(0); SetIdentificationString(bi.IsBootloaderFound()); SetIds(bi.imageList.size() != 0); metaHdrKeySrc = bi.options.bifOptions->metaHdrAttributes.encrKeySource; SetMetaHdrSecureHdrIv(metaHdrSecHdrIv); dpacm = bi.bifOptions->metaHdrAttributes.dpaCM; pufHDLoc = bi.bifOptions->metaHdrAttributes.pufHdLoc; } else { if (bi.bifOptions->GetPdiId() != 0) { pdiId = bi.bifOptions->GetPdiId(); } if (bi.bifOptions->GetParentId() != 0) { parentId = bi.bifOptions->GetParentId(); } if (bi.bifOptions->GetIdCode() != 0) { idCode = bi.bifOptions->GetIdCode(); } if (bi.bifOptions->GetExtendedIdCode() != 0) { extendedIdCode = bi.bifOptions->GetExtendedIdCode(); } if (bi.bifOptions->GetBypassIdcodeFlag() != false) { bypassIdCode = bi.bifOptions->GetBypassIdcodeFlag(); } if (bi.bifOptions->GetBootDevice() != 0) { bootDevice = bi.bifOptions->GetBootDevice(); } SetIdentificationString(bi.IsBootloaderFound()); SetIds(bi.imageList.size() != 0); if (bi.bifOptions->metaHdrAttributes.encrKeySource != KeySource::None) { metaHdrKeySrc = bi.options.bifOptions->metaHdrAttributes.encrKeySource; } if (bi.bifOptions->metaHdrAttributes.dpaCM != DpaCM::DpaCMDisable) { dpacm = bi.bifOptions->metaHdrAttributes.dpaCM; } if (bi.bifOptions->metaHdrAttributes.pufHdLoc != PufHdLoc::PUFinEFuse) { pufHDLoc = bi.bifOptions->metaHdrAttributes.pufHdLoc; } SetOptionalData(bi.iht_optional_data, bi.iht_optional_data_length); } /* Sub system Image Header creation */ if (bi.createSubSystemPdis == true) { for (std::list::iterator subsysimage = bi.subSysImageList.begin(); subsysimage != bi.subSysImageList.end(); subsysimage++) { (*subsysimage)->Build(bi, cache); isApuOrRpuSubsystem = false; for (std::list::iterator img = (*subsysimage)->imgList.begin(); img != (*subsysimage)->imgList.end(); img++) { ValidateSecurityCombinations((*img)->GetAuthenticationType(), (*img)->GetEncryptContext()->Type(), (*img)->GetChecksumContext()->Type()); if ((*img)->GetDestCpu() == DestinationCPU::A53_0 || (*img)->GetDestCpu() == DestinationCPU::A53_1 || (*img)->GetDestCpu() == DestinationCPU::R5_0 || (*img)->GetDestCpu() == DestinationCPU::R5_1 || (*img)->GetDestCpu() == DestinationCPU::R5_lockstep) { isApuOrRpuSubsystem = true; } } if (isApuOrRpuSubsystem == false) { nonApuSubSysCnt++; } } if (nonApuSubSysCnt == 0) { idCodeCheck = 3; } else { idCodeCheck = 0; } } else { for (std::list::iterator image = bi.imageList.begin(); image != bi.imageList.end(); image++) { (*image)->Build(bi, cache); ValidateSecurityCombinations((*image)->GetAuthenticationType(), (*image)->GetEncryptContext()->Type(), (*image)->GetChecksumContext()->Type()); if ((*image)->GetDestCpu() == DestinationCPU::A53_0 || (*image)->GetDestCpu() == DestinationCPU::A53_1 || (*image)->GetDestCpu() == DestinationCPU::R5_0 || (*image)->GetDestCpu() == DestinationCPU::R5_1 || (*image)->GetDestCpu() == DestinationCPU::R5_lockstep) { idCodeCheck = 3; } imageHeaderList.push_back(*image); } } bi.options.SetPadHeaderTable(false); if (bi.options.DoPadHeaderTable()) { if (bi.imageList.size() == 0) { std::list outFileNames = bi.options.GetOutputFileNames(); if (outFileNames.size() > 0) { std::cerr << "WARNING: -padimageheader was requested, but no images were specified." << std::endl; } } else { int paddingsize = GetMaxNumOfPartitions() - bi.imageList.size(); if (paddingsize > 0) { bi.imageList.back()->section->Reserve = (1 + paddingsize) * 64; } } } if (bi.options.IsAuthOptimizationEnabled()) { /* Adding an entry for header in hashtable */ if(bi.options.bifOptions->metaHdrAttributes.authenticate == Authentication::None) { LOG_ERROR("MetaHeader must be authenticated if authentication optimization is enabled, using -enable_auth_opt"); } else { bi.numHashTableEntries++; } std::string metaHdrSsk = bi.options.bifOptions->metaHdrAttributes.ssk; if(metaHdrSsk.size() == 0) { metaHdrSsk = bi.options.bifOptions->GetSSKFileName(); } std::string metaHdrPsk = bi.options.bifOptions->metaHdrAttributes.psk; if(metaHdrPsk.size() == 0) { metaHdrPsk = bi.options.bifOptions->GetPSKFileName(); } uint32_t i = 0; for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++, i++) { if (!(*partHdr)->IsBootloader()) { (*partHdr)->partitionNum = i; (*partHdr)->section->partitionNum = i; if ((*partHdr)->imageHeader->GetAuthenticationType() != Authentication::None) { std::string partHdrSsk = (*partHdr)->imageHeader->GetAuthContext()->sskFile; std::string partHdrPsk = (*partHdr)->imageHeader->GetAuthContext()->pskFile; if(metaHdrSsk.compare(partHdrSsk)) { LOG_ERROR("MetaHeader and partition must use same SSK if authentication optimization is enabled, using -enable_auth_opt"); } if(metaHdrPsk.compare(partHdrPsk)) { LOG_ERROR("MetaHeader and partition must use same PSK if authentication optimization is enabled, using -enable_auth_opt"); } bi.numHashTableEntries++; } } } } bi.imageHeaderTable->SetUserOptionalData(bi.bifOptions->metaHdrAttributes.ihtOptionalDataInfo, bi.numHashTableEntries); bi.iht_optional_data_length = iht_optional_data_length; bi.copied_iht_optional_data_length = copied_iht_optional_data_length; bi.iht_optional_data = (uint32_t*)realloc(bi.iht_optional_data, bi.iht_optional_data_length); memcpy(bi.iht_optional_data, iht_optional_data, iht_optional_data_length); } /******************************************************************************/ void VersalImageHeaderTable::Link(BootImage &bi) { /* Realigning the data ptr is necessary because Section->Data ptr gets changed in the RSAAuthenticationContext::ResizeIfNecessary() function call */ RealignSectionDataPtr(); slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; if (bi.partitionHeaderTable->firstSection != NULL) { SetFirstPartitionHeaderOffset((uint32_t)bi.partitionHeaderTable->firstSection->WordAddress()); } if (bi.options.bifOptions->GetHeaderEncyption()) { SetFirstImageHeaderOffset(bi.encryptedHeaders->WordAddress()); SetImageCount((uint32_t)bi.imageList.size()); } else { if (bi.imageList.size() != 0) { if (bi.imageList.front()->section != NULL) { uint32_t size = (bi.imageList.size() > 0) ? (uint32_t)bi.imageList.front()->section->WordAddress() : 0; SetFirstImageHeaderOffset(size); } SetImageCount((uint32_t)bi.imageList.size()); } } if (bi.createSubSystemPdis == true) { if (bi.options.bifOptions->GetHeaderEncyption()) { SetFirstImageHeaderOffset(bi.encryptedHeaders->WordAddress()); SetImageCount((uint32_t)bi.subSysImageList.size()); } else if (bi.subSysImageList.size() != 0) { if (bi.subSysImageList.front()->section != NULL) { uint32_t size = (bi.subSysImageList.size() > 0) ? (uint32_t)bi.subSysImageList.front()->section->WordAddress() : 0; SetFirstImageHeaderOffset(size); } SetImageCount((uint32_t)bi.subSysImageList.size()); } } SetPartitionCount((uint32_t)bi.partitionHeaderList.size()); uint32_t acOffset = (bi.headerAC != 0) ? (bi.headerAC->section->WordAddress()) : 0; SetHeaderAuthCertificateOffset(acOffset); // Go through image list, to set the next image's offset parameters if (bi.createSubSystemPdis == true) { /* Sub system Image Header creation */ for (std::list::iterator subsysimage = bi.subSysImageList.begin(); subsysimage != bi.subSysImageList.end();) { std::list::iterator prevSubSysImage = subsysimage; subsysimage++; if (subsysimage == bi.subSysImageList.end()) { (*prevSubSysImage)->Link(bi, 0); } else { (*prevSubSysImage)->Link(bi, (*subsysimage)); } } } else { for (std::list::iterator currentImage = imageHeaderList.begin(); currentImage != imageHeaderList.end(); ) { std::list::iterator prevImage = currentImage; currentImage++; if (currentImage == imageHeaderList.end()) { (*prevImage)->Link(bi, (*prevImage)->GetPartitionHeaderList().front(), 0); } else { (*prevImage)->Link(bi, (*prevImage)->GetPartitionHeaderList().front(), (*currentImage)); } } } if (prebuilt) { SetTotalMetaHdrLength(bi.imageHeaderTable->metaHeaderLength); } SetBootDevice(bi.bifOptions->GetBootDevice()); SetBootDeviceAddress(bi.bifOptions->GetBootDeviceAddress()); SetMetaHdrKeySrc(bi.imageHeaderTable->metaHdrKeySrc, bi.bifOptions); SetMetaHdrGreyOrBlackIv(kekIvFile); SetImageHeaderTableAttributes(); SetReservedFields(); SetOptionalDataSize(); SetChecksum(); } /******************************************************************************/ void VersalImageHeaderTable::SetImageHeaderTableVersion(uint32_t version) { iHTable->version = version; } /******************************************************************************/ void VersalImageHeaderTable::SetHeaderTablesSize() { iHTable->headerSizes = (sizeof(VersalImageHeaderTableStructure)/4) | (sizeof(VersalImageHeaderStructure)/4 << 8) | (sizeof(VersalPartitionHeaderTableStructure)/4 << 16); } /******************************************************************************/ void VersalImageHeaderTable::SetTotalMetaHdrLength(uint32_t size) { iHTable->totalMetaHdrLength = size / sizeof(uint32_t); } /******************************************************************************/ void VersalImageHeaderTable::SetPartitionCount(uint32_t count) { iHTable->partitionTotalCount = count; } /******************************************************************************/ void VersalImageHeaderTable::SetImageCount(uint32_t count) { iHTable->imageTotalCount = count; } /******************************************************************************/ void VersalImageHeaderTable::SetFirstImageHeaderOffset(uint32_t offset) { iHTable->firstImageHeaderWordOffset = offset; if (slaveBootSplitMode && (iHTable->firstImageHeaderWordOffset != 0)) { iHTable->firstImageHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void VersalImageHeaderTable::SetFirstPartitionHeaderOffset(uint32_t offset) { iHTable->firstPartitionHeaderWordOffset = offset; if (slaveBootSplitMode && (iHTable->firstPartitionHeaderWordOffset != 0)) { iHTable->firstPartitionHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void VersalImageHeaderTable::SetBootDeviceAddress(uint32_t address) { iHTable->secondaryBootDeviceAddress = address; } /******************************************************************************/ void VersalImageHeaderTable::SetIds(bool warnIdCode) { if (idCode == 0 && warnIdCode) { LOG_WARNING("id_code is not specified in BIF, default id code is 0x04ca8093"); idCode = DEFAULT_ID_CODE_S80; } iHTable->idCode = idCode; iHTable->extendedIdCode = extendedIdCode; iHTable->parentId = parentId; iHTable->pdiId = pdiId; } /******************************************************************************/ void VersalImageHeaderTable::SetImageHeaderTableAttributes() { iHTable->imageHeaderTableAttributes = bypassIdCode; iHTable->imageHeaderTableAttributes |= ((creatorId & 0x0F) << 1); iHTable->imageHeaderTableAttributes |= ((bootDevice & vihtSecBootDeviceMask) << vihtSecBootDeviceShift); iHTable->imageHeaderTableAttributes |= ((dpacm & vihtDpacmEnableMask) << vihtDpacmEnableShift); iHTable->imageHeaderTableAttributes |= ((pufHDLoc & vihtPufHDLocationMask) << vihtPufHDLocationShift); iHTable->imageHeaderTableAttributes |= ((idCodeCheck & vihtIdCodeCheckMask) << vihtIdCodeCheckShift); } /******************************************************************************/ void VersalImageHeaderTable::SetMetaHdrSecureHdrIv(uint8_t* iv) { if (iv == NULL) { memset(iHTable->metaHdrSecureHdrIv, 0, IV_LENGTH * WORD_SIZE_IN_BYTES); } else { memcpy(iHTable->metaHdrSecureHdrIv, iv, IV_LENGTH * WORD_SIZE_IN_BYTES); } } /******************************************************************************/ void VersalImageHeaderTable::SetMetaHdrKeySrc(KeySource::Type keyType, BifOptions* bifOptions) { //Encryption key source, only key source used for PLM is valid for meta header kekIvMust = false; switch (keyType) { case KeySource::EfuseRedKey: iHTable->metaHdrKeySource = EFUSE_RED_KEY; break; case KeySource::BbramRedKey: iHTable->metaHdrKeySource = BBRAM_RED_KEY; break; case KeySource::EfuseBlkKey: iHTable->metaHdrKeySource = EFUSE_BLK_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_blk_key'"); } kekIvMust = true; break; case KeySource::BbramBlkKey: iHTable->metaHdrKeySource = BBRAM_BLK_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_blk_key'"); } kekIvMust = true; break; case KeySource::BhBlkKey: iHTable->metaHdrKeySource = BH_BLACK_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_blk_key'"); } kekIvMust = true; break; case KeySource::EfuseGryKey: iHTable->metaHdrKeySource = EFUSE_GRY_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_gry_key'"); } kekIvMust = true; break; case KeySource::BbramGryKey: iHTable->metaHdrKeySource = BBRAM_GRY_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_gry_key'"); } kekIvMust = true; break; case KeySource::BhGryKey: iHTable->metaHdrKeySource = BH_GRY_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_gry_key'"); } kekIvMust = true; break; case KeySource::None: iHTable->metaHdrKeySource = 0; break; default: LOG_ERROR("BIF attribute error !!!\n\t\tInvalid 'keysrc' mentioned for MetaHeader."); break; } } /******************************************************************************/ void VersalImageHeaderTable::SetMetaHdrGreyOrBlackIv(std::string ivFile) { uint8_t* ivData = new uint8_t[IV_LENGTH * 4]; memset(ivData, 0, IV_LENGTH * 4); if (ivFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(ivFile, ivData, IV_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Black/Grey Key IV.\n Expected length for Grey/Black IV is 12 bytes"); } } else { if (kekIvMust) { LOG_ERROR("Black/Grey IV is mandatory in case of Black/Grey key sources\n Please use 'bh_kek_iv' to specify the IV in BIF file"); } } memcpy(&iHTable->metaHdrGreyOrBlackIV, ivData, IV_LENGTH * 4); delete[] ivData; } /******************************************************************************/ void VersalImageHeaderTable::SetHeaderAuthCertificateOffset(uint32_t address) { iHTable->headerAuthCertificateWordOffset = address; } /******************************************************************************/ void VersalImageHeaderTable::SetPdiId(uint32_t id) { pdiId = id; } /******************************************************************************/ void VersalImageHeaderTable::SetParentId(uint32_t id) { parentId = id; } /******************************************************************************/ void VersalImageHeaderTable::SetIdentificationString(bool bootloaderFound) { if (bootloaderFound) { iHTable->identificationString = FPDI; } else { iHTable->identificationString = PPDI; } } /******************************************************************************/ void VersalImageHeaderTable::SetCreatorId(uint8_t id) { creatorId = id; } /******************************************************************************/ void VersalImageHeaderTable::SetReservedFields(void) { memset(&iHTable->reserved, 0x00, MAX_IHT_RESERVED_VERSAL * sizeof(uint32_t)); } /******************************************************************************/ void VersalImageHeaderTable::SetChecksum(void) { iHTable->ihtChecksum = ComputeWordChecksum(iHTable, sizeof(VersalImageHeaderTableStructure) - sizeof(iHTable->ihtChecksum) /* bytes*/); } /******************************************************************************/ void VersalImageHeaderTable::SetOptionalDataSize() { iHTable->optionalDataSize = iht_optional_data_length / 4; } /******************************************************************************/ void VersalImageHeaderTable::SetXplmModulesData(BootImage& bi, uint32_t * data, uint32_t size) { if (size != 0) { bi.xplm_modules_data_length = size; bi.xplm_modules_data = (uint32_t*)malloc(bi.xplm_modules_data_length); memcpy(bi.xplm_modules_data, data, bi.xplm_modules_data_length); } } /******************************************************************************/ void VersalImageHeaderTable::SetOptionalData(uint32_t * data, uint32_t size) { iht_optional_data_length = size; if (size != 0) { iht_optional_data = (uint32_t*)malloc(iht_optional_data_length); memcpy(iht_optional_data, data, iht_optional_data_length); } } /******************************************************************************/ void VersalImageHeaderTable::SetUserOptionalData(std::vector> optionalDataInfo, uint32_t numHashTableEntries) { /* Fetch optional data, if available then exclude padding */ if(iht_optional_data_length > 0) { uint32_t actual_opData_length = 0; while(actual_opData_length < iht_optional_data_length) { uint32_t* buffer = (uint32_t*)iht_optional_data + (actual_opData_length / 4); uint32_t opData_id = buffer[0] & 0x0000FFFF; if(opData_id == 0x0000FFFF) break; actual_opData_length += (((buffer[0] & 0xFFFF0000) >> 16) * 4); } /* Update existing length to exculde padding */ iht_optional_data_length = actual_opData_length; } for (size_t i = 0; i < optionalDataInfo.size(); i++) { if ((0x00 <= optionalDataInfo[i].second) && (optionalDataInfo[i].second <= 0x20)) { LOG_WARNING("The Data IDs form 0x0 to 0x20 for Optional Data are reserved for internal use. Please use any ID > 0x20 as User Optional Data ID"); } size_t size = 0; uint8_t* tempData = (uint8_t*)file_to_buf((char *)optionalDataInfo[i].first.c_str(), &size); if(size > 0x20000){ LOG_ERROR("Maximum allowed size for optional data is 0x20000 bytes, including optional data header of 8 bytes. Refer UG1283 for more details"); } uint32_t optional_data_padLength = (size % 64 != 0) ? 64 - (size % 64) : 0; uint8_t* data= new uint8_t[size + optional_data_padLength]; memset(data, 0, size + optional_data_padLength); memcpy(data, tempData, size); delete[] tempData; size += optional_data_padLength; if (size != 0) { uint32_t sectn_size_id = 0; /* Optional Data Header + Optional Data Actual size + Checksum */ uint16_t sectn_length = sizeof(uint32_t) + size + sizeof(uint32_t); sectn_size_id = (uint32_t)((sectn_length / 4) << 16) | (optionalDataInfo[i].second); iht_optional_data = (uint32_t*)realloc(iht_optional_data, iht_optional_data_length + sectn_length); memcpy((uint8_t*)iht_optional_data + iht_optional_data_length, §n_size_id, sizeof(uint32_t)); memcpy((uint8_t*)iht_optional_data + iht_optional_data_length + sizeof(uint32_t), data, size); uint32_t checksum = ComputeWordChecksum((uint8_t*)iht_optional_data + iht_optional_data_length, sectn_length - sizeof(uint32_t)); memcpy((uint8_t*)iht_optional_data + iht_optional_data_length + sectn_length - sizeof(uint32_t), &checksum, sizeof(uint32_t)); iht_optional_data_length += sectn_length; } } copied_iht_optional_data_length = iht_optional_data_length; if (numHashTableEntries != 0) { /* Optional Data Header + Optional Data Actual size (32 bit(4Bytes) partition Number + Hash Length in bytes) + Checksum */ uint16_t sectn_length = sizeof(uint32_t) + (numHashTableEntries * (sizeof(uint32_t) + SHA3_LENGTH_BYTES)) + sizeof(uint32_t); iht_optional_data = (uint32_t*)realloc(iht_optional_data, iht_optional_data_length + sectn_length); memset((uint8_t*)iht_optional_data + iht_optional_data_length, 0, sectn_length); iht_optional_data_length += sectn_length; } if (iht_optional_data_length != 0) { uint32_t padLength = (iht_optional_data_length % 64 != 0) ? 64 - (iht_optional_data_length % 64) : 0; iht_optional_data = (uint32_t*)realloc(iht_optional_data, iht_optional_data_length + padLength); memset((uint8_t*)iht_optional_data + (iht_optional_data_length), 0xFF, padLength); iht_optional_data_length += padLength; section->IncreaseLengthAndPadTo(sizeof(VersalImageHeaderTableStructure) + iht_optional_data_length, 0); memcpy(section->Data + sizeof(VersalImageHeaderTableStructure), iht_optional_data, iht_optional_data_length); iHTable = (VersalImageHeaderTableStructure*)section->Data; iHTable->optionalDataSize = iht_optional_data_length / 4; } LOG_TRACE("User optional data is processed"); } /******************************************************************************/ void VersalImageHeaderTable::RealignSectionDataPtr(void) { iHTable = (VersalImageHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t VersalImageHeaderTable::GetImageHeaderTableVersion(void) { return iHTable->version; } /******************************************************************************/ uint32_t VersalImageHeaderTable::GetPartitionCount(void) { return iHTable->partitionTotalCount; } /******************************************************************************/ uint32_t VersalImageHeaderTable::GetImageCount(void) { return iHTable->imageTotalCount; } /******************************************************************************/ uint32_t VersalImageHeaderTable::GetFirstImageHeaderOffset(void) { return iHTable->firstImageHeaderWordOffset; } /******************************************************************************/ uint32_t VersalImageHeaderTable::GetTotalMetaHdrLength() { return (iHTable->totalMetaHdrLength) * sizeof(uint32_t); } /******************************************************************************/ void VersalImageHeaderTable::ValidateSecurityCombinations(Authentication::Type authType, Encryption::Type encryptType, Checksum::Type cksumType) { if (cksumType != Checksum::None) { if (authType != Authentication::None) { LOG_ERROR("Checksum is not supported with Authentication"); } if (encryptType != Encryption::None) { LOG_ERROR("Checksum is not supported with Encryption"); } } } /******************************************************************************/ VersalImageHeader::VersalImageHeader(std::string& filename) : ImageHeader(filename) , imageHeader(NULL) , cdoHeader(NULL) , aie_array_base_address(AIE_BASE_ADDR) , coreBaseAddr(0) , southBankBaseAddr(0) , westBankBaseAddr(0) , northBankBaseAddr(0) , eastBankBaseAddr(0) , num_of_slrs(0) { Name = StringUtils::BaseName(filename); uint32_t size = sizeof(VersalImageHeaderStructure); section = new Section("ImageHeader " + Name, size); memset(section->Data, 0, size); } /******************************************************************************/ VersalImageHeader::VersalImageHeader(uint8_t* data, uint64_t len) : ImageHeader(data, len) , imageHeader(NULL) , cdoHeader(NULL) , aie_array_base_address(AIE_BASE_ADDR) , coreBaseAddr(0) , southBankBaseAddr(0) , westBankBaseAddr(0) , northBankBaseAddr(0) , eastBankBaseAddr(0) , num_of_slrs(0) { Name = "Buffer" + StringUtils::Format(".%d", bufferIndex++); uint32_t size = sizeof(VersalImageHeaderStructure); section = new Section("ImageHeader " + Name, size); memset(section->Data, 0, size); } /******************************************************************************/ VersalImageHeader::VersalImageHeader(std::ifstream& ifs, bool IsBootloader) : ImageHeader(ifs) , imageHeader(NULL) , cdoHeader(NULL) , aie_array_base_address(AIE_BASE_ADDR) , coreBaseAddr(0) , southBankBaseAddr(0) , westBankBaseAddr(0) , northBankBaseAddr(0) , eastBankBaseAddr(0) , num_of_slrs(0) { bool firstValidHdr = false; VersalImageHeaderStructure importedIH; long pos = ifs.tellg(); ifs.read((char*)&importedIH, 4 * sizeof(uint32_t)); char buffer[4]; char name[256]; uint32_t i = 0; do { ifs.read(buffer, 4); name[i + 0] = buffer[0]; name[i + 1] = buffer[1]; name[i + 2] = buffer[2]; name[i + 3] = buffer[3]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } Name = name; uint32_t size = sizeof(VersalImageHeaderStructure); ifs.seekg(pos); section = new Section("ImageHeader " + Name, size); imageHeader = (VersalImageHeaderStructure*)section->Data; ifs.read((char*)imageHeader, size); uint32_t count = 0; if (imageHeader->dataSectionCount < 32) { count = imageHeader->dataSectionCount; } uint32_t offset = imageHeader->partitionHeaderWordOffset * sizeof(uint32_t); for (uint8_t index = 0; index < count; index++) { Bootloader = IsBootloader; VersalPartitionHeader* hdr = new VersalPartitionHeader(this, index); if (!firstValidHdr) { hdr->firstValidIndex = true; firstValidHdr = true; } ifs.seekg(offset); hdr->ReadHeader(ifs); hdr->ReadData(ifs); if (hdr->GetPartitionKeySource()) { hdr->preencrypted = true; } partitionHeaderList.push_back(hdr); Alignment = 0; Offset = 0; Reserve = 0; destCpu = (DestinationCPU::Type)hdr->GetDestinationCpu(); exceptionLevel = (ExceptionLevel::Type)hdr->GetExceptionLevel(); trustzone = (TrustZone::Type)hdr->GetTrustZone(); early_handoff = hdr->GetEarlyHandoff(); hivec = hdr->GetHivec(); partitionType = hdr->GetPartitionType(); PartOwner = (PartitionOwner::Type)hdr->GetOwnerType(); dpacm = hdr->GetDpaCMFlag(); pufHdLoc = hdr->GetPufHdLocation(); offset += hdr->GetPartitionHeaderSize(); } } /******************************************************************************/ VersalImageHeader::VersalImageHeader(std::ifstream& ifs, VersalImageHeaderStructure* importedIH, bool IsBootloader, uint32_t img_index) : ImageHeader(ifs) , imageHeader(NULL) , coreBaseAddr(0) , southBankBaseAddr(0) , westBankBaseAddr(0) , northBankBaseAddr(0) , eastBankBaseAddr(0) , num_of_slrs(0) { bool firstValidHdr = false; Name = importedIH->imageName; uint32_t size = sizeof(VersalImageHeaderStructure); section = new Section("ImageHeader " + Name, size); imageHeader = (VersalImageHeaderStructure*)section->Data; memcpy(imageHeader, importedIH, size); uint32_t offset = (imageHeader->partitionHeaderWordOffset * sizeof(uint32_t)) + (img_index * sizeof(VersalPartitionHeaderTableStructure)); VersalPartitionHeaderTableStructure* tempPHT = new VersalPartitionHeaderTableStructure; ifs.seekg(offset); ifs.read((char*)tempPHT, sizeof(VersalPartitionHeaderTableStructure)); uint32_t count = 0; if (imageHeader->dataSectionCount < 32) { count = tempPHT->dataSectionCount; } delete tempPHT; for (uint8_t index = 0; index < count; index++) { Bootloader = IsBootloader; VersalPartitionHeader* hdr = new VersalPartitionHeader(this, index); if (!firstValidHdr) { hdr->firstValidIndex = true; firstValidHdr = true; } ifs.seekg(offset); hdr->ReadHeader(ifs); hdr->ReadData(ifs); if (hdr->GetPartitionKeySource()) { hdr->preencrypted = true; } partitionHeaderList.push_back(hdr); Alignment = 0; Offset = 0; Reserve = 0; destCpu = (DestinationCPU::Type)hdr->GetDestinationCpu(); exceptionLevel = (ExceptionLevel::Type)hdr->GetExceptionLevel(); trustzone = (TrustZone::Type)hdr->GetTrustZone(); early_handoff = hdr->GetEarlyHandoff(); hivec = hdr->GetHivec(); partitionType = hdr->GetPartitionType(); PartOwner = (PartitionOwner::Type)hdr->GetOwnerType(); dpacm = hdr->GetDpaCMFlag(); pufHdLoc = hdr->GetPufHdLocation(); offset += hdr->GetPartitionHeaderSize(); cluster = hdr->GetDestinationCluster(); lockstep = hdr->GetLockStepFlag(); } } /******************************************************************************/ VersalImageHeader::~VersalImageHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ uint32_t VersalImageHeader::GetImageHeaderAttributes(void) { return imageHeader->imageAttributes; } /******************************************************************************/ void VersalImageHeader::SetAuthBlock(size_t blockSize, bool flag) { if (flag) { authBlock = 0; } else { if (blockSize == 0) { authBlock = 8; } else { authBlock = blockSize; } } } /******************************************************************************/ void VersalImageHeader::SetPartitionUid(uint32_t id) { partitionUid = id; } /******************************************************************************/ void VersalImageHeader::SetEncryptionKeySrc(KeySource::Type type) { keySrc = type; if (type != KeySource::None) { LOG_TRACE("Setting Encryption Key Source as %d", type); } } /******************************************************************************/ void VersalImageHeader::SetImageId(void) { /* This is for the non-subsystem flow. BOOTGEN_SUBSYSTEM_PDI = 0 Place image IDs as per the new subsystem guidelines i.e. 0x1c000001 for PMC subsystem and 0x1c000000 for default subsystems */ if (IsBootloader()) { imageHeader->imageId = 0x1c000001; } else { imageHeader->imageId = 0x1c000000; } } /******************************************************************************/ void VersalImageHeader::SetPartitionRevocationId(uint32_t id) { partitionRevokeId = id; } /******************************************************************************/ void VersalImageHeader::SetMemCopyAddr() { if (ihMemCpyAddr == 0xFFFFFFFFFFFFFFFF) { ihMemCpyAddr = 0; } imageHeader->memcpyAddressLo = ihMemCpyAddr; imageHeader->memcpyAddressHi = ihMemCpyAddr >> 32; } /******************************************************************************/ uint32_t VersalImageHeader::GetPartitionUid(void) { return partitionUid; } /******************************************************************************/ KeySource::Type VersalImageHeader::GetEncryptionKeySrc(void) { return keySrc; } /******************************************************************************/ uint32_t VersalImageHeader::GetPartitionRevocationId() { return partitionRevokeId; } /******************************************************************************/ DpaCM::Type VersalImageHeader::GetDpacm(void) { return dpacm; } /******************************************************************************/ PufHdLoc::Type VersalImageHeader::GetPufHdLocation(void) { return pufHdLoc; } /******************************************************************************/ std::string VersalImageHeader::GetKekIV(void) { return kekIvFile; } /******************************************************************************/ void VersalImageHeader::Build(BootImage& bi, Binary& cache) { if ((bi.subSysImageList.size() == 0) || (bi.createSubSystemPdis == false)) { if (section != NULL) { bi.headers.push_back(section); bi.imageHeaderTable->metaHeaderLength += section->Length; } } uint32_t defaultAlignment = bi.options.GetDefaultAlignment(); if (imageHeader == NULL) { imageHeader = (VersalImageHeaderStructure*)section->Data; SetImageName(); SetImageHeaderAttributes(); SetDataSectionCount(0); SetPartitionHeaderOffset(0); SetMetaHdrRevokeId(bi.bifOptions->metaHdrAttributes.revokeId); SetImageId(); SetMemCopyAddr(); if (Alignment.IsSet() && Offset.IsSet()) { LOG_ERROR("[alignment] and [offset] attributes are mutually exclusive"); } if (Alignment.IsSet() && (Alignment.Value() & (defaultAlignment - 1))) { LOG_ERROR("Alignment (0x%X) is not a multiple of %d", Alignment.Value(), defaultAlignment); } if (Reserve.IsSet() && (Reserve.Value() & (defaultAlignment - 1))) { LOG_ERROR("Reserve (0x%X) is not a multiple of %d", Reserve.Value(), defaultAlignment); } if (Offset.IsSet() && (Offset.Value() & (defaultAlignment - 1))) { LOG_ERROR("Offset (0x%X) is not a multiple of %d", Offset.Value(), defaultAlignment); } partitionHeaderList.clear(); ParseFileToImport(bi); SetDataSectionCount(partitionHeaderList.size()); } bi.partitionHeaderList.insert(bi.partitionHeaderList.end(), partitionHeaderList.begin(), partitionHeaderList.end()); } /******************************************************************************/ void VersalImageHeader::ImportBin(BootImage& bi) { SetDomain(Domain::PS); Binary::Address_t load_addr, exec_addr; ByteFile data(Filename); if (Load.IsSet()) { load_addr = Load.Value(); } else { load_addr = 0; } if (Startup.IsSet()) { exec_addr = Startup.Value(); } else { exec_addr = 0; } uint32_t dataValue; uint32_t alignlen = data.len + ((4 - (data.len & 3)) & 3); uint8_t* tempBuffer = new uint8_t[alignlen]; if (GetPartitionType() == PartitionType::CONFIG_DATA_OBJ) { dataValue = ReadBigEndian32(data.bytes + 4); bool change_endianness = false; if ((dataValue != 0x584c4e58) && (dataValue != 0x584e4c58) && (dataValue != 0x004f4443) && (dataValue != 0x43444f00)) { LOG_ERROR("Invalid CDO format - incorrect identification word (XLNX/CDO) - 0x%x", dataValue); } /* Read ID value (XNLX/CDO) from CDO Header to identify endianness */ if (dataValue == 0x584c4e58 || dataValue == 0x004f4443) { /* Convert BE CDOs to LE */ change_endianness = true; LOG_WARNING("CDO is in Big Endian format. Big Endian CDOs are deprecated. Please use little endian CDOs."); } for (uint32_t index = 0; index < data.len; index += 4) { dataValue = ReadBigEndian32(data.bytes + index); if (change_endianness) { WriteLittleEndian32(tempBuffer + index, dataValue); } else { WriteBigEndian32(tempBuffer + index, dataValue); } } if (PostProcessCdo(tempBuffer, data.len)) return; load_addr = 0xFFFFFFFF; exec_addr = 0; } else if (GetPartitionType() == PartitionType::CFI) { uint32_t value[4] = { 0 }; /* Rearrange data in CFI files as follows CFI File: D6 00 00 52 BE BA FE C0 BE BA FE C0 BE BA FE C0 PDI File: C0 FE BA BE C0 FE BA BE C0 FE BA BE 52 00 00 D6 */ for (uint32_t index = 0; index < data.len; index += 16) { /* Read 32-bit word, change endianness Swap positions of 4 32-bit words */ for (uint8_t i = 0; i < 4; i++) { value[i] = ReadBigEndian32(data.bytes + index + (4 * i)); WriteLittleEndian32(tempBuffer + index + 4 * (3 - i), value[i]); } } exec_addr = 0; } else { memcpy(tempBuffer, data.bytes, alignlen); } PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->loadAddress = load_addr; hdr->execAddress = exec_addr; if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(alignlen > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { alignlen = Reserve.Value(); } } } hdr->partition = new VersalPartition(hdr, tempBuffer, alignlen); hdr->partitionSize = alignlen; delete[] tempBuffer; SetLoadAndExecAddress(hdr); partitionHeaderList.push_back(hdr); } /******************************************************************************/ void VersalImageHeader::ImportBuffer(BootImage& bi) { SetDomain(Domain::PS); PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = Startup.ValueOrDefault(0); if (Load.IsSet()) { hdr->loadAddress = Load.Value(); } else { hdr->loadAddress = 0; if ((GetPartitionType() == PartitionType::CFI) || (GetPartitionType() == PartitionType::NPI) || (GetPartitionType() == PartitionType::CONFIG_DATA_OBJ)) { SetDomain(Domain::PL); } } if(updateReserveInPh) { if(Reserve.IsSet()) { if(bufferSize > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { bufferSize = Reserve.Value(); } } } hdr->partition = new VersalPartition(hdr, buffer, bufferSize); hdr->partitionSize = bufferSize; partitionHeaderList.push_back(hdr); } /******************************************************************************/ void VersalImageHeader::ImportNpi(BootImage& bi) { SetPartitionType(PartitionType::CONFIG_DATA_OBJ); if (Bootloader) { LOG_ERROR("NPI can not be marked [bootloader]"); } /* Parse the bitstream, and set the bit file name for usage by other features such as '-process_bitstream' */ std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read NPI file - %s ", Filename.c_str()); } BitFile *bit = new VersalBitFile(stream); bit->ParseBit(bi); bi.bitFilename = Filename.c_str(); /* The endianess is different (Big Endian) in case of Zynq MP/FPGA encryption cases. All other cases the the bitstream is copied as Little Endian */ OutputStream *os = bit->GetOutputStreamType(); bit->CopyNpi(os); /* Bitstream sizes should be word aligned. Otherwise bitstream is invalid */ if (os->Size() % 4) { LOG_DEBUG(DEBUG_STAMP, "BIT stream %s does not have a word aligned number of bytes (0xX)", Name.c_str(), (uint32_t)os->Size()); LOG_ERROR("BIT file parsing error !!!"); } /* As bitstreams are configured in the PL section There should be no load / start-up (execution) addresses in case of bitstreams. */ if (this->Startup.IsSet()) { LOG_ERROR("[startup=...] attribute not supported for BIT partition - %s", this->Name.c_str()); } if (PostProcessCdo(os->Start(), os->Size())) return; PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = 0; /* Padding of the partition, based on encryption */ hdr->partitionSize = os->Size(); // Larger size, if needed. hdr->transferSize = os->Size(); hdr->preservedBitstreamHdr = os->pHdr; hdr->partition = new VersalPartition(hdr, os->Start(), os->Size()); partitionHeaderList.push_back(hdr); } /******************************************************************************/ void VersalImageHeader::ImportBit(BootImage& bi) { /* Bitstream can never be marked as a bootloader */ if (Bootloader) { LOG_ERROR("Bit stream can not be marked [bootloader]"); } static bool cfi_gsc_mask = false; if (GetPartitionType() == PartitionType::CFI_GSC) { if (!cfi_gsc_mask) { SetPartitionType(PartitionType::CFI_GSC_UNMASK); cfi_gsc_mask = true; } else if (cfi_gsc_mask) { SetPartitionType(PartitionType::CFI_GSC); cfi_gsc_mask = false; } } else { SetPartitionType(PartitionType::CFI); } /* Parse the bitstream, and set the bit file name for usage by other features such as '-process_bitstream' */ std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read BIT file - %s ", Filename.c_str()); } BitFile *bit = new VersalBitFile(stream); bit->ParseBit(bi); bi.bitFilename = Filename.c_str(); /* The endianess is different (Big Endian) in case of Zynq MP/FPGA encryption cases. All other cases the the bitstream is copied as Little Endian */ OutputStream *os = bit->GetOutputStreamType(); bit->Copy(os); /* Bitstream sizes should be word aligned. Otherwise bitstream is invalid */ if (os->Size() % 4) { LOG_DEBUG(DEBUG_STAMP, "BIT stream %s does not have a word aligned number of bytes (0xX)", Name.c_str(), (uint32_t)os->Size()); LOG_ERROR("BIT file parsing error !!!"); } /* As bitstreams are configured in the PL section There should be no load / start-up (execution) addresses in case of bitstreams. */ if (this->Startup.IsSet()) { LOG_ERROR("[startup=...] attribute not supported for BIT partition - %s", this->Name.c_str()); } PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = 0; /* Padding of the partition, based on encryption */ hdr->partitionSize = os->Size(); // Larger size, if needed. hdr->transferSize = os->Size(); hdr->preservedBitstreamHdr = os->pHdr; SetPartitionType(PartitionType::CFI); hdr->partition = new VersalPartition(hdr, os->Start(), os->Size()); partitionHeaderList.push_back(hdr); } /******************************************************************************/ void VersalImageHeader::ParseFileToImport(BootImage& bi) { if (destCpu == DestinationCPU::AIE) { if (bi.convertAieElfToCdo == true) { CreateAieEnginePartition(bi); LOG_INFO("AIE partitions are created by converting AIE elfs to CDOs"); } else { ImportAieEngineElf(bi); LOG_INFO("AIE partitions are created using AIE elfs"); } } else if (partitionType == PartitionType::SLR_BOOT) { CreateSlrBootPartition(bi); } else if (partitionType == PartitionType::SLR_CONFIG) { CreateSlrConfigPartition(bi); } else if (partitionType == PartitionType::IMAGE_STORE_PDI) { CreateWriteImageStorePartition(); } else { if (Filename != "") { if (FileUtils::GetFileSize(Filename) == 0) { LOG_ERROR("Cannot read empty file - %s ", Filename.c_str()); } if ((filelist.size() > 1) && (GetPartitionType() != PartitionType::CONFIG_DATA_OBJ)) { LOG_ERROR("File for merging is not in CDO format - %s", Filename.c_str()); } LOG_INFO("Parsing file - %s", filelist.at(0).c_str()); std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read file - %s ", Filename.c_str()); } std::string line; while(line == "") { getline(stream, line); } if (IsElf(line) && (partitionType != PartitionType::RAW)) { ImportElf(bi); } else if (!IsElf(line) && (partitionType == PartitionType::RAW)) { ImportBin(bi); } else if ((line.find("Xilinx ASCII Bitstream") != std::string::npos) || (line.find("Xilinx ASCII CFI Deviceimage") != std::string::npos)) { ImportBit(bi); } else if ((line.find("Xilinx ASCII NPI Deviceimage") != std::string::npos) || (line.find("Xilinx ASCII PSAXIMM Deviceimage") != std::string::npos) || (line.find("version") != std::string::npos) || (GetPartitionType() == PartitionType::CONFIG_DATA_OBJ)) { ImportCdo(bi); } else { if (IsElf(line)) { SetPartitionType(PartitionType::RAW_ELF); } else if (GetPartitionType() != PartitionType::RESERVED) { SetPartitionType(GetPartitionType()); } else { SetPartitionType(PartitionType::RAW); } ImportBin(bi); } stream.close(); } else { ImportBuffer(bi); } } } /******************************************************************************/ void VersalImageHeader::ImportCdoSource(BootImage& bi) { uint8_t* buffer = NULL; size_t size = 0; buffer = DecodeCdo(Filename, &size); if (PostProcessCdo(buffer, size)) return; PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->loadAddress = 0xFFFFFFFFFFFFFFFF; hdr->execAddress = 0; hdr->partition = new VersalPartition(hdr, buffer, size); hdr->partitionSize = size; delete[] buffer; SetLoadAndExecAddress(hdr); partitionHeaderList.push_back(hdr); } /******************************************************************************/ void VersalImageHeader::ImportCdo(BootImage& bi) { uint8_t* buffer = NULL; size_t size = 0; if (filelist.size() > 0) { if ((bi.bifOptions->pdiType == PartitionType::SLR_SLAVE_CONFIG) && (getenv("BOOTGEN_PROCESS_NOC_MARKERS") != NULL)) { ParseSlaveSlrConfigCdos(bi, filelist, &buffer, &size, false); } else { ParseCdos(bi, filelist, &buffer, &size, false); } } SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->loadAddress = 0xFFFFFFFFFFFFFFFF; hdr->execAddress = 0; if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { size = Reserve.Value(); } } } hdr->partition = new VersalPartition(hdr, buffer, size); hdr->partitionSize = hdr->transferSize = size; delete[] buffer; SetLoadAndExecAddress(hdr); partitionHeaderList.push_back(hdr); } /******************************************************************************/ uint8_t* VersalImageHeader::DecodeCdo(std::string file, size_t* size) { uint8_t* buffer = NULL; FILE* fp = fopen(file.c_str(), "r"); CdoSequence* seq = cdoseq_from_source(fp); fclose(fp); if (seq == NULL) { LOG_ERROR("Error decoding CDO file %s", file.c_str()); } buffer = (uint8_t*)cdoseq_to_binary(seq, size, 0); return buffer; } /******************************************************************************/ void VersalImageHeader::Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageHeader) { slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; imageHeader = (VersalImageHeaderStructure*)section->Data; if (partitionHeader->section != NULL) { SetPartitionHeaderOffset((uint32_t)partitionHeader->section->Address); } SetImageId(); SetChecksum(); } /******************************************************************************/ void VersalImageHeader::SetMetaHdrRevokeId(uint32_t revokeId) { imageHeader->metaHdrRevokeId = revokeId; } /******************************************************************************/ void VersalImageHeader::SetChecksum(void) { imageHeader->ihChecksum = ComputeWordChecksum(imageHeader, sizeof(VersalImageHeaderStructure) - sizeof(imageHeader->ihChecksum) /* bytes*/); } /******************************************************************************/ void VersalImageHeader::SetPartitionHeaderOffset(uint32_t addr) { imageHeader->partitionHeaderWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (imageHeader->partitionHeaderWordOffset != 0)) { imageHeader->partitionHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void VersalImageHeader::SetDataSectionCount(uint32_t cnt) { imageHeader->dataSectionCount = cnt; } /******************************************************************************/ void VersalImageHeader::SetImageHeaderAttributes() { if (GetPartOwner() != PartitionOwner::FSBL) { imageHeader->imageAttributes = 1 << 3; } else { imageHeader->imageAttributes = 0; } if (ihDelayLoad) { imageHeader->imageAttributes |= (1 << vihDelayLoadShift); } if (ihDelayHandoff) { imageHeader->imageAttributes |= (1 << vihDelayHandoffShift); } if (ihMemCpyAddr != 0xFFFFFFFFFFFFFFFF) { imageHeader->imageAttributes |= (1 << vihCopyToMemoryShift); } } /******************************************************************************/ void VersalImageHeader::SetImageName(void) { /* Only 16-bytes available to store the name name length <= 16 bytes - complete name name length > 16 bytes - some part of name + file extension */ std::string ext = StringUtils::GetExtension(Name); uint32_t i = 0; if (Name.size() <= 16) { for (i = 0; i < Name.size(); i++) { imageHeader->imageName[i] = Name[i]; } } else { for (i = 0; i < (16 - ext.size()); i++) { imageHeader->imageName[i] = Name[i]; } uint8_t j = 0; for (; i < 16; i++) { imageHeader->imageName[i] = ext[j++]; } } } /******************************************************************************/ uint32_t VersalImageHeader::GetPartitionHeaderOffset(void) { return imageHeader->partitionHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t VersalImageHeader::GetDataSectionCount(void) { return imageHeader->dataSectionCount; } /******************************************************************************/ std::vector SplitString(std::string strToSplit, char delimeter) { std::stringstream ss(strToSplit); std::string item; std::vector splittedStrings; while (std::getline(ss, item, delimeter)) { splittedStrings.push_back(item); } return splittedStrings; } /******************************************************************************/ void VersalImageHeader::ImportElf(BootImage& bi) { uint8_t proc_state = 0; domain = Domain::PS; SetPartitionType(PartitionType::ELF); /* Convert the file into array of bytes */ ByteFile data(Filename); /* Get the ELF Class format - 32-bit elf vs 64-bit elf */ elfClass = GetElfClass(data.bytes); ElfFormat* elf = ElfFormat::GetElfFormat(elfClass, data.bytes, &proc_state); /* Check for no. of executable sections & non-zero size LOAD sections */ uint8_t exec_count = 0; uint8_t non_zero_elf_sec_count = 0; for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { if (elf->GetProgramHeaderFlags(iprog) & PF_X) { exec_count++; } if ((elf->GetProgramHeaderFileSize(iprog) > 0) && (elf->GetProgramHeaderType(iprog) == xPT_LOAD)) { non_zero_elf_sec_count++; } } if (non_zero_elf_sec_count == 0) { LOG_ERROR("No non-empty program sections in %s", Filename.c_str()); } // Variables for combining sections uint32_t num_hdrs = 0; uint32_t hdr_index = 0; Binary::Length_t size = 0; Binary::Length_t total_size = 0; Binary::Address_t addr = 0; Binary::Address_t prev_end = 0; Binary::Address_t offset = 0; Binary::Address_t load_addr = 0; Binary::Address_t exec_addr = 0; uint8_t *partition_data = NULL; /* Loop through all the program headers and populate the fields exec, load address etc. */ for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { bool first_index = false; size = elf->GetProgramHeaderFileSize(iprog); addr = elf->GetPhysicalAddress(iprog); exec_addr = elf->GetStartUpAddress(); /* For bootloader, all the sections are combined by padding the gaps to create only partition */ if (Bootloader) { bi.imageHeaderTable->SetOptionalData(elf->iht_optional_data, elf->iht_optional_data_size); bi.imageHeaderTable->SetXplmModulesData(bi, elf->xplm_modules_data, elf->xplm_modules_data_size); /* Only loadable sections with non-size are considered */ if ((elf->GetProgramHeaderType(iprog) == xPT_LOAD) && (size > 0)) { num_hdrs++; /* Consider load address of first section */ if (num_hdrs == 1) { load_addr = addr; } else { /* Calculate filler bytes and pad to combine different sections */ Binary::Length_t filler_bytes = addr - prev_end; if (filler_bytes != 0) { total_size += filler_bytes; partition_data = (uint8_t*)realloc(partition_data, total_size); memset(partition_data + offset, 0, filler_bytes); offset = total_size; } } total_size += size; partition_data = (uint8_t*)realloc(partition_data, total_size); memcpy(partition_data + offset, elf->GetProgramHeaderData(iprog), size); prev_end = addr + size; offset = total_size; } /* Loop through till last entry */ if (iprog < elf->programHdrEntryCount - 1) { continue; } /* Calculate pad bytes for aligning PMC FW for 16 byte-alignment to add to lengths populated in boot header */ uint32_t pmc_fw_pad_bytes = 0; uint64_t pmc_fw_size = total_size; if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(pmc_fw_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { pmc_fw_size = Reserve.Value(); } } } if (pmc_fw_size % 16 != 0) { pmc_fw_pad_bytes = 16 - (pmc_fw_size % 16); } SetFsblFwSizeIh(pmc_fw_size + pmc_fw_pad_bytes); SetTotalFsblFwSizeIh(pmc_fw_size + pmc_fw_pad_bytes); if ((bi.bifOptions->GetPmcCdoFileList().size() > 0) || (bi.bifOptions->GetPmcDataBuffer() != NULL)) { uint8_t* cdo_partition = NULL; size_t cdo_length = 0; if(bi.bifOptions->GetPmcCdoFileList().size() != 0) { LOG_INFO("File for merging - %s ", bi.bifOptions->GetPmcCdoFileList().at(0).c_str()); } bool add_ssit_sync_master_cmd = (bi.bifOptions->pdiType == PartitionType::SLR_SLAVE_BOOT); ParseCdos(bi, bi.bifOptions->GetPmcCdoFileList(), &cdo_partition, &cdo_length, add_ssit_sync_master_cmd); /* Calculate pad bytes for aligning PMC CDO for 16 byte-alignment */ uint32_t total_cdo_pad_bytes = 0; if (cdo_length % 16 != 0) { total_cdo_pad_bytes = 16 - (cdo_length % 16); } /* Append PMC CDO to PMC FW to create a single partition */ pmcdataSize = totalpmcdataSize = cdo_length + total_cdo_pad_bytes; total_size = pmc_fw_size + pmc_fw_pad_bytes + pmcdataSize; partition_data = (uint8_t*)realloc(partition_data, total_size); memset(partition_data + pmc_fw_size, 0, pmc_fw_pad_bytes); memcpy(partition_data + pmc_fw_size + pmc_fw_pad_bytes, cdo_partition, cdo_length); memset(partition_data + pmc_fw_size + pmc_fw_pad_bytes + cdo_length, 0, total_cdo_pad_bytes); delete[] cdo_partition; } } /* For all other partitions add each loadable section as a different partition */ else { /* Only loadable sections with non-size are considered */ if ((elf->GetProgramHeaderType(iprog) == xPT_LOAD) && (size > 0)) { load_addr = addr; total_size = size; if(updateReserveInPh == true) { if(Reserve.IsSet() && non_zero_elf_sec_count > 1) { LOG_WARNING("Multiple sections in elf. Hence reserve attribute is ignored."); } if(Reserve.IsSet() && non_zero_elf_sec_count == 1) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { total_size = Reserve.Value(); } } } partition_data = (uint8_t*)malloc(total_size); memcpy(partition_data, elf->GetProgramHeaderData(iprog), total_size); } } if (partition_data != NULL) { if (hdr_index == 0) { first_index = true; } /* Override the exec and load address, if startup & load are set through BIF attributes */ if (Startup.IsSet() && iprog == 0) { exec_addr = Startup.Value(); } if (Load.IsSet() && iprog == 0) { load_addr = Load.Value(); } PartitionHeader* partHdr = new VersalPartitionHeader(this, hdr_index); partHdr->firstValidIndex = first_index; partHdr->elfEndianess = elf->endian; partHdr->execAddress = exec_addr; partHdr->loadAddress = load_addr; partHdr->execState = proc_state; if (elf->atf_handoff_params_prg_hdr_count == iprog && elf->atf_handoff_params_found) { partHdr->atf_handoff_params_offset = elf->atf_handoff_params_offset; partHdr->update_atf_handoff_params = true; } partHdr->partition = new VersalPartition(partHdr, partition_data, total_size); // This length also includes padding size necessary for 16-byte alignment partHdr->partitionSize = partHdr->partition->section->Length; partitionHeaderList.push_back(partHdr); hdr_index++; free(partition_data); partition_data = NULL; } } } /******************************************************************************/ void VersalImageHeader::ParseSlaveSlrConfigCdos(BootImage& bi, std::vector filelist, uint8_t** cdo_data, size_t* cdo_size, bool add_ssit_sync_master) { uint8_t* total_cdo_data = NULL; uint8_t* cdo_padded_buffer = NULL; size_t cdo_padded_buffer_length = 0; uint64_t total_cdo_length = 0; uint32_t* start_marker_offsets = NULL; uint8_t num_start_markers = 0; uint32_t* end_marker_offsets = NULL; uint8_t num_end_markers = 0; if (filelist.size() > 0) { /* Offset and length are set to CDO header size, to take into account the addition of merged CDO header which will be added at the end */ uint64_t offset = sizeof(VersalCdoHeader); total_cdo_length = sizeof(VersalCdoHeader); for (uint8_t idx = 0; idx != filelist.size(); idx++) { void* cdo_data = NULL; size_t cdo_length = 0; uint64_t actual_cdo_size = 0; const char* cdo_filename = filelist.at(idx).c_str(); CdoSequence * cdo_seq; CdoSequence * cdo_seq1; if (add_ssit_sync_master) { /* Add SSIT Sync Master command */ cdo_seq1 = cdoseq_load_cdo(cdo_filename); if (cdo_seq1 == NULL) { LOG_ERROR("Error parsing CDO file"); } cdo_seq = cdocmd_create_sequence(); cdocmd_add_ssit_sync_master(cdo_seq); cdocmd_concat_seq(cdo_seq, cdo_seq1); add_ssit_sync_master = false; } else { cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file"); } } if (bi.overlayCDO && cdooverlay_apply(cdo_seq, (CdoOverlayInfo *)(bi.overlayCDO))) { LOG_ERROR("Error applying overlay CDO file"); } /* Enable the search for sync points - only needs to be done for SSIT devices */ search_for_sync_points(); cdo_data = cdoseq_to_binary(cdo_seq, &cdo_length, 0); CheckIdsInCdo(cdo_seq, bi.options.IsVersalNetSeries(), cdo_filename); if (cdo_length != 0) { actual_cdo_size = cdo_length - sizeof(VersalCdoHeader); } else { LOG_ERROR("Incorrect CDO length read from : %s", cdo_filename); } total_cdo_length += (actual_cdo_size); total_cdo_data = (uint8_t*)realloc(total_cdo_data, total_cdo_length); memcpy(total_cdo_data + offset, (uint8_t*)cdo_data + sizeof(VersalCdoHeader), actual_cdo_size); offset += actual_cdo_size; //delete cdo_data; } num_start_markers = get_num_start_markers(); start_marker_offsets = get_slr_start_marker_offsets(); num_end_markers = get_num_end_markers(); end_marker_offsets = get_slr_end_marker_offsets(); if (num_start_markers != num_end_markers) { LOG_ERROR("Number of start and end markers for NoC startup sequence is not same."); } if (num_start_markers > 0) { size_t size = 0, prev_start = 0; size_t start = 0, end = 0; uint32_t p_offset = 0; size_t copied_offset = 0; size_t pad_bytes = 0; LOG_TRACE(" markers found at offsets -"); for (int i = 0; i < num_start_markers; i++) { start = *(start_marker_offsets + i) * 4; end = *(end_marker_offsets + i) * 4; /* Create a new chunk at start only if start and end are not in same 32K data */ if (start / SSIT_CHUNK_SIZE != end / SSIT_CHUNK_SIZE) { size = start - prev_start; pad_bytes = SSIT_CHUNK_SIZE - (size % SSIT_CHUNK_SIZE); cdo_padded_buffer_length += (size + pad_bytes); cdo_padded_buffer = (uint8_t*)realloc(cdo_padded_buffer, cdo_padded_buffer_length); memcpy(cdo_padded_buffer + p_offset, total_cdo_data + copied_offset, size); p_offset += size; copied_offset += size; if (pad_bytes != 0) { CdoCommandNop* cdoCmd = CdoCmdNoOperation2(pad_bytes); memcpy(cdo_padded_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE + 4); p_offset += (CDO_CMD_NOP_SIZE + 4); if (cdoCmd->length > 0) { memset(cdo_padded_buffer + p_offset, 0, cdoCmd->length * sizeof(uint32_t)); p_offset += (cdoCmd->length * sizeof(uint32_t)); } } prev_start = start; LOG_TRACE(" offset = 0x%lx, end = 0x%lx", start, end); } else { LOG_TRACE(" skipping marker at 0x%lx since end marker (0x%lx) is in same chunk", start, end); } } /* Remaining data after last marker */ size = total_cdo_length - prev_start; cdo_padded_buffer_length += size; cdo_padded_buffer = (uint8_t*)realloc(cdo_padded_buffer, cdo_padded_buffer_length); memcpy(cdo_padded_buffer + p_offset, total_cdo_data + copied_offset, size); delete start_marker_offsets; if (end_marker_offsets) delete end_marker_offsets; total_cdo_length = (cdo_padded_buffer_length); total_cdo_data = (uint8_t*)realloc(total_cdo_data, total_cdo_length); memcpy(total_cdo_data, cdo_padded_buffer, total_cdo_length); delete cdo_padded_buffer; } VersalCdoHeader* cdo_header = new VersalCdoHeader; cdo_header->remaining_words = 0x04; cdo_header->id_word = 0x004f4443; /* CDO */ cdo_header->version = 0x00000200; /* Version - 2.0 */ cdo_header->length = (total_cdo_length - sizeof(VersalCdoHeader)) / 4; cdo_header->checksum = ~(cdo_header->remaining_words + cdo_header->id_word + cdo_header->version + cdo_header->length); memcpy(total_cdo_data, cdo_header, sizeof(VersalCdoHeader)); delete cdo_header; } *cdo_size = total_cdo_length; *cdo_data = total_cdo_data; } /******************************************************************************/ void VersalImageHeader::ParseCdos(BootImage& bi, std::vector filelist, uint8_t** cdo_data, size_t* cdo_size, bool add_ssit_sync_master) { uint8_t* total_cdo_data = NULL; uint64_t total_cdo_length = 0; void *cdo_data_pp = NULL; size_t cdo_data_pp_length = 0; char slrid_from_source = 0; char slrid_from_binary = 0; char input_ch_souce = 0; char input_ch_binary = 0; bool is_source_cdo = false; bool is_binary_cdo = false; uint32_t idcode_source = 0; uint32_t source_cdo_idcode = 0; uint32_t idcode_binary = 0; uint32_t binary_cdo_idcode = 0; if (filelist.size() > 0) { /* Offset and length are set to CDO header size, to take into account the addition of merged CDO header which will be added at the end */ uint64_t offset = sizeof(VersalCdoHeader); total_cdo_length = sizeof(VersalCdoHeader); for (uint8_t idx = 0; idx != filelist.size(); idx++) { void* cdo_data = NULL; size_t cdo_length = 0; uint64_t actual_cdo_size = 0; const char* cdo_filename = filelist.at(idx).c_str(); CdoSequence * cdo_seq; CdoSequence * cdo_seq1; if (add_ssit_sync_master) { /* Add SSIT Sync Master command */ cdo_seq1 = cdoseq_load_cdo(cdo_filename); if (cdo_seq1 == NULL) { LOG_ERROR("Error parsing CDO file"); } cdo_seq = cdocmd_create_sequence(); cdocmd_add_ssit_sync_master(cdo_seq); cdocmd_concat_seq(cdo_seq, cdo_seq1); add_ssit_sync_master = false; } else { cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file"); } } slrid_from_source = slr_id_from_source(input_ch_souce); if (slrid_from_source != 0) { if (bi.globalSlrId != 0) { is_source_cdo = (bi.globalSlrId == slrid_from_source); if (is_source_cdo == false) { LOG_WARNING("Mismatch between SLR ID of %s and rest of the CDOs. This may cause runtime issues. \n Please ensure that all the CDOs used for creating the pdi are for the same SLR/device", cdo_filename); } bi.globalSlrId = 0; } bi.globalSlrId = slrid_from_source; } else { slrid_from_binary = slr_id_from_binary(input_ch_binary); if (slrid_from_binary != 0) { if (bi.globalSlrId != 0) { is_binary_cdo = (bi.globalSlrId == slrid_from_binary); if (is_binary_cdo == false) { LOG_WARNING("Mismatch between SLR ID of %s and rest of the CDOs. This may cause runtime issues. \n Please ensure that all the CDOs used for creating the pdi are for the same SLR/device", cdo_filename); } bi.globalSlrId = 0; } else { bi.globalSlrId = slrid_from_binary; } } } if (bi.overlayCDO && cdooverlay_apply(cdo_seq, (CdoOverlayInfo *)(bi.overlayCDO))) { LOG_ERROR("Error applying overlay CDO file"); } cdo_data = cdoseq_to_binary(cdo_seq, &cdo_length, 0); CheckIdsInCdo(cdo_seq, bi.options.IsVersalNetSeries(), cdo_filename); // TODO: Call this only for v2 const char * env = getenv("BOOTGEN_CHECK_CDO_COMMANDS"); if (env && *env != '\0') { if (check_cdo_commands(cdo_data, cdo_length, bi.xplm_modules_data, bi.xplm_modules_data_length) != 0) { LOG_WARNING("Invalid PLM cdo command is found in input cdo file"); } } //cdocmd_delete_sequence(cdo_seq); if (cdocmd_post_process_cdo(cdo_data, cdo_length, &cdo_data_pp, &cdo_data_pp_length)) { LOG_ERROR("PMC CDO post process error"); } source_cdo_idcode = idcode_from_source(idcode_source); binary_cdo_idcode = idcode_from_binary(idcode_binary); if (source_cdo_idcode != 0) { if (bi.bifOptions->idCode != source_cdo_idcode) { //LOG_WARNING("CDO %s is of different device than cdos present in pdi", cdo_filename); } } else if (binary_cdo_idcode != 0) { if (bi.bifOptions->idCode != binary_cdo_idcode) { //LOG_WARNING("CDO %s is of different device than cdos present in pdi", cdo_filename); } } if (cdo_data_pp != NULL) { //delete cdo_data; cdo_data = (uint8_t*)cdo_data_pp; cdo_length = cdo_data_pp_length; } if (cdo_length > sizeof(VersalCdoHeader)) { actual_cdo_size = cdo_length - sizeof(VersalCdoHeader); } else { LOG_ERROR("Incorrect cdo length read from : %s", cdo_filename); } total_cdo_length += (actual_cdo_size); total_cdo_data = (uint8_t*)realloc(total_cdo_data, total_cdo_length); memcpy(total_cdo_data + offset, (uint8_t*)cdo_data + sizeof(VersalCdoHeader), actual_cdo_size); offset += actual_cdo_size; //delete cdo_data; } VersalCdoHeader* cdo_header = new VersalCdoHeader; cdo_header->remaining_words = 0x04; cdo_header->id_word = 0x004f4443; /* CDO */ cdo_header->version = 0x00000200; /* Version - 2.0 */ cdo_header->length = (total_cdo_length - sizeof(VersalCdoHeader)) / 4; cdo_header->checksum = ~(cdo_header->remaining_words + cdo_header->id_word + cdo_header->version + cdo_header->length); memcpy(total_cdo_data, cdo_header, sizeof(VersalCdoHeader)); delete cdo_header; } else { /* If PMC CDO is passed as a buffer or in case PDI is passed as input in BIF, PMC data is read into a buffer from the PDI */ total_cdo_length = bi.bifOptions->GetTotalpmcdataSize(); total_cdo_data = new uint8_t[total_cdo_length]; memcpy(total_cdo_data, bi.bifOptions->GetPmcDataBuffer(), total_cdo_length); } *cdo_size = total_cdo_length; *cdo_data = total_cdo_data; } /******************************************************************************/ void VersalImageHeader::CreateAieEnginePartition(BootImage& bi) { bool is_dir = false; std::ifstream aie_file(Filename); uint64_t size = 0; struct stat buf; std::list aie_elf_list; if (stat(Filename.c_str(), &buf) == 0) { is_dir = S_IFDIR & buf.st_mode; } if (!is_dir) { aie_elf_list = bi.bifOptions->aie_elfs; } else { aie_elf_list = GetAieFilesPath(Filename); } for (std::list::iterator aie_file = aie_elf_list.begin(); aie_file != aie_elf_list.end(); aie_file++) { size += ImportAieEngineElfCdo(*aie_file); } cdoHeader = new VersalCdoHeader; cdoHeader->remaining_words = 0x04; cdoHeader->id_word = 0x004f4443; /* CDO */ cdoHeader->version = 0x00000200; /* Version - 2.0 */ size += sizeof(VersalCdoHeader); PartitionHeader* partHdr = new VersalPartitionHeader(this, 0); partHdr->execState = 0; partHdr->elfEndianess = 0; partHdr->firstValidIndex = true; uint8_t* pBuffer = new uint8_t[size]; uint32_t p_offset = 0; cdoHeader->length = (size - sizeof(VersalCdoHeader)) / 4; cdoHeader->checksum = ~(cdoHeader->remaining_words + cdoHeader->id_word + cdoHeader->version + cdoHeader->length); memcpy(pBuffer, cdoHeader, sizeof(VersalCdoHeader)); p_offset += sizeof(VersalCdoHeader); for (std::list::iterator it = cdoSections.begin(); it != cdoSections.end(); it++) { memcpy(pBuffer + p_offset, (*it), CDO_COMMAND_SIZE); p_offset += CDO_COMMAND_SIZE; memcpy(pBuffer + p_offset, (*it)->data, ((*it)->length - 2) * 4); p_offset += (((*it)->length - 2) * 4); delete *it; } partHdr->partitionSize = size; partHdr->partition = new VersalPartition(partHdr, pBuffer, size); partitionHeaderList.push_back(partHdr); delete[] pBuffer; cdoSections.clear(); } /******************************************************************************/ std::list VersalImageHeader::GetAieFilesPath(std::string filename) { std::list aie_elf_list; std::list core_list; std::string json_file; std::string file_path; file_path = filename + "//" + "aie" + "//"; json_file = file_path + "active_cores.json"; std::ifstream aie_json(json_file); if (!aie_json.good()) { LOG_ERROR("AIE Work \"%s\" directory doesn't have AIE folder", filename.c_str()); } core_list = ParseAieJson(json_file.c_str()); for (std::list::iterator aie_file = core_list.begin(); aie_file != core_list.end(); aie_file++) { std::string aie_elf = file_path + (*aie_file) + "//" + "Release" + "//" + (*aie_file); aie_elf_list.push_back(aie_elf); } return aie_elf_list; } /******************************************************************************/ uint64_t VersalImageHeader::ImportAieEngineElfCdo(std::string aie_file) { uint32_t progHdrCnt = 0; uint8_t *newData = NULL; uint32_t rowNum = 0; uint32_t colNum = 0; SetPartitionType(PartitionType::CONFIG_DATA_OBJ); /* Convert the file into array of bytes */ ByteFile data(aie_file); /* Get the ELF Class format - 32-bit elf vs 64-bit elf */ ElfFormat32 elf(data.bytes); /* Check for no. of executable sections & non-zero size LOAD sections */ uint8_t execCount = 0; uint8_t nonZeroCount = 0; for (uint32_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { if (elf.GetProgramHeaderFlags(iprog) & PF_X) { execCount++; } if ((elf.GetProgramHeaderFileSize(iprog) > 0) && (elf.GetProgramHeaderType(iprog) == xPT_LOAD)) { nonZeroCount++; } } if (nonZeroCount == 0) { LOG_ERROR("No non-empty program sections in %s", Filename.c_str()); } // Extract column and row numbers from elf file name (elfname__.elf) // Example: test_2_4.elf -> AIE core with column-2 and row-4 std::string temp = StringUtils::RemoveExtension(StringUtils::BaseName(aie_file)); size_t pos = temp.find_last_of("."); if (pos != std::string::npos) { temp = temp.substr(pos+1); } std::vector coreName = SplitString(temp, '_'); if (coreName.size() != 2) { LOG_ERROR("Invalid core name in %s", aie_file.c_str()); } colNum = std::stoi(coreName.at(0)); rowNum = std::stoi(coreName.at(1)); /* AIE Tile details in the form of [ColumnNum (16-bits) | RowNum(16-bits)] to be put into Exec Address Lo field in case of AIE partition */ LOG_INFO("Parsing AIE elfs - %s", Filename.c_str()); CalculateAieEngineBaseAddress(colNum, rowNum); /* Loop through all the program headers and populate the fields like, startup address, load address etc., which can be overrided by the BIF file options */ uint32_t numHdrs = 0; std::size_t size = 0; std::size_t prevSize = 0; std::size_t totalSize = 0; uint64_t addr = 0; uint64_t prevAddr = 0; uint64_t offset = 0; Binary::Address_t textSecAddr = 0; Elf32ProgramHeader* elfPrgHeader = NULL; uint64_t total_psize = 0; for (uint32_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { elfPrgHeader = elf.programHeaders[iprog]; // For executable sections (combine all text sections) (addr < 0x20000 corresponds to AIE program memory) if ((elfPrgHeader->p_type == xPT_LOAD) && (elfPrgHeader->p_paddr < 0x20000) && (elfPrgHeader->p_filesz > 0) && (elfPrgHeader->p_flags & PF_X)) { size = elfPrgHeader->p_filesz; addr = elfPrgHeader->p_paddr; // Consider 1st text section for load address in PHT if (numHdrs == 0) { textSecAddr = elf.GetPhysicalAddress(iprog); } numHdrs++; if (numHdrs > 1) { std::size_t fillerBytes = (std::size_t) (addr - (prevAddr + prevSize)); totalSize += fillerBytes; newData = (uint8_t*)realloc(newData, totalSize); memset(newData + offset, 0, fillerBytes); offset = totalSize; } /* Populate the section data */ totalSize += size; newData = (uint8_t *)realloc(newData, totalSize); memcpy(newData + offset, elfPrgHeader->data, size); prevAddr = addr; prevSize = size; offset = totalSize; } } total_psize += CdoCmdDmaWrite(totalSize, GetAieEngineGlobalAddress(textSecAddr), newData); delete[] newData; for (uint8_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { elfPrgHeader = elf.programHeaders[iprog]; // For data sections (addr >= 0x20000 corresponds to AIE data memory) if ((elfPrgHeader->p_type == xPT_LOAD) && !(elfPrgHeader->p_flags & PF_X) && (elfPrgHeader->p_paddr >= 0x20000)) { if (elfPrgHeader->p_filesz > 0) { Binary::Length_t previousPartitionSize = 0, spill, pSize; Binary::Address_t pAddr; do { spill = CheckAieEngineDataMemoryBoundary((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize, elfPrgHeader->p_filesz - previousPartitionSize); pSize = elfPrgHeader->p_filesz - spill - previousPartitionSize; pAddr = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize); total_psize += CdoCmdDmaWrite(pSize, pAddr, elfPrgHeader->data + previousPartitionSize); previousPartitionSize += pSize; progHdrCnt++; } while (spill); } else if (elfPrgHeader->p_memsz > 0) { Binary::Length_t previousPartitionSize = 0, spill; do { spill = CheckAieEngineDataMemoryBoundary((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize, elfPrgHeader->p_memsz - previousPartitionSize); uint32_t pSize = elfPrgHeader->p_memsz - spill - previousPartitionSize; uint64_t pAddr = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize); uint32_t p_size_pad = pSize + ((4 - (pSize & 3)) & 3); uint8_t *databuffer = new uint8_t[p_size_pad]; memset(databuffer, 0, p_size_pad); previousPartitionSize += pSize; total_psize += CdoCmdDmaWrite(pSize, pAddr, databuffer); delete[] databuffer; progHdrCnt++; } while (spill); } } } return total_psize; } /* In physical address space, PM is mapped to 0x20000 and DM is mapped to 0x0, * whereas in logical address space, PM is mapped to 0x0 and DM is mapped to 0x20000. * Also, the DM is spread across banks in 4 directions, so adjust the row/tile number, * based on the bank in which the DM address falls. Below are the details about how to * adjust the row/col number based on the DM address. * +----------------------------+---------------+---------------+ * | Bank | Odd Row | Even Row | * |----------------------------|---------------|---------------| * | South (0 – 0x7fff) | row - 1 | row - 1 | * | West (0x8000 – 0xffff) | same tile | col - 1 | * | North (0x10000 – 0x17fff) | row + 1 | row + 1 | * | East (0x18000 – 0x1ffff) | col + 1 | same tile | * +----------------------------+---------------+---------------+ * Row 0 is now assigned to shim, so we should be using row - 1 to check if the row * is odd or even */ /******************************************************************************/ void VersalImageHeader::ImportAieEngineElf(BootImage& bi) { uint32_t progHdrCnt = 0; uint8_t procState = 0; uint8_t *newData = NULL; uint32_t rowNum = 0; uint32_t colNum = 0; SetPartitionType(PartitionType::ELF); /* Convert the file into array of bytes */ ByteFile data(Filename); /* Get the ELF Class format - 32-bit elf vs 64-bit elf */ ElfFormat32 elf(data.bytes); /* Check for no. of executable sections & non-zero size LOAD sections */ uint8_t execCount = 0; uint8_t nonZeroCount = 0; for (uint32_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { if (elf.GetProgramHeaderFlags(iprog) & PF_X) { execCount++; } if ((elf.GetProgramHeaderFileSize(iprog) > 0) && (elf.GetProgramHeaderType(iprog) == xPT_LOAD)) { nonZeroCount++; } } if (nonZeroCount == 0) { LOG_ERROR("No non-empty program sections in %s", Filename.c_str()); } // Extract column and row numbers from elf file name (elfname__.elf) // Example: test_2_4.elf -> AIE core with column-2 and row-4 std::string temp = StringUtils::RemoveExtension(StringUtils::BaseName(Filename)); std::vector coreName = SplitString(temp, '_'); if (coreName.size() != 2) { LOG_ERROR("Invalid core name in %s", Filename.c_str()); } colNum = std::stoi(coreName.at(0)); rowNum = std::stoi(coreName.at(1)); //colNum = std::stoi(temp.substr((temp.length() - 3), 1)); //rowNum = std::stoi(temp.substr((temp.length() - 1), 1)); /* AIE Tile details in the form of [ColumnNum (16-bits) | RowNum(16-bits)] to be put into Exec Address Lo field in case of AIE partition */ uint64_t aieTileDetails = (colNum << 16) | (rowNum); CalculateAieEngineBaseAddress(colNum, rowNum); /* Loop through all the program headers and populate the fields like, startup address, load address etc., which can be overrided by the BIF file options */ uint32_t numHdrs = 0; std::size_t size = 0; std::size_t prevSize = 0; std::size_t totalSize = 0; uint64_t addr = 0; uint64_t prevAddr = 0; uint64_t offset = 0; uint8_t padding = 0; Binary::Address_t textSecAddr = 0; Elf32ProgramHeader* elfPrgHeader = NULL; PartitionHeader* partHdr = new VersalPartitionHeader(this, progHdrCnt); partHdr->execState = procState; partHdr->elfEndianess = elf.endian; for (uint32_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { elfPrgHeader = elf.programHeaders[iprog]; // For executable sections (combine all text sections) (addr < 0x20000 corresponds to AIE program memory) if ((elfPrgHeader->p_type == xPT_LOAD) && (elfPrgHeader->p_paddr < 0x20000) && (elfPrgHeader->p_filesz > 0) && (elfPrgHeader->p_flags & PF_X)) { size = elfPrgHeader->p_filesz; addr = elfPrgHeader->p_paddr; // Consider 1st text section for load address in PHT if (numHdrs == 0) { textSecAddr = elf.GetPhysicalAddress(iprog); } numHdrs++; if (numHdrs > 1) { std::size_t fillerBytes = (std::size_t) (addr - (prevAddr + prevSize)); totalSize += fillerBytes; newData = (uint8_t*)realloc(newData, totalSize); memset(newData + offset, 0, fillerBytes); offset = totalSize; } /* Populate the section data */ totalSize += size; newData = (uint8_t *)realloc(newData, totalSize); memcpy(newData + offset, elfPrgHeader->data, size); prevAddr = addr; prevSize = size; offset = totalSize; partHdr->firstValidIndex = true; } } //padding = (4 - (totalSize & 3) & 3); partHdr->partitionSize = totalSize + padding; /* AIE Tile details in Exec address in case of AIE partitions Load address & execution address will be same for AIE elfs, so no need of separate exec addr field*/ //partHdr->execAddress = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetStartUpAddress()); partHdr->execAddress = aieTileDetails; // consider addr of first header partHdr->loadAddress = GetAieEngineGlobalAddress(textSecAddr); /* Create a new partition out of each valid program header */ partHdr->partition = new VersalPartition(partHdr, newData, partHdr->partitionSize); progHdrCnt++; partitionHeaderList.push_back(partHdr); for (uint8_t iprog = 0; iprog < elf.programHdrEntryCount; iprog++) { elfPrgHeader = elf.programHeaders[iprog]; // For data sections (addr >= 0x20000 corresponds to AIE data memory) if ((elfPrgHeader->p_type == xPT_LOAD) && !(elfPrgHeader->p_flags & PF_X) && (elfPrgHeader->p_paddr >= 0x20000)) { if (elfPrgHeader->p_filesz > 0) { Binary::Length_t previousPartitionSize = 0, spill; do { spill = CheckAieEngineDataMemoryBoundary((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize, elfPrgHeader->p_filesz - previousPartitionSize); PartitionHeader* partHdr = new VersalPartitionHeader(this, progHdrCnt); partHdr->partitionType = PartitionType::ELF; partHdr->partitionSize = elfPrgHeader->p_filesz - spill - previousPartitionSize; partHdr->loadAddress = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize); partHdr->partition = new VersalPartition(partHdr, elfPrgHeader->data + previousPartitionSize, partHdr->partitionSize); previousPartitionSize += partHdr->partitionSize; partitionHeaderList.push_back(partHdr); progHdrCnt++; } while (spill); } else if (elfPrgHeader->p_memsz > 0) { Binary::Length_t previousPartitionSize = 0, spill; do { spill = CheckAieEngineDataMemoryBoundary((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize, elfPrgHeader->p_memsz - previousPartitionSize); PartitionHeader* partHdr = new VersalPartitionHeader(this, progHdrCnt); partHdr->partitionType = PartitionType::ELF; partHdr->partitionSize = elfPrgHeader->p_memsz - spill - previousPartitionSize; partHdr->loadAddress = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetPhysicalAddress(iprog) + previousPartitionSize); previousPartitionSize += partHdr->partitionSize; uint8_t *databuffer = new uint8_t[partHdr->partitionSize]; memset(databuffer, 0, partHdr->partitionSize); partHdr->partition = new VersalPartition(partHdr, databuffer, partHdr->partitionSize); partitionHeaderList.push_back(partHdr); delete[] databuffer; progHdrCnt++; } while (spill); } } } delete[] newData; } /******************************************************************************/ uint32_t VersalImageHeader::CdoCmdDmaWrite(uint32_t pSize, uint64_t pAddr, uint8_t *databuffer) { uint32_t total_size; CdoCommandDmaWrite* cdoDataSec = new CdoCommandDmaWrite; uint32_t p_size_pad = pSize + ((4 - (pSize & 3)) & 3); cdoDataSec->header = 0x00ff0105; cdoDataSec->length = (p_size_pad / 4) + 2; cdoDataSec->hi_address = ((pAddr) >> 32) & 0xFFFFFFFF; cdoDataSec->lo_address = (pAddr) & 0xFFFFFFFF; cdoDataSec->data = new uint8_t[p_size_pad]; memset(cdoDataSec->data, 0, p_size_pad); memcpy(cdoDataSec->data, databuffer, pSize); cdoSections.push_back(cdoDataSec); total_size = (CDO_COMMAND_SIZE + p_size_pad); LOG_TRACE("AIE ELF CDO DMA Write Command: Address-0x%x%08x, Size-%x", cdoDataSec->hi_address, cdoDataSec->lo_address, p_size_pad); return total_size; } /******************************************************************************/ uint32_t VersalImageHeader::CdoCmdWriteImageStore(uint32_t pSize, uint64_t pdi_id, uint8_t *databuffer) { uint32_t total_size; CdoCommandWriteImageStore* cdoDataSec = new CdoCommandWriteImageStore; uint32_t p_size_pad = pSize + ((4 - (pSize & 3)) & 3); cdoDataSec->header = 0x00ff070D; cdoDataSec->length = (p_size_pad / 4) + 2; cdoDataSec->id = pdi_id; cdoDataSec->data = new uint8_t[p_size_pad]; memset(cdoDataSec->data, 0, p_size_pad); memcpy(cdoDataSec->data, databuffer, pSize); total_size = (CDO_COMMAND_SIZE + p_size_pad); return total_size; } /******************************************************************************/ void VersalImageHeader::CalculateAieEngineBaseAddress(uint32_t colNum, uint32_t rowNum) { #define AIE_ARRAY_TILE_STRIDE 0x40000 #define AIE_ARRAY_ROW_WIDTH 32 // Row-0 is always used for SHIM, so actual rows start from 1 rowNum++; uint32_t coreIndex = AIE_ARRAY_ROW_WIDTH * colNum + rowNum; coreBaseAddr = aie_array_base_address + (coreIndex * AIE_ARRAY_TILE_STRIDE); // South Tile uint32_t southCoreIndex = ((AIE_ARRAY_ROW_WIDTH * colNum) + (rowNum - 1)); southBankBaseAddr = aie_array_base_address + (southCoreIndex * AIE_ARRAY_TILE_STRIDE); // West Tile uint32_t westCoreIndex = ((rowNum - 1) % 2) ? coreIndex : ((AIE_ARRAY_ROW_WIDTH * (colNum - 1)) + rowNum); westBankBaseAddr = aie_array_base_address + (westCoreIndex * AIE_ARRAY_TILE_STRIDE); // North Tile uint32_t northCoreIndex = ((AIE_ARRAY_ROW_WIDTH * colNum) + (rowNum + 1)); northBankBaseAddr = aie_array_base_address + (northCoreIndex * AIE_ARRAY_TILE_STRIDE); // East Tile uint32_t eastCoreIndex = ((rowNum - 1) % 2) ? ((AIE_ARRAY_ROW_WIDTH * (colNum + 1)) + rowNum) : coreIndex; eastBankBaseAddr = aie_array_base_address + (eastCoreIndex * AIE_ARRAY_TILE_STRIDE); } /******************************************************************************/ Binary::Address_t VersalImageHeader::GetAieEngineGlobalAddress(Binary::Address_t elfAddr) { Binary::Address_t globalAddr = elfAddr; if (globalAddr < 0x20000) { globalAddr += coreBaseAddr + 0x20000; } else if (globalAddr < 0x40000) { globalAddr -= 0x20000; if (globalAddr < 0x8000) { globalAddr += southBankBaseAddr; } else if (globalAddr < 0x10000) { globalAddr += westBankBaseAddr - 0x8000; } else if (globalAddr < 0x18000) { globalAddr += northBankBaseAddr - 0x10000; } else { globalAddr += eastBankBaseAddr - 0x18000; } } return globalAddr; } /******************************************************************************/ uint32_t VersalImageHeader::CheckAieEngineDataMemoryBoundary(Binary::Address_t globalAddr, Binary::Length_t pSize) { Binary::Address_t startAddr = globalAddr; Binary::Address_t endAddr; uint64_t spillSize = 0; if (startAddr < 0x40000) { startAddr -= 0x20000; endAddr = startAddr + pSize - 1; if (((startAddr >= 0 && startAddr < 0x8000) && (endAddr >= 0 && endAddr < 0x8000)) || ((startAddr >= 0x8000 && startAddr < 0x10000) && (endAddr >= 0x8000 && endAddr < 0x10000)) || ((startAddr >= 0x10000 && startAddr < 0x18000) && (endAddr >= 0x10000 && endAddr < 0x18000)) || ((startAddr >= 0x18000 && startAddr < 0x20000) && (endAddr >= 0x18000 && endAddr < 0x20000))) { // do nothing } else { if (startAddr < 0x8000) { spillSize = endAddr + 1 - 0x8000; } else if (startAddr < 0x10000) { spillSize = endAddr + 1 - 0x10000; } else if (startAddr < 0x18000) { spillSize = endAddr + 1 - 0x18000; } else { spillSize = endAddr + 1 - 0x20000; } } } return spillSize; } /******************************************************************************/ void VersalImageHeader::SetLoadAndExecAddress(PartitionHeader* partHdr) { if (destCpu == DestinationCPU::AIE) { // Extract column and row numbers from elf file name (elfname__.elf) // Example: test_2_4.elf -> AIE core with column-2 and row-4 std::string temp = StringUtils::RemoveExtension(StringUtils::BaseName(Filename)); uint32_t colNum = std::stoi(temp.substr((temp.length() - 3), 1)); uint32_t rowNum = std::stoi(temp.substr((temp.length() - 1), 1)); /* AIE Tile details in the form of [ColumnNum (16-bits) | RowNum(16-bits)] to be put into Exec Address Lo field in case of AIE partition */ uint64_t aieTileDetails = (colNum << 16) | (rowNum); /* AIE Tile details in Exec address in case of AIE partitions Load address & execution address will be same for AIE elfs, so no need of separate exec addr field*/ //partHdr->execAddress = GetAieEngineGlobalAddress((Binary::Address_t)elf.GetStartUpAddress()); partHdr->execAddress = aieTileDetails; CalculateAieEngineBaseAddress(colNum, rowNum); partHdr->loadAddress = GetAieEngineGlobalAddress(0); } } /******************************************************************************/ std::list VersalImageHeader::ParseAieJson(const char * filename) { std::list core_list; cJSON *Jfile = parse_file(filename); cJSON *JsonStr = cJSON_GetObjectItem(Jfile, "ActiveCores"); int active_cores = cJSON_GetArraySize(JsonStr); for (int core_no = 0; core_no < active_cores; core_no++) { cJSON *core_array = cJSON_GetArrayItem(JsonStr, core_no); auto arrayStr = StringUtils::Split_jsonString((std::string) cJSON_Print(core_array)); auto key = StringUtils::Trim_quotes(arrayStr.first); auto value = StringUtils::Trim_quotes(arrayStr.second); //auto path = "/Release/" + key; //path_full.push_back(value + path); core_list.push_back(key); } return core_list; } /******************************************************************************/ CdoCommandHeader* CdoCmdCdoEnd(void) { CdoCommandHeader* cdoCmd = new CdoCommandHeader; cdoCmd->reserved = 0x00; cdoCmd->length = 0x0; cdoCmd->handler_id = 1; cdoCmd->cmd_id = CdoCmds::END; LOG_TRACE("CDO_CMD_END"); return cdoCmd; } /******************************************************************************/ CdoSsitSlaves* CdoCmdWriteSsitSyncSlaves(uint8_t mask) { CdoSsitSlaves* cdoCmd = new CdoSsitSlaves; cdoCmd->header.reserved = 0x00; cdoCmd->header.length = 0x2; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::SSIT_SYNC_SLAVES; cdoCmd->mask = mask; cdoCmd->timeout_ms = 0xFFFF; LOG_TRACE("CDO_CMD_SSIT_SYNC_SLAVES - %d, %x", cdoCmd->mask, cdoCmd->timeout_ms); return cdoCmd; } /******************************************************************************/ CdoSsitSlaves* CdoCmdWriteSsitWaitSlaves(uint32_t mask) { CdoSsitSlaves* cdoCmd = new CdoSsitSlaves; cdoCmd->header.reserved = 0x00; cdoCmd->header.length = 0x2; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::SSIT_WAIT_SLAVES; cdoCmd->mask = mask; cdoCmd->timeout_ms = 0xFFFF; LOG_TRACE("CDO_CMD_SSIT_WAIT_SLAVES - %d, %x", cdoCmd->mask, cdoCmd->timeout_ms); return cdoCmd; } /******************************************************************************/ CdoCommandWriteKeyhole* CdoCmdWriteKeyHole(uint32_t size, SlrId::Type slr_index) { uint8_t index = slr_index; if (slr_index == 4) { index = 0; } CdoCommandWriteKeyhole* cdoCmd = new CdoCommandWriteKeyhole; cdoCmd->header.reserved = 0x00; cdoCmd->header.length = 0xff; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::WRITE_KEYHOLE; cdoCmd->length = (size / 4) + 3; /* +3 to accomodate the address lengths and keyhole size*/ cdoCmd->hi_address = (slr_sbi_base_array[index] >> 32) & 0xFFFFFFFF; cdoCmd->lo_address = slr_sbi_base_array[index] & 0xFFFFFFFF; cdoCmd->keyhole_size = SBI_KEYHOLE_SIZE / 4; LOG_TRACE(" CDO_CMD_WRITE_KEYHOLE: Address-0x%llx, Length-0x%lx (words)", slr_sbi_base_array[index], cdoCmd->length); return cdoCmd; } /******************************************************************************/ CdoCommandNop* CdoCmdNoOperation(size_t size) { CdoCommandNop* cdoCmd = new CdoCommandNop; uint8_t length = size - CDO_CMD_NOP_SIZE; cdoCmd->header.reserved = 0x00; /* If 1 word needs to be ignored, then no need to add length and payload */ cdoCmd->header.length = length / CDO_CMD_NOP_SIZE; cdoCmd->header.handler_id = 1; cdoCmd->header.cmd_id = CdoCmds::NOP; LOG_TRACE(" CDO_CMD_NOP - %d", cdoCmd->header.length + 1); return cdoCmd; } /******************************************************************************/ bool IsCdoCmdEndFound(const uint8_t* buffer, size_t size) { bool status = false; uint32_t end_word = buffer[size - sizeof(CdoCommandHeader)]; if (end_word == CDO_CMD_END) { status = true; } return status; } /******************************************************************************/ bool IsCdoFile(uint32_t value) { if ((value == 0x584c4e58) || (value == 0x584e4c58) || (value == 0x004f4443) || (value == 0x43444f00)) { return true; } return false; } /******************************************************************************/ void CompareCDOSequences(CdoSequence * user_cdo_seq, std::string golden_cdo_filename, std::string user_cdo_filename) { cdoseq_extract_writes(user_cdo_seq); uint32_t * golden_value = NULL; uint32_t * user_value = NULL; int pos_plus_neg_itr = 2; struct stat f_stat; bool found = false; bool golden_element_found = false; std::string golden_cdo; std::vector golden_cdo_write; for (int i = 0; i < pos_plus_neg_itr; i++) { golden_cdo.clear(); golden_cdo_write.clear(); golden_value = NULL; user_value = NULL; if (stat(golden_cdo_filename.c_str(), &f_stat) == 0) { found = true; } else { #ifdef _WIN32 std::string DS = "\\"; #else std::string DS = "/"; #endif char *s = getenv("HDI_APPROOT"); if (s != NULL && *s != '\0') { if (i == 0) { golden_cdo = s + DS + "data" + DS + "bootgen" + DS + golden_cdo_filename + "_positive.cdo"; } else { golden_cdo = s + DS + "data" + DS + "bootgen" + DS + golden_cdo_filename + "_negative.cdo"; } if (stat(golden_cdo.c_str(), &f_stat) == 0) { found = true; } } } if (!found) { LOG_ERROR("Cannot find golden CDO : %s", golden_cdo.c_str()); } CdoSequence * golden_cdo_seq = NULL; golden_cdo_seq = cdoseq_load_cdo(golden_cdo.c_str()); if (golden_cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file : %s", golden_cdo.c_str()); } if(found) { LINK * l = golden_cdo_seq->cmds.next; while (l != &golden_cdo_seq->cmds) { CdoCommand * golden_cmd = all2cmds(l); l = l->next; golden_value = (uint32_t *)golden_cmd->buf; LINK * U = user_cdo_seq->cmds.next; while (U != &user_cdo_seq->cmds) { CdoCommand * user_cmd = all2cmds(U); U = U->next; user_value = (uint32_t *)user_cmd->buf; if ((golden_cmd->dstaddr == user_cmd->dstaddr) && (*golden_value == *user_value)) { golden_element_found = true; break; } } if ((i == 0) && (golden_element_found == false)) { golden_cdo_write.push_back(golden_cmd->dstaddr); golden_cdo_write.push_back(*golden_value); } else if ((i != 0) && golden_element_found == true) { golden_cdo_write.push_back(golden_cmd->dstaddr); golden_cdo_write.push_back(*golden_value); } golden_element_found = false; } if (golden_cdo_write.size() != 0) { LOG_MSG("\n"); if (i == 0) { LOG_WARNING("User Cdo %s has missing write commands with below address and value.\n", user_cdo_filename.c_str()); } else { LOG_WARNING("User Cdo %s has invalid write commands with below address and value.\n", user_cdo_filename.c_str()); } for (size_t itr = 0; itr < golden_cdo_write.size(); itr+=2) { LOG_MSG(" Address = 0x%x ; Value = 0x%x", golden_cdo_write[itr], golden_cdo_write[itr + 1]); } } } found = false; } } /******************************************************************************/ bool IsCdoFile(std::string file) { std::ifstream stream(file.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read file - %s ", (file.c_str())); } std::string line; getline(stream, line); if ((line.find("Xilinx ASCII NPI Deviceimage") != std::string::npos) || (line.find("Xilinx ASCII PSAXIMM Deviceimage") != std::string::npos) || (line.find("version") != std::string::npos)) { return true; } else { FILE *binFile = fopen(file.c_str(), "rb"); if (!binFile) { LOG_ERROR("Cannot read file %s", file.c_str()); } uint32_t value = 0; size_t result = fread(&value, 1, 4, binFile); if (result == 4) { if ((value == 0x584c4e58) || (value == 0x584e4c58) || (value == 0x004f4443) || (value == 0x43444f00)) { return true; } } fclose(binFile); } return false; } /******************************************************************************/ SlrPdiType GetSlrType(SlrPdiInfo* slr) { if (IsCdoFile(slr->file)) { return SlrPdiType::MASTER_CDO; } else { return SlrPdiType::BOOT; } } /******************************************************************************/ uint8_t GetTotalSlrCount(std::list slrPdi) { uint8_t cnt = 0; for (std::list::iterator slr_id = slrPdi.begin(); slr_id != slrPdi.end(); slr_id++) { if (!IsCdoFile((*slr_id)->file)) { cnt++; } } return cnt; } /******************************************************************************/ bool SortByIndex(SlrPdiInfo* A, SlrPdiInfo* B) { return (A->index < B->index); } /******************************************************************************/ /* Total SLR boot partition: +-------------------+ | CDO Header | CDO header size +-------------------+ + | | WRITE KEYHOLE CDO command size | SLR1 PDI | + | | SLR1 PDI size +-------------------+ + | SYNC | SYNC CDO command size +-------------------+ + | | WRITE KEYHOLE CDO command size | SLR2 PDI | + | | SLR2 PDI size +-------------------+ + | SYNC | SYNC CDO command size +-------------------+ + | | WRITE KEYHOLE CDO command size | SLR3 PDI | + | | SLR3 PDI size +-------------------+ + | SYNC | SYNC CDO command size +-------------------+ + | NoC Freq & | | reconfig | NoC CDO size | CDO | +-------------------+ + | SYNC | SYNC CDO command size +-------------------+ */ void VersalImageHeader::CreateSlrBootPartition(BootImage& bi) { LOG_INFO("Creating SLR Boot CDO partition"); if ((slrBootPdiInfo.size() == 1) && GetSlrType(slrBootPdiInfo.front()) == MASTER_CDO) { SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* partHdr = new VersalPartitionHeader(this, 0); partHdr->execState = 0; partHdr->elfEndianess = 0; partHdr->firstValidIndex = true; uint8_t* cdo_buffer = NULL; size_t size = 0; const char* cdo_filename = slrBootPdiInfo.front()->file.c_str(); CdoSequence * cdo_seq; cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file"); } if (bi.overlayCDO && cdooverlay_apply(cdo_seq, (CdoOverlayInfo *)(bi.overlayCDO))) { LOG_ERROR("Error applying overlay CDO file : %s", cdo_filename); } cdo_buffer = (uint8_t*)cdoseq_to_binary(cdo_seq, &size, 0); partHdr->partitionSize = size; partHdr->partition = new VersalPartition(partHdr, cdo_buffer, size); partitionHeaderList.push_back(partHdr); delete cdo_buffer; delete cdoHeader; cdoSections.clear(); } else { uint32_t p_offset = 0; uint64_t size = 0; uint8_t slr_cnt = 0; /* Add CDO Header */ cdoHeader = new VersalCdoHeader; cdoHeader->remaining_words = CDO_REMAINING_WORDS; cdoHeader->id_word = CDO_IDENTIFICATION; /* CDO */ cdoHeader->version = CDO_VERSION; /* Version - 2.0 */ cdoHeader->length = 0; cdoHeader->checksum = 0; size += sizeof(VersalCdoHeader); uint8_t* p_buffer = new uint8_t[size]; memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); p_offset += sizeof(VersalCdoHeader); slrBootPdiInfo.sort(SortByIndex); num_of_slrs = GetTotalSlrCount(slrBootPdiInfo); char * do_ssit_check = getenv("BOOTGEN_DO_SSIT_NOC_CHECK"); bool master_cdo_verified = 0; std::string device_name = ""; if (do_ssit_check != NULL) { switch (bi.bifOptions->idCode) { case 0x04d24093: /* h10 */ case 0x14d24093: //device_name = "xcvp1202"; break; case 0x04d08093: /* h20 */ case 0x14d08093: device_name = "xcvp1502"; break; case 0x04d2c093: /* h30 */ case 0x14d2c093: break; case 0x04d10093: /* h40 */ case 0x14d10093: device_name = "xcvp1702"; break; case 0x04d14093: /* h50 */ case 0x14d14093: device_name = "xcvp1802"; break; default: LOG_WARNING("Skipping NoC configuration verification for the SSIT device. Device IDCODE 0x%08x ", bi.bifOptions->idCode); } } /* Add CDO Write Keyhole commands */ for (std::list::iterator slr_id = slrBootPdiInfo.begin(); slr_id != slrBootPdiInfo.end(); slr_id++) { uint32_t file_size = 0; uint32_t pad_size = 0; std::ifstream stream((*slr_id)->file.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read file - %s ", (*slr_id)->file.c_str()); } if (GetSlrType(*slr_id) == SlrPdiType::BOOT) { slr_cnt++; ByteFile slr_boot_data((*slr_id)->file); file_size = slr_boot_data.len; pad_size = file_size + ((4 - (file_size & 3)) & 3); uint32_t bh_offset = 0; uint32_t ih_offset = ((VersalBootHeaderStructure *)(slr_boot_data.bytes))->imageHeaderByteOffset; /* Remove the 16-bytes of SMAP bus width from start of PDI */ uint32_t smap_data = (slr_boot_data.bytes[0]) + (slr_boot_data.bytes[1] << 8) + (slr_boot_data.bytes[2] << 16) + (slr_boot_data.bytes[3] << 24); if ((smap_data == 0xDD000000) || (smap_data == 0x00DD0000) || (smap_data == 0x000000DD)) { bh_offset = (SMAP_BUS_WIDTH * 4); file_size -= (SMAP_BUS_WIDTH * 4); pad_size -= (SMAP_BUS_WIDTH * 4); ih_offset -= (SMAP_BUS_WIDTH * 4); } uint32_t p1_size = ih_offset, p2_size = file_size - p1_size; //if (getenv("BOOTGEN_SPLIT_SSIT_SLAVE_BOOT_PDI") != NULL) { pad_size = p1_size + ((4 - (p1_size & 3)) & 3); } if ((device_name != "") && (do_ssit_check != NULL)) { /* Get the partition offsets from the PDI */ uint32_t partition_offset = 0; uint32_t partition_size = 0; //VersalBootHeaderStructure* bH = (VersalBootHeaderStructure*)(slr_boot_data.bytes); uint32_t *id_offset = (uint32_t *)(slr_boot_data.bytes + bh_offset + 0x4); if (*id_offset == 0x584c4e58) { uint32_t *ih_byte_offset = (uint32_t *)(slr_boot_data.bytes + bh_offset + 0xb4); VersalImageHeaderTableStructure* iHT = (VersalImageHeaderTableStructure*)(slr_boot_data.bytes + *ih_byte_offset); size_t offset = iHT->firstPartitionHeaderWordOffset * 4; offset += sizeof(VersalPartitionHeaderTableStructure); for (uint8_t index = 1; index < iHT->partitionTotalCount; index++) { VersalPartitionHeaderTableStructure* pHT = (VersalPartitionHeaderTableStructure*)(slr_boot_data.bytes + offset); if (((pHT->partitionAttributes >> vphtPartitionTypeShift) & vphtPartitionTypeMask) == PartitionType::CONFIG_DATA_OBJ) { partition_size = pHT->totalPartitionLength * 4; partition_offset = pHT->partitionWordOffset * 4; break; } offset += sizeof(VersalPartitionHeaderTableStructure); } CdoSequence* cdo_seq = decode_cdo_binary(slr_boot_data.bytes + partition_offset, partition_size); if (cdo_seq == NULL) { LOG_WARNING("Cannot decode binary cdo data for slr %d, skipping verification of NoC configuration", (*slr_id)->index); } else { std::string golden_cdo_filename = device_name + "_boot" + std::to_string((*slr_id)->index); CompareCDOSequences(cdo_seq, golden_cdo_filename, (*slr_id)->file); //cdocmd_delete_sequence(cdo_seq); } } } /* For DMA alignment - add nop commands to align it to 128-bit (16-byte) */ size_t pad_bytes = ((16 - ((p_offset + CDO_CMD_WRITE_KEYHOLE_SIZE) & 15)) & 15); size += (CDO_CMD_WRITE_KEYHOLE_SIZE + pad_size + pad_bytes); p_buffer = (uint8_t*)realloc(p_buffer, size); if (pad_bytes != 0) { CdoCommandNop* cdoCmd = CdoCmdNoOperation(pad_bytes); LOG_TRACE("NOP - 0x%x", p_offset); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE); p_offset += CDO_CMD_NOP_SIZE; if (cdoCmd->header.length > 0) { memset(p_buffer + p_offset, 0, cdoCmd->header.length * sizeof(uint32_t)); p_offset += (cdoCmd->header.length * sizeof(uint32_t)); } } /* Add Write Key Hole command with SLR Boot PDI data */ CdoCommandWriteKeyhole* cdoCmd = CdoCmdWriteKeyHole(pad_size, (*slr_id)->index); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_WRITE_KEYHOLE_SIZE); p_offset += CDO_CMD_WRITE_KEYHOLE_SIZE; { memcpy(p_buffer + p_offset, slr_boot_data.bytes + bh_offset, p1_size); p_offset += p1_size; if ((pad_size - p1_size) != 0) { memset(p_buffer + p_offset, 0, pad_size - p1_size); p_offset += pad_size - p1_size; } /* Add SSIT Sync Slave command */ size += sizeof(CdoSsitSlaves); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoSsitSlaves *ssit_sync_slaves_cmd = CdoCmdWriteSsitSyncSlaves(1 << ((*slr_id)->index - 1) & 0xFF); memcpy(p_buffer + p_offset, ssit_sync_slaves_cmd, sizeof(CdoSsitSlaves)); p_offset += sizeof(CdoSsitSlaves); delete ssit_sync_slaves_cmd; /* Add part 2 write keyhole*/ pad_size = p2_size + ((4 - (p2_size & 3)) & 3); pad_bytes = ((16 - ((p_offset + CDO_CMD_WRITE_KEYHOLE_SIZE) & 15)) & 15); size += (CDO_CMD_WRITE_KEYHOLE_SIZE + pad_size + pad_bytes); p_buffer = (uint8_t*)realloc(p_buffer, size); if (pad_bytes != 0) { CdoCommandNop* cdoCmd = CdoCmdNoOperation(pad_bytes); LOG_TRACE("NOP - 0x%x", p_offset); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE); p_offset += CDO_CMD_NOP_SIZE; if (cdoCmd->header.length > 0) { memset(p_buffer + p_offset, 0, cdoCmd->header.length * sizeof(uint32_t)); p_offset += (cdoCmd->header.length * sizeof(uint32_t)); } } CdoCommandWriteKeyhole* cdoCmd2 = CdoCmdWriteKeyHole(pad_size, (*slr_id)->index); memcpy(p_buffer + p_offset, cdoCmd2, CDO_CMD_WRITE_KEYHOLE_SIZE); p_offset += CDO_CMD_WRITE_KEYHOLE_SIZE; memcpy(p_buffer + p_offset, slr_boot_data.bytes + ih_offset + (SMAP_BUS_WIDTH * 4), p2_size); p_offset += p2_size; if ((pad_size - p2_size) != 0) { memset(p_buffer + p_offset, 0, pad_size - p2_size); p_offset += pad_size - p2_size; } delete cdoCmd2; } delete cdoCmd; /* Add SSIT Wait Slave command */ size += sizeof(CdoSsitSlaves); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoSsitSlaves *ssit_wait_slaves_cmd = CdoCmdWriteSsitWaitSlaves(1 << ((*slr_id)->index - 1)); memcpy(p_buffer + p_offset, ssit_wait_slaves_cmd, sizeof(CdoSsitSlaves)); p_offset += sizeof(CdoSsitSlaves); delete ssit_wait_slaves_cmd; if (slr_cnt == num_of_slrs) { /* Add SSIT Sync Slave command */ size += sizeof(CdoSsitSlaves); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoSsitSlaves *ssit_sync_slaves_cmd = CdoCmdWriteSsitSyncSlaves(((1 << num_of_slrs) - 1) & 0xFF); memcpy(p_buffer + p_offset, ssit_sync_slaves_cmd, sizeof(CdoSsitSlaves)); p_offset += sizeof(CdoSsitSlaves); delete ssit_sync_slaves_cmd; } if (bi.options.GetDumpOption() != DumpOption::SLAVE_PDIS) { remove ((*slr_id)->file.c_str()); } } else if (GetSlrType(*slr_id) == SlrPdiType::MASTER_CDO) { /* Add Master Boot NPI and NoC freq CDO commands by parsing the CDO file */ const char* cdo_filename = (*slr_id)->file.c_str(); CdoSequence* cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file : %s", cdo_filename); } if (bi.overlayCDO && cdooverlay_apply(cdo_seq, (CdoOverlayInfo *)(bi.overlayCDO))) { LOG_ERROR("Error applying overlay CDO file : %s", cdo_filename); } if ((master_cdo_verified == 0) && (device_name != "") && (do_ssit_check != NULL)) { std::string golden_cdo_filename = device_name + "_boot0"; master_cdo_verified = 1; CompareCDOSequences(cdo_seq, golden_cdo_filename, (*slr_id)->file.c_str()); //cdocmd_delete_sequence(cdo_seq); cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file : %s", cdo_filename); } } size_t cdo_size = 0; uint8_t* cdo_buffer = (uint8_t*)cdoseq_to_binary(cdo_seq, &cdo_size, 0); file_size = cdo_size; if (file_size > sizeof(VersalCdoHeader)) { pad_size = file_size + ((4 - (file_size & 3)) & 3); file_size -= sizeof(VersalCdoHeader); pad_size -= sizeof(VersalCdoHeader); } else { LOG_ERROR("Incorrect CDO length read from : %s", cdo_filename); } if (IsCdoCmdEndFound(cdo_buffer, file_size)) { file_size -= +sizeof(CdoCommandHeader); pad_size -= +sizeof(CdoCommandHeader); } size += pad_size; p_buffer = (uint8_t*)realloc(p_buffer, size); memcpy(p_buffer + p_offset, cdo_buffer + sizeof(VersalCdoHeader), file_size); if ((pad_size - file_size) != 0) { memset(p_buffer + p_offset + file_size, 0, pad_size - file_size); } delete[] cdo_buffer; p_offset += pad_size; if ((*slr_id)->index == slrBootPdiInfo.size()) { /* Add SSIT Sync Slave command */ size += sizeof(CdoSsitSlaves); p_buffer = (uint8_t*)realloc(p_buffer, size); /* Add SSIT Sync Slave command */ CdoSsitSlaves *ssit_sync_slaves_cmd = CdoCmdWriteSsitSyncSlaves(((1 << num_of_slrs) - 1) & 0xFF); memcpy(p_buffer + p_offset, ssit_sync_slaves_cmd, sizeof(CdoSsitSlaves)); p_offset += sizeof(CdoSsitSlaves); delete ssit_sync_slaves_cmd; } } } size += sizeof(CdoCommandHeader); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoCommandHeader* cmd_end = CdoCmdCdoEnd(); memcpy(p_buffer + p_offset, cmd_end, sizeof(CdoCommandHeader)); delete cmd_end; /* Update CDO header lengths and checksum */ cdoHeader->length = (size - sizeof(VersalCdoHeader)) / 4; cdoHeader->checksum = ~(cdoHeader->remaining_words + cdoHeader->id_word + cdoHeader->version + cdoHeader->length); memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* partHdr = new VersalPartitionHeader(this, 0); partHdr->execState = 0; partHdr->elfEndianess = 0; partHdr->firstValidIndex = true; partHdr->partitionSize = size; partHdr->partition = new VersalPartition(partHdr, p_buffer, size); partitionHeaderList.push_back(partHdr); delete[] p_buffer; delete cdoHeader; cdoSections.clear(); } } /******************************************************************************/ size_t GetActualChunkSize(SsitConfigSlrInfo* slr_info) { size_t num_bytes = 0; static bool chunk_size_info_printed = false; /* Default chunk size - 32KB */ uint64_t chunk_size = SSIT_CHUNK_SIZE; char * ssit_chunk_size = getenv("BOOTGEN_SSIT_CHUNK_SIZE"); if (ssit_chunk_size != NULL) { chunk_size = strtoull(ssit_chunk_size, NULL, 16); } if (!chunk_size_info_printed) { LOG_INFO("SSIT chunk size = 0x%x", chunk_size); chunk_size_info_printed = true; } for (std::vector::iterator slr_security_info = slr_info->security_info.begin(); slr_security_info != slr_info->security_info.end(); slr_security_info++) { if ((*slr_security_info)->partition_index == slr_info->partition_index && (*slr_security_info)->top_chunk_processed == false) { if ((*slr_security_info)->checksum != Checksum::None) { num_bytes = SHA3_LENGTH_BYTES; slr_info->partition_offset += num_bytes; (*slr_security_info)->top_chunk_processed = true; return num_bytes; } else if (((*slr_security_info)->encryption != Encryption::None) && ((*slr_security_info)->authentication != Authentication::None)) { num_bytes = sizeof(AuthCertificate4096Sha3PaddingStructure); /* Auth Certificate size is the same for all Algorithms in case of Versal */ num_bytes += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); slr_info->partition_offset += num_bytes; (*slr_security_info)->top_chunk_processed = true; return num_bytes; } else if ((*slr_security_info)->authentication != Authentication::None) { num_bytes = sizeof(AuthCertificate4096Sha3PaddingStructure); /* Auth Certificate size is the same for all Algorithms in case of Versal */ slr_info->partition_offset += num_bytes; (*slr_security_info)->top_chunk_processed = true; return num_bytes; } else if ((*slr_security_info)->encryption != Encryption::None) { num_bytes = (SECURE_HDR_SZ + AES_GCM_TAG_SZ); slr_info->partition_offset += num_bytes; (*slr_security_info)->top_chunk_processed = true; return num_bytes; } } } /* Create chunks such that each partition within a SLR PDI starts as a new chunk */ size_t partition_size = slr_info->partition_sizes.at(slr_info->partition_index); if((partition_size - slr_info->partition_offset) <= chunk_size) { /* If remaining bytes in partition are less than chunk size, create a chunk with remaining bytes */ num_bytes = partition_size - slr_info->partition_offset; if (slr_info->partition_index < (slr_info->partition_sizes.size() - 1)) { slr_info->partition_index++; slr_info->partition_offset = 0; } else { slr_info->partition_offset += num_bytes; } } else { /* If partition size is greater than chunk size, create a chunk with chunk size */ num_bytes = chunk_size; slr_info->partition_offset += num_bytes; } return num_bytes; } /******************************************************************************/ void VersalImageHeader::LogConfigSlrDetails(size_t chunk_num, uint8_t slr_num, size_t offset, size_t chunk_size, size_t sync_points) { SsitConfigSlrLog* log_details = new SsitConfigSlrLog; log_details->slr_num = slr_num; log_details->offset = offset; log_details->size = chunk_size; log_details->sync_points = sync_points; configSlrLog.push_back(log_details); } /******************************************************************************/ void VersalImageHeader::PrintConfigSlrSummary(void) { LOG_TRACE("Note: Offset in below table is from the start of the config CDO partition and not start of PDI"); LOG_TRACE("---------------------------------------------------------------"); LOG_TRACE(" SSIT Summary "); LOG_TRACE("---------------------------------------------------------------"); LOG_TRACE(" Chunks SLR Offset Size Cumulative Sync Points"); LOG_TRACE("---------------------------------------------------------------"); uint32_t index = 1; for (std::vector::iterator slr_info = configSlrLog.begin(); slr_info != configSlrLog.end(); slr_info++) { std::string slr = ((*slr_info)->slr_num == 4) ? "master" : ("slr-" + std::to_string((*slr_info)->slr_num)); LOG_TRACE("%4d %8s 0x%-8x 0x%-8x %3d", index++, slr.c_str(), (*slr_info)->offset, (*slr_info)->size, (*slr_info)->sync_points); } LOG_TRACE("---------------------------------------------------------------"); } /******************************************************************************/ /* SLR Slave config partition CDO with round robin chunking +--------------+--------------+--------------+--------------+ | SLR1 | SLR2 | SLR3 | Master SLR | +--------------+--------------+--------------+--------------+ | 1 | 2 (S) | 3 | | +--------------+--------------+--------------+--------------+ | 4 (S) (S) | | 5 | | +--------------+--------------+--------------+--------------+ | | | 6 | | +--------------+--------------+--------------+--------------+ | | | 7 | | +--------------+--------------+--------------+--------------+ | | | 8 (S) | 9 (S) | +--------------+--------------+--------------+--------------+ | | 10 (S) (S) | 11 | | +--------------+--------------+--------------+--------------+ | | - | 12 | | +--------------+--------------+--------------+--------------+ | | - | 13 | | +--------------+--------------+--------------+--------------+ | | - | 14 (S) | 15 (S) | +--------------+--------------+--------------+--------------+ */ void VersalImageHeader::CreateSlrConfigPartition(BootImage& bi) { size_t size = 0; size_t p_offset = 0; size_t common_sync_point = 0, current_sync_point = 0, last_sync_point = 0; size_t total_slr_chunk_size = 0; size_t master_file_size = 0; size_t slr_total_file_size = 0; uint32_t chunk_num = 1; bool master_slr_available = false; LOG_INFO("Creating SLR Config CDO partition"); /* CDO Header */ cdoHeader = new VersalCdoHeader; cdoHeader->remaining_words = CDO_REMAINING_WORDS; cdoHeader->id_word = CDO_IDENTIFICATION; /* CDO */ cdoHeader->version = CDO_VERSION; /* Version - 2.0 */ /* Populate length and checksum later, as we can't estimate the exact size of CDO */ cdoHeader->length = 0; cdoHeader->checksum = 0; size += sizeof(VersalCdoHeader); uint8_t* p_buffer = new uint8_t[size]; memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); p_offset += sizeof(VersalCdoHeader); /* Initialize the individual SLR config structures */ slrConfigPdiInfo.sort(SortByIndex); for (std::list::iterator slr_id = slrConfigPdiInfo.begin(); slr_id != slrConfigPdiInfo.end(); slr_id++) { SsitConfigSlrInfo* configSlr = new SsitConfigSlrInfo; configSlr->file = (*slr_id)->file; configSlr->index = (*slr_id)->index; configSlr->offset = 0; configSlr->size = 0; configSlr->sync_points = 0; configSlr->data = NULL; configSlr->partition_index = 0; configSlr->partition_offset = 0; configSlr->num_chunks = 0; configSlr->eof = false; configSlrsInfo.push_back(configSlr); if (configSlr->index ==SlrId::MASTER) { master_slr_available = true; } } /* Parse slave SLR config files to get SLR data, identify sync points, file sizes and get total file size */ ParseSlrConfigFiles(&slr_total_file_size); /* 1. Create DMA write keyhole command for chunk from each slave SLR in a round robin fashion. 2. Continue the above process till a sync point is found in the current chunk. 3. Once a sync point is reached for a slave SLRx, don't include this slave SLRx chunks in the round robin. 4. Continue the above steps for remaining slave SLRs. 5. Once all the slave SLRs reach a common sync point, create a master SLR chunk. 6. Master SLR chunk is data between two sync points (CDO_SSIT_SYNC_SLAVES_CMD). 7. Repeat the above steps, till all the sync points are processed or EOF for each slave SLR PDI. */ uint8_t master_index = 0; while (total_slr_chunk_size < slr_total_file_size) { for (std::vector::iterator slr_info = configSlrsInfo.begin(); slr_info != configSlrsInfo.end(); slr_info++) { /* Process slave SLR data only if it has not yet reached the common sync point */ if (((*slr_info)->sync_points == common_sync_point) && ((*slr_info)->index != SlrId::MASTER) && (last_sync_point == current_sync_point)) { /* Slave SLRs processing */ size_t chunk_size = GetActualChunkSize(*slr_info); if(chunk_size != 0) { (*slr_info)->num_chunks++; /* For DMA alignment - add nop commands to align it to 128-bit (16-byte) */ size_t pad_bytes = ((16 - ((p_offset + CDO_CMD_WRITE_KEYHOLE_SIZE) & 15)) & 15); size += (chunk_size + CDO_CMD_WRITE_KEYHOLE_SIZE + pad_bytes); p_buffer = (uint8_t*)realloc(p_buffer, size); if (pad_bytes != 0) { CdoCommandNop* cdoCmd = CdoCmdNoOperation(pad_bytes); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE); p_offset += CDO_CMD_NOP_SIZE; if (cdoCmd->header.length > 0) { memset(p_buffer + p_offset, 0, cdoCmd->header.length * sizeof(uint32_t)); p_offset += (cdoCmd->header.length * sizeof(uint32_t)); } } LOG_TRACE("Chunk-%d | SLR-%d", chunk_num, (*slr_info)->index); /* Check for sync points in the current chunk */ CheckSyncPointInChunk(*slr_info, chunk_size); LogConfigSlrDetails(chunk_num++, (((*slr_info)->index == 4) ? 0 : (*slr_info)->index), p_offset, chunk_size, (*slr_info)->sync_points); /* Add write keyhole command for slave SLRs and master config */ CdoCommandWriteKeyhole* cdoCmd = CdoCmdWriteKeyHole(chunk_size, (*slr_info)->index); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_WRITE_KEYHOLE_SIZE); delete cdoCmd; p_offset += CDO_CMD_WRITE_KEYHOLE_SIZE; memcpy(p_buffer + p_offset, (*slr_info)->data + (*slr_info)->offset, chunk_size); p_offset += chunk_size; total_slr_chunk_size += chunk_size; (*slr_info)->offset += chunk_size; } else { /* If EOF reached, don't consider this SLR for finding common sync points */ (*slr_info)->eof = true; } } /* Get the common sync point - sync point which all the slave SLRs have serviced */ current_sync_point = FindCurrentSyncPoint(); if ((last_sync_point != current_sync_point)) { if (master_slr_available) { /* Do not process any other SLR data, until the master data is processed */ if (((*slr_info)->index == SlrId::MASTER) && (master_file_size < (*slr_info)->size)) { size_t master_chunk_size = 0; /* Chunk size in master is different from the chunk size of slave SLR chunk sizes Master SLRs chunk size is data size between two sync points (CDO_SSIT_SYNC_SLAVES_CMD )in Master SLR CDO */ (*slr_info)->num_chunks++; const char* cdo_filename = (*slr_info)->file.c_str(); CdoSequence * master_cdo_seq; master_cdo_seq = cdoseq_load_cdo(cdo_filename); CheckIdsInCdo(master_cdo_seq, bi.options.IsVersalNetSeries(), cdo_filename); if (master_cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file"); } if (bi.overlayCDO && cdooverlay_apply(master_cdo_seq, (CdoOverlayInfo *)(bi.overlayCDO))) { LOG_ERROR("Error applying overlay CDO file : %s", cdo_filename); } size_t part_size = 0; /* Pass the complete CDO sequence and SYNC point index */ /* If SYNC point 1 is passed, it will extract the data between start & 1st SSIT_SYNC_SLAVES command in RCDO If SYNC point 2 is passed, it will extract the data between 1st & 2nd SSIT_SYNC_SLAVES command in RCDO */ CdoSequence* part_seq = cdoseq_extract_cdo_till_ssit_sync_slaves(master_cdo_seq, master_index + 1); uint8_t* part_data = (uint8_t*)cdoseq_to_binary(part_seq, &part_size, 0); size_t pad_bytes = 0; master_chunk_size = part_size; pad_bytes = ((16 - (p_offset & 15)) & 15); size += (master_chunk_size+ pad_bytes); p_buffer = (uint8_t*)realloc(p_buffer, size); /* For master SLR, just copy the CDO contents to chunk. No need to create seperate DMA commands like slave SLRs */ if (pad_bytes != 0) { CdoCommandNop* cdoCmd = CdoCmdNoOperation(pad_bytes); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE); p_offset += CDO_CMD_NOP_SIZE; if (cdoCmd->header.length > 0) { memset(p_buffer + p_offset, 0, cdoCmd->header.length * sizeof(uint32_t)); p_offset += (cdoCmd->header.length * sizeof(uint32_t)); } } LOG_TRACE("Chunk-%d | SLR-master", chunk_num); if(master_index < (*slr_info)->sync_addresses.size()) { master_index++; } LogConfigSlrDetails(chunk_num++, SlrId::MASTER, p_offset, master_chunk_size, master_index); /* As we strip the CDO header, we are replacing that with NOP commands to ensure other alignments are not disturbed for only the first chunk */ CdoCommandNop* cdoCmd = CdoCmdNoOperation(sizeof(VersalCdoHeader)); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_NOP_SIZE); memset(p_buffer + p_offset + CDO_CMD_NOP_SIZE, 0, sizeof(VersalCdoHeader) - CDO_CMD_NOP_SIZE); if (part_size > sizeof(VersalCdoHeader)) { memcpy(p_buffer + p_offset + sizeof(VersalCdoHeader), part_data + sizeof(VersalCdoHeader), part_size - sizeof(VersalCdoHeader)); } else { LOG_ERROR("Incorrect CDO length read from : %s", cdo_filename); } p_offset += (master_chunk_size); (*slr_info)->offset += (master_chunk_size); master_file_size += master_chunk_size; total_slr_chunk_size += master_chunk_size; last_sync_point++; if (current_sync_point == 0xFFFFFFFF) { break; } } } else { last_sync_point++; } } } common_sync_point = current_sync_point; if (current_sync_point == 0xFFFFFFFF) { break; } } size += sizeof(CdoCommandHeader); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoCommandHeader* cmd_end = CdoCmdCdoEnd(); memcpy(p_buffer + p_offset, cmd_end, sizeof(CdoCommandHeader)); /* Update CDO header lengths and checksum */ cdoHeader->length = (size - sizeof(VersalCdoHeader)) / 4; cdoHeader->checksum = ~(cdoHeader->remaining_words + cdoHeader->id_word + cdoHeader->version + cdoHeader->length); memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* partHdr = new VersalPartitionHeader(this, 0); partHdr->execState = 0; partHdr->elfEndianess = 0; partHdr->firstValidIndex = true; partHdr->partitionSize = size; partHdr->partition = new VersalPartition(partHdr, p_buffer, size); partitionHeaderList.push_back(partHdr); delete[] p_buffer; delete cmd_end; for (std::vector::iterator slr_info = configSlrsInfo.begin(); slr_info != configSlrsInfo.end(); slr_info++) { if ((*slr_info)->index != SlrId::MASTER) { LOG_TRACE("SSIT: total slr-%d chunks = %d", (*slr_info)->index, (*slr_info)->num_chunks); if (bi.options.GetDumpOption() != DumpOption::SLAVE_PDIS) { remove ((*slr_info)->file.c_str()); } } else { LOG_TRACE("SSIT: total master chunks = %d", (*slr_info)->num_chunks); } } PrintConfigSlrSummary(); } /******************************************************************************/ void GetPartitionOffsets(SsitConfigSlrInfo* slr_info, uint8_t* data, size_t size) { uint8_t num_of_sync_points = 0; bool info_display = true; VersalImageHeaderTableStructure* iHT = (VersalImageHeaderTableStructure*)data; size_t offset = iHT->firstPartitionHeaderWordOffset * 4; slr_info->partition_sizes.push_back(sizeof(VersalImageHeaderTableStructure) + (iHT->optionalDataSize * 4) + (iHT->totalMetaHdrLength * 4)); for (uint8_t index = 0; index < iHT->partitionTotalCount; index++) { VersalPartitionHeaderTableStructure* pHT = (VersalPartitionHeaderTableStructure*)(data + offset); /* TotalPartitionLength includes AC + partition + hashes if authenticated.*/ if (pHT->checksumWordOffset != 0) { slr_info->partition_sizes.push_back((pHT->totalPartitionLength * 4) + SHA3_LENGTH_BYTES); } else { slr_info->partition_sizes.push_back(pHT->totalPartitionLength * 4); } SsitConfigPartitionSecurityInfo* partition_security_info = new SsitConfigPartitionSecurityInfo; partition_security_info->partition_index = index + 1; partition_security_info->checksum = Checksum::None; partition_security_info->authentication = Authentication::None; partition_security_info->encryption = Encryption::None; partition_security_info->top_chunk_processed = false; if (pHT->checksumWordOffset != 0) { partition_security_info->checksum = Checksum::SHA3; } else if (pHT->authCertificateOffset != 0) { partition_security_info->authentication = Authentication::RSA; } if (pHT->partitionKeySource != KeySource::None) { partition_security_info->encryption = Encryption::AES; } slr_info->security_info.push_back(partition_security_info); offset += sizeof(VersalPartitionHeaderTableStructure); if (((pHT->partitionAttributes >> vphtPartitionTypeShift) & vphtPartitionTypeMask) == PartitionType::CONFIG_DATA_OBJ) { { std::string sync_addresses_filename = StringUtils::RemoveExtension(slr_info->file) + "_" + std::to_string(pHT->puid) + "_sync_offsets.txt"; std::ifstream offsetFile(sync_addresses_filename.c_str()); std::vector syncpt_offsets; if (!offsetFile) { offsetFile.close(); } else { LOG_TRACE("Reading SLR Config CDO Sync Addresses from - %s", sync_addresses_filename.c_str()); } while (offsetFile) { std::string word; offsetFile >> word; // If file vacant if (word == "") { return; } if (word == "sync_offsets") { while (offsetFile) { offsetFile >> word; uint32_t offset = std::stoi(word); syncpt_offsets.push_back(offset); } } } if(syncpt_offsets.size() != 0) syncpt_offsets.pop_back(); num_of_sync_points = syncpt_offsets.size(); //remove(sync_addresses_filename.c_str()); int num_secure_chunks = 0; uint64_t data_chunk = SECURE_32K_CHUNK; size_t offset_shift = 0; uint32_t partition_length = pHT->unencryptedPartitionLength * 4; uint32_t padLength = (partition_length % 16 != 0) ? 16 - (partition_length % 16) : 0; partition_length += padLength; if (pHT->authCertificateOffset != 0 || pHT->checksumWordOffset != 0) { data_chunk -= SHA3_LENGTH_BYTES; offset_shift += SHA3_LENGTH_BYTES; } if (pHT->partitionKeySource != KeySource::None) { data_chunk -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); offset_shift += SECURE_HDR_SZ + AES_GCM_TAG_SZ; } if (partition_length <= data_chunk) { // no chunking } else { num_secure_chunks = partition_length / data_chunk; if (partition_length % data_chunk != 0) { num_secure_chunks++; } } if (num_of_sync_points > 0) { if (info_display) { LOG_TRACE("SSIT_SYNC_MASTER command detected at following offsets:\n Count : 0x%X", num_of_sync_points); LOG_TRACE(" slr_%d:", slr_info->index); info_display = false; } for (int i = 0; i < num_of_sync_points; i++) { size_t offset = syncpt_offsets[i]; for (int i = 1; i < num_secure_chunks; i++) { if (offset > (data_chunk * i)) { offset += offset_shift; } } offset += (pHT->partitionWordOffset * 4); slr_info->sync_addresses.push_back(offset); LOG_TRACE(" offset = 0x%x", offset); } } } } } } /******************************************************************************/ void VersalImageHeader::ParseSlrConfigFiles(size_t* slr_total_file_size) { uint32_t slr_sync_points[4] = { 0, 0, 0, 0 }; uint32_t* syncpt_offsets = NULL; uint8_t num_of_sync_points = 0; for (std::vector::iterator slr_info = configSlrsInfo.begin(); slr_info != configSlrsInfo.end(); slr_info++) { if (IsCdoFile((*slr_info)->file)) { /* For CDO files - master CDO */ const char* cdo_filename = (*slr_info)->file.c_str(); CdoSequence * cdo_seq; cdo_seq = cdoseq_load_cdo(cdo_filename); if (cdo_seq == NULL) { LOG_ERROR("Error parsing CDO file - %s", (*slr_info)->file.c_str()); } search_for_sync_points(); (*slr_info)->data = (uint8_t*)cdoseq_to_binary(cdo_seq, &(*slr_info)->size, 0); num_of_sync_points = get_num_of_sync_points(); syncpt_offsets = get_slr_sync_point_offsets(); LOG_TRACE("SSIT_SYNC_SLAVES command detected at following offsets:\n Count : 0x%X", num_of_sync_points); slr_sync_points[0] = num_of_sync_points; for (int i = 0; i < num_of_sync_points; i++) { size_t offset = (*(syncpt_offsets + i) * 4); (*slr_info)->sync_addresses.push_back(offset); LOG_TRACE(" offset = 0x%x", offset); } /* As we strip the CDO HEADER, we are replacing that with NOP commands to ensure other alignments are not disturbed */ CdoCommandNop* cdoCmd = CdoCmdNoOperation(sizeof(VersalCdoHeader)); memcpy((*slr_info)->data, cdoCmd, CDO_CMD_NOP_SIZE); memset((*slr_info)->data + CDO_CMD_NOP_SIZE, 0, sizeof(VersalCdoHeader) - CDO_CMD_NOP_SIZE); delete syncpt_offsets; /* Add the size to accomodate the NOPs added at the start of each master chunk Since the master chunks are read using the cdoseq_to_binary, each chunk comes with a CDO header This CDO header is replaced with NOPs to not disturb the alignments of the rest of the commands in CDO No. of CDO headers replaced is equal to the number of master chunks which is equal to the number of sync points */ (*slr_info)->size += ((num_of_sync_points) * sizeof(VersalCdoHeader)); } else { /* For PDI files - slave PDIs */ std::ifstream fl((*slr_info)->file.c_str(), std::ios::binary); fl.seekg(0, std::ios::end); if (fl.bad() || fl.fail()) { LOG_ERROR("Cannot seek to end of file - %s", (*slr_info)->file.c_str()); } (*slr_info)->size = fl.tellg(); (*slr_info)->data = new uint8_t[(*slr_info)->size]; fl.seekg(0, std::ios::beg); fl.read((char*)(*slr_info)->data, (*slr_info)->size); fl.close(); GetPartitionOffsets((*slr_info), (*slr_info)->data, (*slr_info)->size); slr_sync_points[(*slr_info)->index] = (*slr_info)->sync_addresses.size(); num_of_slrs++; } *slr_total_file_size += (*slr_info)->size; } /* Check for mismatch in sync points between different slaves and master */ bool sync_point_mismatch_error = false; for (uint8_t i = 1; i <= num_of_slrs; i++) { if (slr_sync_points[i] != slr_sync_points[0]) { sync_point_mismatch_error = true; break; } } char * env_ss = getenv("BOOTGEN_SKIP_SSIT_SYNCPOINT_CHECK"); if (env_ss != NULL) { LOG_WARNING("BOOTGEN_SKIP_SSIT_SYNCPOINT_CHECK is enabled. Skipping the check for sync point mismatch across SLRs."); if (sync_point_mismatch_error) { LOG_WARNING("The number of SYNC commands are not same across slave SLRs and master SLR."); } } else { if (sync_point_mismatch_error) { LOG_WARNING("Set env variable BOOTGEN_SKIP_SSIT_SYNCPOINT_CHECK to 1, to skip the check for sync point mismatch across SLRs."); LOG_ERROR("The number of SYNC commands are not same across slave SLRs and master SLR."); } } } /******************************************************************************/ uint32_t VersalImageHeader::FindCurrentSyncPoint(void) { uint32_t temp = 0xFFFFFFFF; /* Check */ for (std::vector::iterator slr_info = configSlrsInfo.begin(); slr_info != configSlrsInfo.end(); slr_info++) { /* Don't check sync points in MASTER */ if ((*slr_info)->index != SlrId::MASTER) { if (((*slr_info)->sync_points < temp) && ((*slr_info)->eof != true)) { temp = (*slr_info)->sync_points; } } } return temp; } /******************************************************************************/ void VersalImageHeader::CheckSyncPointInChunk(SsitConfigSlrInfo* slr_info, size_t size) { /* Check if the current chunk has the identified sync point for the SLR If yes, increment the sync point. "sync_point" points to the no. of sync points processed */ for (uint32_t ix = 0; ix < slr_info->sync_addresses.size(); ix++) { if ((slr_info->sync_addresses[ix] >= slr_info->offset) && (slr_info->sync_addresses[ix] < (slr_info->offset + size))) { slr_info->sync_points++; LOG_TRACE(" sync point - %d",slr_info->sync_points); } } } /******************************************************************************/ void VersalImageHeader::SetSlrBootPartitions(std::list bootPdis) { slrBootPdiInfo = bootPdis; } /******************************************************************************/ void VersalImageHeader::SetSlrConfigPartitions(std::list configPdis) { slrConfigPdiInfo = configPdis; } /******************************************************************************/ void VersalImageHeader::SetWriteImageStorePartitions(ImageStorePdiInfo* imageStorePDIs) { imageStorePdiInfo = imageStorePDIs; } /******************************************************************************/ void VersalImageHeader::SetDpacm(DpaCM::Type type) { dpacm = type; } /******************************************************************************/ void VersalImageHeader::SetPufHdLocation(PufHdLoc::Type type) { pufHdLoc = type; } /******************************************************************************/ void SubSysImageHeader::Build(BootImage& bi, Binary& cache) { if (section != NULL) { bi.headers.push_back(section); bi.imageHeaderTable->metaHeaderLength += section->Length; } if (imgList.size() == 0) { LOG_ERROR("Partitions not specified in subsystem - %s", imageName.c_str()); } bool uid_updated = false; for (std::list::iterator image = imgList.begin(); image != imgList.end(); image++) { (*image)->Build(bi, cache); if(((*image)->GetImageId() != 0) && ((*image)->IsUidInfoFoundInCdo() == true) && (uid_updated == false)) { if (uniqueId == 0xFFFFFFFF) { uniqueId = (*image)->GetUniqueId(); } if (parentUniqueId == 0xFFFFFFFF) { parentUniqueId = (*image)->GetParentUniqueId(); } if (functionId == 0xFFFFFFFF) { functionId = (*image)->GetFunctionId(); } uid_updated = true; } if (!isPLPowerDomain) { isPLPowerDomain = (*image)->GetPLPowerDomainFlag(); } if (!isFullPowerDomain) { isFullPowerDomain = (*image)->GetFullPowerDomainFlag(); } if (!isLowPowerDomain) { isLowPowerDomain = (*image)->GetLowPowerDomainFlag(); } if (!isSystemPowerDomain) { isSystemPowerDomain = (*image)->GetSystemPowerDomainFlag(); } } if (subSysImageHeaderTable == NULL) { subSysImageHeaderTable = (VersalImageHeaderStructure*)section->Data; SetImageName(); SetImageHeaderAttributes(); SetPartitionHeaderOffset(0); SetMetaHdrRevokeId(bi.bifOptions->metaHdrAttributes.revokeId); SetMemCopyAddress(); SetImageHeaderIds(); } } /******************************************************************************/ void SubSysImageHeader::Link(BootImage &bi, SubSysImageHeader* nextHeader) { subSysImageHeaderTable = (VersalImageHeaderStructure*)section->Data; if (imgList.front()->GetPartitionHeaderList().front()->section != NULL) { SetPartitionHeaderOffset((uint32_t)imgList.front()->GetPartitionHeaderList().front()->section->Address); } SetDataSectionCount(); SetImageHeaderIds(); SetPCRMeasurementIndex(bi.options.IsVersalNetSeries()); SetPCRNumber(bi.options.IsVersalNetSeries()); SetChecksum(); } /******************************************************************************/ void SubSysImageHeader::SetPCRMeasurementIndex(bool versalnet) { if (versalnet) { subSysImageHeaderTable->pcrMeasurementIndex = GetPCRMeasurementIndex(); } else { subSysImageHeaderTable->pcrMeasurementIndex = 0x00; } } /******************************************************************************/ void SubSysImageHeader::SetPCRNumber(bool versalnet) { if (versalnet) { subSysImageHeaderTable->pcrNumber = GetPCRNumber(); } else { subSysImageHeaderTable->pcrNumber = 0x00; } } /******************************************************************************/ void SubSysImageHeader::SetChecksum(void) { subSysImageHeaderTable->ihChecksum = ComputeWordChecksum(subSysImageHeaderTable, sizeof(VersalImageHeaderStructure) - sizeof(subSysImageHeaderTable->ihChecksum) /* bytes*/); } /******************************************************************************/ void SubSysImageHeader::SetPartitionHeaderOffset(uint32_t addr) { subSysImageHeaderTable->partitionHeaderWordOffset = addr / sizeof(uint32_t); } /******************************************************************************/ void SubSysImageHeader::SetDataSectionCount(void) { subSysImageHeaderTable->dataSectionCount = 0; for (std::list::iterator imageItr = imgList.begin(); imageItr != imgList.end(); imageItr++) { subSysImageHeaderTable->dataSectionCount += (*imageItr)->NumPartitions(); } } /******************************************************************************/ void SubSysImageHeader::SetMetaHdrRevokeId(uint32_t id) { subSysImageHeaderTable->metaHdrRevokeId = id; } /******************************************************************************/ void SubSysImageHeader::SetImageHeaderIds(void) { subSysImageHeaderTable->imageId = imageId; subSysImageHeaderTable->uniqueId = (uniqueId != 0xFFFFFFFF) ? uniqueId : 0; subSysImageHeaderTable->parentUniqueId = (parentUniqueId != 0xFFFFFFFF) ? parentUniqueId : 0; subSysImageHeaderTable->functionId = (functionId != 0xFFFFFFFF) ? functionId : 0; } /******************************************************************************/ void SubSysImageHeader::SetImageHeaderAttributes(void) { if (delayLoad) { subSysImageHeaderTable->imageAttributes |= (1 << vihDelayLoadShift); } if (delayHandoff) { subSysImageHeaderTable->imageAttributes |= (1 << vihDelayHandoffShift); } if (memCopyAddr != 0xFFFFFFFFFFFFFFFF) { subSysImageHeaderTable->imageAttributes |= (1 << vihCopyToMemoryShift); } if (isFullPowerDomain) { subSysImageHeaderTable->imageAttributes |= (1 << vihLowPowerDomainShift); } if (isLowPowerDomain) { subSysImageHeaderTable->imageAttributes |= (1 << vihFullPowerDomainShift); } if (isSystemPowerDomain) { subSysImageHeaderTable->imageAttributes |= (1 << vihSystemPowerDomainShift); } if (isPLPowerDomain) { subSysImageHeaderTable->imageAttributes |= (1 << vihPLPowerDomainShift); } } /******************************************************************************/ void SubSysImageHeader::SetImageName(void) { for (uint32_t i = 0; iimageName[i] = imageName[i]; } } /******************************************************************************/ void SubSysImageHeader::SetMemCopyAddress(void) { if (memCopyAddr == 0xFFFFFFFFFFFFFFFF) { memCopyAddr = 0; } subSysImageHeaderTable->memcpyAddressLo = memCopyAddr; subSysImageHeaderTable->memcpyAddressHi = memCopyAddr >> 32; } /******************************************************************************/ uint64_t SubSysImageHeader::GetMemCopyAddress(void) { uint64_t mem_cpy_addr = 0; mem_cpy_addr = subSysImageHeaderTable->memcpyAddressHi; mem_cpy_addr = (mem_cpy_addr << 32) | (subSysImageHeaderTable->memcpyAddressLo); return mem_cpy_addr; } /******************************************************************************/ uint32_t SubSysImageHeader::GetPartitionHeaderOffset(void) { return subSysImageHeaderTable->partitionHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t SubSysImageHeader::GetDataSectionCount(void) { return subSysImageHeaderTable->dataSectionCount; } /******************************************************************************/ uint32_t SubSysImageHeader::GetImageHeaderAttributes(void) { return subSysImageHeaderTable->imageAttributes; } /******************************************************************************/ void SubSysImageHeader::SetSubSystemName(std::string name) { imageName = name; } /******************************************************************************/ void SubSysImageHeader::SetSubSystemId(uint32_t id) { imageId = id; } /******************************************************************************/ void SubSysImageHeader::SetSubSystemType(PartitionType::Type type) { imageType = type; } /******************************************************************************/ void SubSysImageHeader::SetDelayHandoffMode(bool flag) { delayHandoff = flag; } /******************************************************************************/ void SubSysImageHeader::SetDelayLoadMode(bool flag) { delayLoad = flag; } /******************************************************************************/ void SubSysImageHeader::SetSubSysMemCopyAddress(uint64_t addr) { memCopyAddr = addr; } /******************************************************************************/ uint64_t SubSysImageHeader::GetSubSysMemCopyAddress(void) { return memCopyAddr; } /******************************************************************************/ bool SubSysImageHeader::GetDelayLoadMode(void) { return delayLoad; } /******************************************************************************/ bool SubSysImageHeader::GetDelayHandoffMode(void) { return delayHandoff; } /******************************************************************************/ PartitionType::Type SubSysImageHeader::GetSubSystemType(void) { return imageType; } /******************************************************************************/ std::string SubSysImageHeader::GetSubSystemName(void) { return imageName; } /******************************************************************************/ uint32_t SubSysImageHeader::GetSubSystemId(void) { return imageId; } /******************************************************************************/ SubSysImageHeader::SubSysImageHeader(ImageBifOptions *imgOptions) { subSysImageHeaderTable = NULL; imageName = imgOptions->GetImageName(); imageId = imgOptions->GetImageId(); delayLoad = imgOptions->GetDelayLoad(); delayHandoff = imgOptions->GetDelayHandoff(); memCopyAddr = imgOptions->GetMemCopyAddress(); imageType = imgOptions->GetImageType(); uniqueId = imgOptions->GetUniqueId(); parentUniqueId = imgOptions->GetParentUniqueId(); functionId = imgOptions->GetFunctionId(); pcrNumber = imgOptions->GetPcrNumber(); pcrMeasurementIndex = imgOptions->GetPcrMeasurementIndex(); isFullPowerDomain = false; isLowPowerDomain = false; isSystemPowerDomain = false; isPLPowerDomain = false; std::string name = "ImageHeader " + imageName; uint32_t size = sizeof(VersalImageHeaderStructure); section = new Section(name, size); memset(section->Data, 0, size); imgList.clear(); num_of_images = 0; } /******************************************************************************/ SubSysImageHeader::SubSysImageHeader(std::ifstream& ifs) { VersalImageHeaderStructure importedSubSysHeaderTable; long pos = ifs.tellg(); ifs.read((char*)&importedSubSysHeaderTable, 4 * sizeof(uint32_t)); char buffer[4]; char name[256]; uint32_t i = 0; do { ifs.read(buffer, 4); name[i + 0] = buffer[0]; name[i + 1] = buffer[1]; name[i + 2] = buffer[2]; name[i + 3] = buffer[3]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } imageName = name; uint32_t size = sizeof(VersalImageHeaderStructure); ifs.seekg(pos); section = new Section("ImageHeader " + imageName, size); subSysImageHeaderTable = (VersalImageHeaderStructure*)section->Data; ifs.read((char*)subSysImageHeaderTable, size); imageId = subSysImageHeaderTable->imageId; uniqueId = subSysImageHeaderTable->uniqueId; parentUniqueId = subSysImageHeaderTable->parentUniqueId; functionId = subSysImageHeaderTable->functionId; delayLoad = ((subSysImageHeaderTable->imageAttributes >> vihDelayLoadShift) & vihDelayLoadMask); delayHandoff = ((subSysImageHeaderTable->imageAttributes >> vihDelayHandoffShift) & vihDelayHandoffMask); memCopyAddr = (uint64_t) (subSysImageHeaderTable->memcpyAddressLo) >> 32; memCopyAddr |= subSysImageHeaderTable->memcpyAddressHi; isPLPowerDomain = ((subSysImageHeaderTable->imageAttributes >> vihPLPowerDomainShift) & vihPLPowerDomainMask); isFullPowerDomain = ((subSysImageHeaderTable->imageAttributes >> vihFullPowerDomainShift) & vihFullPowerDomainMask); isLowPowerDomain = ((subSysImageHeaderTable->imageAttributes >> vihLowPowerDomainShift) & vihLowPowerDomainMask); isSystemPowerDomain = ((subSysImageHeaderTable->imageAttributes >> vihSystemPowerDomainShift) & vihSystemPowerDomainMask); pcrNumber = subSysImageHeaderTable->pcrNumber; pcrMeasurementIndex = subSysImageHeaderTable->pcrMeasurementIndex; /* Find the no. of image headers to be created */ num_of_images = 0; uint32_t num_of_sections = 0; uint32_t p_count = 0; if (subSysImageHeaderTable->dataSectionCount < 32) { p_count = subSysImageHeaderTable->dataSectionCount; } uint32_t p_offset = subSysImageHeaderTable->partitionHeaderWordOffset * sizeof(uint32_t); p_offset += 0x28; for (uint32_t i = 0; i < p_count; i++) { ifs.seekg(p_offset); ifs.read((char*)&num_of_sections, 4); if (num_of_sections != 0) { num_of_images++; } p_offset += sizeof(VersalPartitionHeaderTableStructure); } } /******************************************************************************/ void VersalImageHeader::CheckIdsInCdo(CdoSequence * seq, bool isVersalNetSeries, std::string cdo_filename) { LINK * l = seq->cmds.next; while (l != &seq->cmds) { CdoCommand * cmd = all2cmds(l); l = l->next; if(cmd->type == CdoCmdMarker) { char* marker_arch = (char*)cmd->buf; if (cmd->value == MARKER_ARCHITECTURE) { if (isVersalNetSeries && (strstr(marker_arch,"versalnet") == 0)) { LOG_WARNING("The architecture(%s) in '%s' does not match '-arch versalnet'", marker_arch, cdo_filename.c_str()); } else if(!isVersalNetSeries && ((strstr(marker_arch,"versalnet") != 0) || (strstr(marker_arch,"versal") == 0))) { LOG_WARNING("The architecture(%s) in '%s' does not match '-arch versal'", marker_arch, cdo_filename.c_str()); } } } if(cmd->type == CdoCmdPmInitNode) { imageId = u32le(cmd->id); if (cmd->value == 0) { SetPowerDomains((uint8_t*)cmd->buf,cmd->count); } } if(cmd->type == CdoCmdLdrSetImageInfo) { if (imageId == u32le(cmd->id)) { uniqueId = u32le(cmd->value); parentUniqueId = u32le(cmd->mask); functionId = u32le(cmd->count); uidInfoFoundInCdo = true; } break; } } } /******************************************************************************/ void VersalImageHeader::SetPowerDomains(uint8_t* buf, uint32_t count) { uint32_t id = 0; for (uint32_t index = 0; index < count ; index++) { id = ReadLittleEndian32(buf); switch (id) { case POWER_FPD: isIhFullPowerDomain = true; break; case POWER_LPD: isIhLowPowerDomain = true; break; case POWER_SPD: isIhSystemPowerDomain = true; break; case POWER_PLD: isIhPLPowerDomain = true; break; default: break; } buf += sizeof(uint32_t); } } /******************************************************************************/ void VersalImageHeader::CreateWriteImageStorePartition() { LOG_INFO("Creating Write Image Store CDO partition"); std::ifstream s(Filename.c_str()); if (!s) { LOG_ERROR("Cannot read file - %s ", Filename.c_str()); } ByteFile data(Filename); uint32_t p_size_pad = data.len + ((4 - (data.len & 3)) & 3); uint8_t* tempBuffer = new uint8_t[p_size_pad]; memcpy(tempBuffer, data.bytes, p_size_pad); size_t size = 0; size_t p_offset = 0; /* CDO Header */ cdoHeader = new VersalCdoHeader; cdoHeader->remaining_words = CDO_REMAINING_WORDS; cdoHeader->id_word = CDO_IDENTIFICATION; /* CDO */ cdoHeader->version = CDO_VERSION; /* Version - 2.0 */ /* Populate length and checksum later, as we can't estimate the exact size of CDO */ cdoHeader->length = 0; cdoHeader->checksum = 0; size += sizeof(VersalCdoHeader); uint8_t* p_buffer = new uint8_t[size]; memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); p_offset += sizeof(VersalCdoHeader); CdoCommandWriteImageStore* cdoCmd = new CdoCommandWriteImageStore; cdoCmd->header = 0x00ff070D; cdoCmd->length = (p_size_pad / 4) + 2; cdoCmd->id = imageStorePdiInfo->id; cdoCmd->data = new uint8_t[p_size_pad]; memset(cdoCmd->data, 0, p_size_pad); memcpy(cdoCmd->data, tempBuffer, p_size_pad); size += CDO_CMD_WRITE_IMAGE_STORE_SIZE; p_buffer = (uint8_t*)realloc(p_buffer, size); memcpy(p_buffer + p_offset, cdoCmd, CDO_CMD_WRITE_IMAGE_STORE_SIZE); p_offset += CDO_CMD_WRITE_IMAGE_STORE_SIZE; size += p_size_pad; p_buffer = (uint8_t*)realloc(p_buffer, size); memcpy(p_buffer + p_offset, cdoCmd->data, p_size_pad); p_offset += p_size_pad; size += sizeof(CdoCommandHeader); p_buffer = (uint8_t*)realloc(p_buffer, size); CdoCommandHeader* cmd_end = CdoCmdCdoEnd(); memcpy(p_buffer + p_offset, cmd_end, sizeof(CdoCommandHeader)); /* Update CDO header lengths and checksum */ cdoHeader->length = (size - sizeof(VersalCdoHeader)) / 4; cdoHeader->checksum = ~(cdoHeader->remaining_words + cdoHeader->id_word + cdoHeader->version + cdoHeader->length); memcpy(p_buffer, cdoHeader, sizeof(VersalCdoHeader)); SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* partHdr = new VersalPartitionHeader(this, imageStorePdiInfo->id); partHdr->execState = 0; partHdr->elfEndianess = 0; partHdr->firstValidIndex = true; partHdr->loadAddress = 0xFFFFFFFFFFFFFFFF; partHdr->execAddress = 0; partHdr->partitionSize = size; partHdr->partition = new VersalPartition(partHdr, p_buffer, size); partitionHeaderList.push_back(partHdr); } xilinx-bootgen-2024.2/imageheadertable-versal.h000077500000000000000000000453361475706442400215120ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _VERSAL_IMAGEHEADERTABLE_H_ #define _VERSAL_IMAGEHEADERTABLE_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable.h" #include "bootheader.h" extern "C" { #include "cdo-command.h" } class ImageBifOptions; class SubSysImageHeader; class BifOptions; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MAX_NUM_PARTITIONS_VERSAL 20 #define MAX_NUM_IMAGES_VERSAL 10 /* 128MB Linear QSPI range */ #define LQSPI_BASE_ADDR_VERSAL (0xC0000000) #define LQSPI_SIZE_VERSAL (0x8000000) #define LQSPI_RANGE_MASK_VERSAL (0x7FFFFFF) #define MAX_IHT_RESERVED_VERSAL 8 #define MAX_SLAVE_SLRS 3 #define CDO_COMMAND_SIZE 16 #define FPDI 0x46504449 #define PPDI 0x50504449 #define MASTER_PMC_BASE_ADDR 0xF0000000 #define SLR1_PMC_BASE_ADDR 0x108000000 #define SLR2_PMC_BASE_ADDR 0x110000000 #define SLR3_PMC_BASE_ADDR 0x118000000 #define PMC_SBI_BUF_ADDR 0xF2100000 #define SLR1_SBI_BUF_BASE_ADDR (SLR1_PMC_BASE_ADDR + (PMC_SBI_BUF_ADDR - MASTER_PMC_BASE_ADDR)) #define SLR2_SBI_BUF_BASE_ADDR (SLR2_PMC_BASE_ADDR + (PMC_SBI_BUF_ADDR - MASTER_PMC_BASE_ADDR)) #define SLR3_SBI_BUF_BASE_ADDR (SLR3_PMC_BASE_ADDR + (PMC_SBI_BUF_ADDR - MASTER_PMC_BASE_ADDR)) #define SBI_KEYHOLE_SIZE 0x10000 #define AIE_BASE_ADDR 0x20000000000 #define SSIT_CHUNK_SIZE 0x8000 typedef enum { vihImageOwnerShift = 3, vihImageOwnerMask = 0x7, vihCopyToMemoryShift = 6, vihCopyToMemoryMask = 0x1, vihDelayLoadShift = 7, vihDelayLoadMask = 0x1, vihDelayHandoffShift = 8, vihDelayHandoffMask = 0x1, vihLowPowerDomainShift = 9, vihLowPowerDomainMask = 0x1, vihFullPowerDomainShift = 10, vihFullPowerDomainMask = 0x1, vihSystemPowerDomainShift = 11, vihSystemPowerDomainMask = 0x1, vihPLPowerDomainShift = 12, vihPLPowerDomainMask = 0x1, } VersalIHAttributes; typedef enum { vihtSiliconRevisionIdCodeCheckShift = 0, vihtSiliconRevisionIdCodeCheckMask = 0x1, vihtImageCreatorIdShift = 1, vihtImageCreatorIdMask = 0x1F, vihtSecBootDeviceShift = 6, vihtSecBootDeviceMask = 0x3F, vihtDpacmEnableShift = 12, vihtDpacmEnableMask = 0x3, vihtPufHDLocationShift = 14, vihtPufHDLocationMask = 0x3, vihtIdCodeCheckShift = 16, vihtIdCodeCheckMask = 0x3, vNetihtEndofPDISyncShift = 18, vNetihtEndofPDISynckMask = 0x3, } VersalIHTAttributes; /* Version Updates : v1 : Initial versal support v2 : IHT,PHT sizes doubled v3 : Partition secure chunk size changed to 32k from 64k v4 : AAD support added for IHT : Hash placemnet updated during chunking Hash is included into the 32k secure chunk */ #define VERSION_v1_00_VERSAL 0x01030000 #define VERSION_v2_00_VERSAL 0x00020000 #define VERSION_v3_00_VERSAL 0x00030000 #define VERSION_v4_00_VERSAL 0x00040000 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ /* totalMetaHdrLength: Includes Authentication and encryption over head (excluding IHT and including AC) */ typedef struct { uint32_t version; // 0x0 uint32_t imageTotalCount; // 0x4 uint32_t firstImageHeaderWordOffset; // 0x8 uint32_t partitionTotalCount; // 0xc uint32_t firstPartitionHeaderWordOffset; // 0x10 uint32_t secondaryBootDeviceAddress; // 0x14 uint32_t idCode; // 0x18 uint32_t imageHeaderTableAttributes; // 0x1c uint32_t pdiId; // 0x20 uint32_t parentId; // 0x24 uint32_t identificationString; // 0x28 uint32_t headerSizes; // 0x2C uint32_t totalMetaHdrLength; // 0x30 uint32_t metaHdrSecureHdrIv[IV_LENGTH]; // 0x34 uint32_t metaHdrKeySource; // 0x40 uint32_t extendedIdCode; // 0x44 uint32_t headerAuthCertificateWordOffset; // 0x48 uint32_t metaHdrGreyOrBlackIV[IV_LENGTH]; // 0x4C uint32_t optionalDataSize; // 0x58 uint32_t reserved[MAX_IHT_RESERVED_VERSAL]; // 0x5C - 0x78 uint32_t ihtChecksum; // 0x7C } VersalImageHeaderTableStructure; typedef struct { uint32_t partitionHeaderWordOffset; // 0x00 uint32_t dataSectionCount; // 0x04 uint32_t metaHdrRevokeId; // 0x08 uint32_t imageAttributes; // 0x0C char imageName[16]; // 0x10 uint32_t imageId; // 0x20 uint32_t uniqueId; // 0x24 uint32_t parentUniqueId; // 0x28 uint32_t functionId; // 0x2C uint32_t memcpyAddressLo; // 0x30 uint32_t memcpyAddressHi; // 0x34 uint16_t pcrNumber; // 0x38 uint16_t pcrMeasurementIndex; // 0x3A uint32_t ihChecksum; // 0x3C } VersalImageHeaderStructure; typedef struct { uint32_t header; uint32_t length; uint32_t hi_address; uint32_t lo_address; uint8_t* data; } CdoCommandDmaWrite; typedef struct { uint32_t header; uint32_t length; uint32_t id; uint8_t* data; } CdoCommandWriteImageStore; #define CDO_CMD_WRITE_IMAGE_STORE_SIZE 12 typedef struct { uint8_t cmd_id; uint8_t handler_id; uint8_t length; uint8_t reserved; } CdoCommandHeader; struct CdoCmds { typedef enum { END, MASK_POLL, MASK_WRITE, WRITE, DELAY, DMA_WRITE, MASK_POLL_64, MASK_WRITE_64, WRITE_64, DMA_XFER, INIT_SEQ, CFI_READ, SET, WRITE_KEYHOLE, SSIT_SYNC_MASTER, SSIT_SYNC_SLAVES, SSIT_WAIT_SLAVES, NOP } Type; }; #define CDO_CMD_DMA_WRITE_SIZE 16 typedef struct { CdoCommandHeader header; uint32_t length; uint32_t hi_address; uint32_t lo_address; uint32_t keyhole_size; uint8_t* data; } CdoCommandWriteKeyhole; #define CDO_CMD_WRITE_KEYHOLE_SIZE 20 typedef struct { CdoCommandHeader header; uint32_t length; } CdoCommandNop; #define CDO_CMD_NOP_SIZE 4 typedef struct { uint32_t header; uint32_t value; } CdoCommandSync; typedef struct { CdoCommandHeader header; } CdoSsitSyncMaster; #define CDO_SSIT_SYNC_MASTER_CMD 0x0E010000 #define CDO_SSIT_SYNC_SLAVES_CMD 0x0F010200 #define CDO_CMD_END 0x00000100 #define CDO_IDENTIFICATION 0x004f4443 #define CDO_VERSION 0x00000200 #define CDO_REMAINING_WORDS 0x4 typedef struct { CdoCommandHeader header; uint32_t mask; uint32_t timeout_ms; } CdoSsitSlaves; typedef struct { uint32_t remaining_words; uint32_t id_word; uint32_t version; uint32_t length; uint32_t checksum; } VersalCdoHeader; typedef struct { uint32_t partition_index; Checksum::Type checksum; Authentication::Type authentication; Encryption::Type encryption; bool top_chunk_processed; } SsitConfigPartitionSecurityInfo; typedef struct { std::string file; /* SLR partition PDI/CDO file */ SlrId::Type index; /* SLR index - master, slr-1, slr-2 etc. */ uint8_t* data; /* SLR partition data */ size_t size; /* SLR partition size */ uint32_t offset; /* To track the offset of data pointer for packing next chunk */ std::vector sync_addresses; /* List of addresses for CDO_SSIT_SYNC_MASTER_CMD/CDO_SSIT_SYNC_SLAVES_CMD */ std::vector partition_sizes; /* Individual partition sizes of each SLR PDI */ uint32_t partition_index; /* To track current partition of SLR PDI to chunk and pack */ uint32_t partition_offset; /* To track current partition of SLR PDI to chunk and pack */ uint32_t sync_points; /* To track how many sync points are processed within SLR PDI */ uint32_t num_chunks; /* To track no of chunks created or processed */ std::vector security_info; bool eof; /* To track end of file for each SLR PDI */ } SsitConfigSlrInfo; typedef struct { uint8_t slr_num; size_t offset; size_t size; size_t sync_points; } SsitConfigSlrLog; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalImageHeaderTable : public ImageHeaderTable { public: VersalImageHeaderTable(); VersalImageHeaderTable(std::ifstream& ifs); ~VersalImageHeaderTable(); void Build(BootImage & bi, Binary & cache); void Link(BootImage & bi); void ValidateSecurityCombinations(Authentication::Type, Encryption::Type, Checksum::Type); void RealignSectionDataPtr(void); void SetImageHeaderTableVersion(uint32_t version); void SetHeaderTablesSize(); void SetImageCount(uint32_t count); void SetFirstImageHeaderOffset(uint32_t offset); void SetFirstPartitionHeaderOffset(uint32_t offset); void SetPartitionCount(uint32_t count); void SetBootDeviceAddress(uint32_t address); void SetIds(bool warnIdCode); void SetIdentificationString(bool bootloader); void SetImageHeaderTableAttributes(); void SetTotalMetaHdrLength(uint32_t size); void SetMetaHdrSecureHdrIv(uint8_t* iv); void SetMetaHdrKeySrc(KeySource::Type keyType, BifOptions* bifOptions); void SetMetaHdrGreyOrBlackIv(std::string); void SetHeaderAuthCertificateOffset(uint32_t offset); void SetReservedFields(void); void SetChecksum(void); void SetOptionalDataSize(void); void SetOptionalData(uint32_t*, uint32_t); void SetUserOptionalData(std::vector> optionalDataInfo, uint32_t hashTableSize); void SetXplmModulesData(BootImage& bi, uint32_t*, uint32_t); uint32_t GetImageHeaderTableVersion(void); uint32_t GetPartitionCount(void); uint32_t GetImageCount(void); uint32_t GetFirstImageHeaderOffset(void); uint8_t GetMaxNumOfPartitions(void) { return MAX_NUM_PARTITIONS_VERSAL; } uint32_t GetTotalMetaHdrLength(); void SetCreatorId(uint8_t id); void SetPdiId(uint32_t id); void SetParentId(uint32_t id); std::list subSysImageList; private: VersalImageHeaderTableStructure *iHTable; uint8_t creatorId; uint32_t parentId; uint32_t pdiId; uint32_t idCode; uint32_t extendedIdCode; uint8_t bootDevice; std::string kekIvFile; bool kekIvMust; bool bypassIdCode; bool prebuilt; DpaCM::Type dpacm; PufHdLoc::Type pufHDLoc; }; /******************************************************************************/ class VersalImageHeader : public ImageHeader { public: VersalImageHeader(std::string& filename); VersalImageHeader(uint8_t* data, uint64_t len); VersalImageHeader(std::ifstream& ifs, bool isBootloader); VersalImageHeader(std::ifstream& ifs, VersalImageHeaderStructure* importedIH, bool isBootloader, uint32_t index); ~VersalImageHeader(); void ImportElf(BootImage& bi); void Build(BootImage& bi, Binary& cache); void Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageheader); void SetMetaHdrRevokeId(uint32_t revocId); void ParseFileToImport(BootImage& bi); void ImportNpi(BootImage& bi); void ImportBuffer(BootImage &bi); void ImportBin(BootImage& bi); void ImportBit(BootImage& bi); void ImportCdoSource(BootImage& bi); void ImportCdo(BootImage& bi); uint8_t* DecodeCdo(std::string file, size_t* size); void ImportAieEngineElf(BootImage& bi); void CreateAieEnginePartition(BootImage& bi); uint64_t ImportAieEngineElfCdo(std::string); uint32_t CdoCmdDmaWrite(uint32_t pSize, uint64_t pAddr, uint8_t *databuffer); uint32_t CdoCmdWriteImageStore(uint32_t pSize, uint64_t id, uint8_t *databuffer); void SetLoadAndExecAddress(PartitionHeader *partHdr); std::list ParseAieJson(const char* filename); std::list GetAieFilesPath(std::string); Binary::Address_t GetAieEngineGlobalAddress(Binary::Address_t elfAddr); void CalculateAieEngineBaseAddress(uint32_t colNum, uint32_t rowNum); uint32_t CheckAieEngineDataMemoryBoundary(Binary::Address_t globalAddr, Binary::Length_t pSize); void CreateSlrBootPartition(BootImage& bi); void CreateSlrConfigPartition(BootImage& bi); void ParseCdos(BootImage& bi, std::vector filelist, uint8_t**, size_t*, bool); void ParseSlaveSlrConfigCdos(BootImage & bi, std::vector filelist, uint8_t **, size_t *, bool); //post-processing bool PostProcessCdo(const uint8_t* cdo_data, Binary::Length_t cdo_size); bool PostProcessCfi(const uint8_t* cdo_data, Binary::Length_t cdo_size); void SetPartitionHeaderOffset(uint32_t addr); void SetDataSectionCount(uint32_t cnt); void SetImageHeaderAttributes(); void SetImageName(void); void SetPartitionUid(uint32_t id); void SetEncryptionKeySrc(KeySource::Type type); void SetImageId(); void SetPartitionRevocationId(uint32_t id); void SetMemCopyAddr(); void SetChecksum(void); void SetAuthBlock(size_t blockSize, bool flag); void SetSlrBootPartitions(std::list); void SetSlrConfigPartitions(std::list); void SetWriteImageStorePartitions(ImageStorePdiInfo*); void SetDpacm(DpaCM::Type); void SetPufHdLocation(PufHdLoc::Type type); uint32_t GetPartitionHeaderOffset(void); uint32_t GetDataSectionCount(void); uint32_t GetImageHeaderAttributes(void); uint32_t GetPartitionUid(void); KeySource::Type GetEncryptionKeySrc(); uint32_t GetPartitionRevocationId(); DpaCM::Type GetDpacm(void); PufHdLoc::Type GetPufHdLocation(void); std::string GetKekIV(void); private: void ParseSlrConfigFiles(size_t* slr_total_file_size); void CheckSyncPointInChunk(SsitConfigSlrInfo* slr_info, size_t size); uint32_t FindCurrentSyncPoint(void); void CheckIdsInCdo(CdoSequence * cdo_seq, bool isVersalNetSeries, std::string cdo_filename); void SetPowerDomains(uint8_t* buf, uint32_t count); void CreateWriteImageStorePartition(); void LogConfigSlrDetails(size_t chunk_num, uint8_t slr_num, size_t offset, size_t chunk_size, size_t sync_points); void PrintConfigSlrSummary(void); uint64_t slr_total_file_size; std::vector configSlrsInfo; std::vector configSlrLog; VersalImageHeaderStructure *imageHeader; VersalCdoHeader* cdoHeader; uint64_t aie_array_base_address; Binary::Address_t coreBaseAddr; Binary::Address_t southBankBaseAddr; Binary::Address_t westBankBaseAddr; Binary::Address_t northBankBaseAddr; Binary::Address_t eastBankBaseAddr; protected: static std::list cdoSections; uint8_t num_of_slrs; }; /******************************************************************************/ class SubSysImageHeader : public BaseThing { public: SubSysImageHeader(ImageBifOptions *imgOptions); SubSysImageHeader(std::ifstream& ifs); ~SubSysImageHeader() { if (section != NULL) { delete section; } } void Build(BootImage& bi, Binary& cache); void Link(BootImage &bi, SubSysImageHeader* nextheader); void SetPCRMeasurementIndex(bool); void SetPCRNumber(bool); void SetSubSystemName(std::string); void SetSubSystemId(uint32_t); void SetSubSystemType(PartitionType::Type); void SetDelayHandoffMode(bool); void SetDelayLoadMode(bool); void SetMemCopyAddress(void); void SetSubSysMemCopyAddress(uint64_t); void SetPartitionHeaderOffset(uint32_t addr); void SetDataSectionCount(void); void SetMetaHdrRevokeId(uint32_t id); void SetImageHeaderAttributes(); void SetImageName(void); void SetImageHeaderIds(); void SetChecksum(void); uint32_t GetPartitionHeaderOffset(void); uint32_t GetDataSectionCount(void); uint32_t GetImageHeaderAttributes(void); bool GetDelayLoadMode(void); bool GetDelayHandoffMode(void); uint64_t GetSubSysMemCopyAddress(void); uint64_t GetMemCopyAddress(void); PartitionType::Type GetSubSystemType(void); std::string GetSubSystemName(void); uint32_t GetSubSystemId(void); uint16_t GetPCRNumber() { return pcrNumber; } uint16_t GetPCRMeasurementIndex() { return pcrMeasurementIndex; } uint32_t num_of_images; std::list imgList; std::list partitionNameList; protected: VersalImageHeaderStructure *subSysImageHeaderTable; uint32_t imageId; std::string imageName; bool delayHandoff; bool delayLoad; bool isFullPowerDomain; bool isLowPowerDomain; bool isSystemPowerDomain; bool isPLPowerDomain; uint64_t memCopyAddr; PartitionType::Type imageType; uint32_t uniqueId; uint32_t parentUniqueId; uint32_t functionId; uint16_t pcrNumber; uint16_t pcrMeasurementIndex; }; #endif xilinx-bootgen-2024.2/imageheadertable-zynq.cpp000077500000000000000000000567731475706442400215610ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable-zynq.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqImageHeader::ZynqImageHeader(std::string& filename) : ImageHeader(filename) , imageHeader(NULL) { Name = StringUtils::BaseName(filename); /* Include null terminator and round up to word */ uint32_t size = (uint32_t)Name.length() + 1; size = (size + 3) & ~3; size += 4; size += 16; section = new Section("ImageHeader " + Name, size); memset(section->Data, 0, size); } /******************************************************************************/ ZynqImageHeader::ZynqImageHeader(std::ifstream& ifs) : ImageHeader(ifs) , imageHeader(NULL) { bool firstValidHdr = false; /* Import the Image Header from a boot image file Read the image header from the file to extract image name for section creation */ ZynqImageHeaderStructure importedIH; long pos = ifs.tellg(); ifs.read((char*)&importedIH, 4 * sizeof(uint32_t)); char buffer[4]; char name[256]; uint32_t i = 0; do { ifs.read(buffer, 4); name[i + 0] = buffer[3]; name[i + 1] = buffer[2]; name[i + 2] = buffer[1]; name[i + 3] = buffer[0]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } Name = name; /* Include null terminator and round upto word */ uint32_t size = (uint32_t)Name.length() + 1; size = (size + 3) & ~3; size += 4; size += 16; /* Go to start and read the image header to populate other fields */ ifs.seekg(pos); section = new Section("ImageHeader " + Name, size); imageHeader = (ZynqImageHeaderStructure*)section->Data; ifs.read((char*)imageHeader, size); /* This is a work around of a bug in the old bootgen. The partition header counter is stored in the wrong field. */ long count = (importedIH.dataSectionCount == 0) ? importedIH.imageNameLength : importedIH.dataSectionCount; long offset = importedIH.partitionHeaderWordOffset * sizeof(uint32_t); for (uint8_t index = 0; indexfirstValidIndex = true; firstValidHdr = true; } ifs.seekg(offset); hdr->ReadHeader(ifs); hdr->ReadData(ifs); partitionHeaderList.push_back(hdr); /* This is just a default value. It may be true when the partition load address is compared to the bootheader */ Bootloader = false; Alignment = 0; Offset = 0; Reserve = 0; destCpu = (DestinationCPU::Type)hdr->GetDestinationCpu(); exceptionLevel = (ExceptionLevel::Type)hdr->GetExceptionLevel(); trustzone = (TrustZone::Type)hdr->GetTrustZone(); early_handoff = hdr->GetEarlyHandoff(); hivec = hdr->GetHivec(); authBlock = hdr->GetAuthblock(); switch (hdr->GetDestinationDevice()) { case DestinationDevice::DEST_DEV_PS: SetDomain(Domain::PS); destDevice = DestinationDevice::DEST_DEV_PS; break; case DestinationDevice::DEST_DEV_PL: SetDomain(Domain::PL); destDevice = DestinationDevice::DEST_DEV_PL; break; case DestinationDevice::DEST_DEV_NONE: LOG_DEBUG(DEBUG_STAMP, "Bad destination field in imported partition header - %s", hdr->section->Name.c_str()); LOG_ERROR("Failure parsing imported bootimage"); } offset += hdr->GetPartitionHeaderSize(); } } /******************************************************************************/ ZynqImageHeader::~ZynqImageHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqImageHeader::ImportFpgaDataFile(BootImage& bi) { ByteFile data(Filename); PartitionHeader* partHdr = new ZynqPartitionHeader(this, 0); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(data.len > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { data.len = Reserve.Value(); } } } partHdr->partition = new Partition(partHdr, data.bytes, data.len); partitionHeaderList.push_back(partHdr); } /******************************************************************************/ void ZynqImageHeader::CreateElfPartitions(BootImage& bi, ElfFormat* elf, uint8_t proc_state) { Binary::Length_t total_size = 0; Binary::Address_t load_addr = 0; Binary::Address_t exec_addr = 0; uint8_t *partition_data = NULL; uint32_t hdr_index = 0; SetDomain(Domain::PS); for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { if (Bootloader) { partition_data = CombineElfSections(elf, &total_size, &load_addr); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { fsblFwSize = totalFsblFwSize = total_size = Reserve.Value(); } } } fsblFwSize = totalFsblFwSize = total_size; if (bi.XipMode) { Offset.IsSet() ? SetFsblSourceAddrIh(Offset.Value()) : SetFsblSourceAddrIh(GetExecAddrForXip(load_addr)); } } else { partition_data = GetElfSections(elf, &total_size, &load_addr, iprog); if(updateReserveInPh == true) { if(Reserve.IsSet() && non_zero_elf_sec_count > 1) { LOG_WARNING("Multiple sections in elf. Hence reserve attribute is ignored."); } if(Reserve.IsSet() && non_zero_elf_sec_count == 1) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { total_size = Reserve.Value(); } } } if (partition_data == NULL) { continue; } } /* Override the exec and load address, if startup & load are set through BIF attributes */ Startup.IsSet() ? (exec_addr = Startup.Value()) : (exec_addr = elf->GetStartUpAddress()); if (Load.IsSet()) { load_addr = Load.Value(); } PartitionHeader* partHdr = new ZynqPartitionHeader(this, hdr_index); (hdr_index == 0) ? (partHdr->firstValidIndex = true) : (partHdr->firstValidIndex = false); partHdr->elfEndianess = elf->endian; partHdr->execAddress = exec_addr; partHdr->loadAddress = load_addr; partHdr->execState = proc_state; partHdr->partition = new Partition(partHdr, partition_data, total_size); free(partition_data); // This length also includes padding size necessary for 16-byte alignment partHdr->partitionSize = partHdr->partition->section->Length; hdr_index++; partitionHeaderList.push_back(partHdr); if (Bootloader) { /* All the sections are already combined using CombineElfSections, so break*/ break; } } } /******************************************************************************/ void ZynqImageHeader::ImportBit(BootImage& bi) { if (Bootloader) { LOG_ERROR("Bit stream can not be marked [bootloader]"); } SetDomain(Domain::PL); SetDestDevice(DestinationDevice::DEST_DEV_PL); std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read BIT file - %s ", Filename.c_str()); } BitFile *bit = new ZynqBitFile(stream); bit->ParseBit(bi); bit->SetEncryptionType(Encrypt->Type()); bi.bitFilename = Filename.c_str(); PartitionHeader* hdr = new ZynqPartitionHeader(this, 0); hdr->firstValidIndex = true; /* The endianess is different (Big Endian) in case of Zynq MP/FPGA encryption cases. All other cases the bitstream is copied as Little Endian */ OutputStream *os = bit->GetOutputStreamType(); /* If the Zynq/FPGA bitstream partition is encrypted, then we need to strip the normal BIT header (sync data, etc) before encryption. All other cases, just copy the entire bitstream as is */ if (bit->GetBitStripFlag()) { bit->Strip(os); } else { bit->Copy(os); } /* Bitstream sizes should be word aligned, otherwise bitstream is invalid */ if (os->Size() % 4) { LOG_DEBUG(DEBUG_STAMP, "BIT stream %s does not have a word aligned number of bytes (0xX)", Name.c_str(), (uint32_t)os->Size()); LOG_ERROR("BIT file parsing error !!!"); } /* As bitstreams are configured in the PL section There should be no load / start-up (execution) addresses in case of bitstreams. */ if (this->Startup.IsSet()) { LOG_ERROR("[startup=...] attribute not supported for BIT partition - %s", this->Name.c_str()); } hdr->execAddress = 0; hdr->SetBitLoadAddress(this->Load.IsSet(), this->Load.Value()); hdr->partitionSize = os->Size(); if (bit->GetBitPadFlag(bi.options.GetLegacyFlag())) { /* Pad the bit stream with NOPS to get a chunk useful for DMA Bit streams must have the length 32 byte aligned because of a HW bug in the PCAP DMA engine. This increases the os to a multiple of 32 bytes */ while (os->Size() % 32) { os->WriteLong(BITSTREAM_NOP); } hdr->partitionSize = os->Size(); } hdr->transferSize = os->Size(); hdr->preservedBitstreamHdr = os->pHdr; hdr->partition = new Partition(hdr, os->Start(), os->Size()); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(hdr->transferSize > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { hdr->transferSize = Reserve.Value(); hdr->partitionSize = Reserve.Value(); hdr->partition = new Partition(hdr, os->Start(),Reserve.Value()); } } } partitionHeaderList.push_back(hdr); } /******************************************************************************/ void ZynqImageHeader::ImportBin(BootImage& bi) { SetDomain(Domain::PS); ByteFile data(Filename); PartitionHeader* hdr = new ZynqPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = Startup.ValueOrDefault(0); if (Load.IsSet()) { hdr->loadAddress = Load.Value(); } else { hdr->loadAddress = 0; } if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(data.len > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { data.len = Reserve.Value(); } } } hdr->partition = new Partition(hdr, data.bytes, data.len); hdr->partitionSize = data.len; partitionHeaderList.push_back(hdr); } /******************************************************************************/ Binary::Address_t ZynqImageHeader::GetNextImageHeaderOffset() { return imageHeader->nextImageHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqImageHeader::GetPartitionHeaderOffset(void) { return imageHeader->partitionHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqImageHeader::GetDataSectionCount(void) { return imageHeader->dataSectionCount; } /******************************************************************************/ uint32_t ZynqImageHeader::GetImageNameLength(void) { return imageHeader->imageNameLength; } /******************************************************************************/ void ZynqImageHeader::Build(BootImage& bi, Binary& cache) { cache.Sections.push_back(section); uint32_t defaultAlignment = bi.options.GetDefaultAlignment(); if (imageHeader == NULL) { imageHeader = (ZynqImageHeaderStructure*)section->Data; SetImageName(); SetImageNameLength((uint32_t)Name.length()); SetDataSectionCount(0); SetPartitionHeaderOffset(0); SetNextImageHeaderOffset(0); if (Alignment.IsSet() && Offset.IsSet()) { LOG_ERROR("[alignment] and [offset] attributes are mutually exclusive"); } if (Alignment.IsSet() && (Alignment.Value() & (defaultAlignment - 1))) { LOG_ERROR("Alignment (0x%X) is not a multiple of %d", Alignment.Value(), defaultAlignment); } if (Reserve.IsSet() && (Reserve.Value() & (defaultAlignment - 1))) { LOG_ERROR("Reserve (0x%X) is not a multiple of %d", Reserve.Value(), defaultAlignment); } if (Offset.IsSet() && (Offset.Value() & (defaultAlignment - 1))) { LOG_ERROR("Offset (0x%X) is not a multiple of %d", Offset.Value(), defaultAlignment); } partitionHeaderList.clear(); std::string comparison = Filename; StringUtils::ToLower(comparison); std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read file - %s ", Filename.c_str()); } std::string line; while(line == "") { getline(stream, line); } if (IsElf(line)) { if (bi.partitionOutput->Type() == PartitionArch::FPGA) { ImportFpgaDataFile(bi); } else { ImportElf(bi); } } else if (StringUtils::EndsWith(comparison, ".srec")) { ImportFpgaDataFile(bi); } else if (StringUtils::EndsWith(comparison, ".bit") || StringUtils::EndsWith(comparison, ".rbt")) { ImportBit(bi); } else { ImportBin(bi); } /* Legacy operation for backward compatibility. This is a bug in the old bootgen */ SetDataSectionCount(0); SetImageNameLength((uint32_t)partitionHeaderList.size()); stream.close(); } bi.partitionHeaderList.insert(bi.partitionHeaderList.end(), partitionHeaderList.begin(), partitionHeaderList.end()); } /******************************************************************************/ void ZynqImageHeader::Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageHeader) { slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; imageHeader = (ZynqImageHeaderStructure*)section->Data; if (partitionHeader->section != NULL) { SetPartitionHeaderOffset((uint32_t)partitionHeader->section->Address); } if (nextImageHeader) { SetNextImageHeaderOffset((uint32_t)(nextImageHeader->section->Address)); } else { SetNextImageHeaderOffset(0); } } /******************************************************************************/ ZynqImageHeaderTable::ZynqImageHeaderTable() { section = new Section("ImageHeaderTable", sizeof(ZynqImageHeaderTableStructure)); iHTable = (ZynqImageHeaderTableStructure*)section->Data; } /******************************************************************************/ ZynqImageHeaderTable::ZynqImageHeaderTable(std::ifstream& src) { section = new Section("ImageHeaderTable", sizeof(ZynqImageHeaderTableStructure)); iHTable = (ZynqImageHeaderTableStructure*)section->Data; /* Import the Image Header Table from a boot image file */ src.read((char*)section->Data, section->Length); } /******************************************************************************/ ZynqImageHeaderTable::~ZynqImageHeaderTable() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqImageHeaderTable::SetImageHeaderTableVersion(uint32_t version) { iHTable->version = version; } /******************************************************************************/ void ZynqImageHeaderTable::SetPartitionCount(uint32_t count) { iHTable->partitionTotalCount = count; } /******************************************************************************/ void ZynqImageHeaderTable::SetFirstPartitionHeaderOffset(uint32_t offset) { iHTable->firstPartitionHeaderWordOffset = offset; } /******************************************************************************/ void ZynqImageHeaderTable::SetFirstImageHeaderOffset(uint32_t offset) { iHTable->firstImageHeaderWordOffset = offset; } /******************************************************************************/ void ZynqImageHeaderTable::SetHeaderAuthCertificateOffset(uint32_t offset) { iHTable->headerAuthCertificateWordOffset = offset; } /******************************************************************************/ void ZynqImageHeaderTable::SetReservedFields(void) { /* For Zynq Image Header Table, reserved fields are set to 0xFF */ memset(&iHTable->reserved, 0xFF, MAX_IHT_RESERVED_ZYNQ * sizeof(uint32_t)); } /******************************************************************************/ void ZynqImageHeaderTable::RealignSectionDataPtr(void) { iHTable = (ZynqImageHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t ZynqImageHeaderTable::GetImageHeaderTableVersion(void) { return iHTable->version; } /******************************************************************************/ uint32_t ZynqImageHeaderTable::GetPartitionCount(void) { return iHTable->partitionTotalCount; } /******************************************************************************/ uint32_t ZynqImageHeaderTable::GetFirstPartitionHeaderOffset(void) { return iHTable->firstPartitionHeaderWordOffset; } /******************************************************************************/ uint32_t ZynqImageHeaderTable::GetFirstImageHeaderOffset(void) { return iHTable->firstImageHeaderWordOffset; } /******************************************************************************/ uint32_t ZynqImageHeaderTable::GetHeaderAuthCertificateOffset(void) { return iHTable->headerAuthCertificateWordOffset; } /******************************************************************************/ void ZynqImageHeader::SetNextImageHeaderOffset(uint32_t addr) { imageHeader->nextImageHeaderWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (imageHeader->nextImageHeaderWordOffset != 0)) { imageHeader->nextImageHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqImageHeader::SetPartitionHeaderOffset(uint32_t addr) { imageHeader->partitionHeaderWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (imageHeader->partitionHeaderWordOffset != 0)) { imageHeader->partitionHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqImageHeader::SetDataSectionCount(uint32_t cnt) { imageHeader->dataSectionCount = cnt; } /******************************************************************************/ void ZynqImageHeader::SetImageNameLength(uint32_t len) { imageHeader->imageNameLength = len; } /******************************************************************************/ void ZynqImageHeader::SetImageName(void) { /* This is legacy ordering, the name is written with each set of 4 characters in reversed order */ for (uint32_t i = 0;iimageName[j] = Name[i]; } } /******************************************************************************/ void ZynqImageHeader::ValidateEncryptionAttributes(BootImage& bi) { if (bi.bootHeader->GetPrebuiltFlag() == false) { if (IsBootloader() && (bi.options.GetEncryptedKeySource() != KeySource::None)) { LOG_ERROR("Key Source can be enabled only if bootloader is encrypted."); } } } /******************************************************************************/ uint64_t ZynqImageHeader::GetExecAddrForXip(uint64_t execAddr) { if ((execAddr >= LQSPI_BASE_ADDR_ZYNQ) && (execAddr < LQSPI_BASE_ADDR_ZYNQ + LQSPI_SIZE_ZYNQ)) { return (execAddr & LQSPI_RANGE_MASK_ZYNQ); } else if ((execAddr >= NOR_BASE_ADDR_ZYNQ) && (execAddr < NOR_BASE_ADDR_ZYNQ + NOR_SIZE_ZYNQ)) { LOG_INFO("Exec Addr - 0x%x, NOR Mask - 0x%x", execAddr, NOR_RANGE_MASK_ZYNQ); return (execAddr - NOR_BASE_ADDR_ZYNQ); } else { LOG_DEBUG(DEBUG_STAMP, "LQSPI Range: 0x%x-0x%x, NOR Range: 0x%x-0x%x, Exec Addr: 0x%x", LQSPI_BASE_ADDR_ZYNQ, LQSPI_BASE_ADDR_ZYNQ + LQSPI_SIZE_ZYNQ, NOR_BASE_ADDR_ZYNQ, NOR_BASE_ADDR_ZYNQ + NOR_SIZE_ZYNQ, execAddr); LOG_ERROR("Execution Address of FSBL is out of Linear QSPI range in XIP mode"); } return 0; } xilinx-bootgen-2024.2/imageheadertable-zynq.h000077500000000000000000000125211475706442400212050ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _IMAGEHEADERTABLE_ZYNQ_H_ #define _IMAGEHEADERTABLE_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable.h" #include "partitionheadertable-zynq.h" #include "bootimage.h" #include "fileutils.h" #include "elftools.h" #include "bitutils.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MAX_IHT_RESERVED_ZYNQ 11 #define MAX_NUM_PARTITIONS_ZYNQ 14 /* 32MB Linear QSPI range */ #define LQSPI_BASE_ADDR_ZYNQ (0xFC000000) #define LQSPI_SIZE_ZYNQ (0x2000000) #define LQSPI_RANGE_MASK_ZYNQ (0x1FFFFFF) /* 32MB + 32MB SMC (NOR0 + NOR1) ranges */ #define NOR_BASE_ADDR_ZYNQ (0xE2000000) #define NOR_SIZE_ZYNQ (0x4000000) #define NOR_RANGE_MASK_ZYNQ (0x3FFFFFF) /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t version; // 0x00 uint32_t partitionTotalCount; // 0x04 uint32_t firstPartitionHeaderWordOffset; // 0x08 uint32_t firstImageHeaderWordOffset; // 0x0C uint32_t headerAuthCertificateWordOffset; // 0x10 uint32_t reserved[MAX_IHT_RESERVED_ZYNQ]; // 0x14 } ZynqImageHeaderTableStructure; typedef struct { uint32_t nextImageHeaderWordOffset; // 0x00 uint32_t partitionHeaderWordOffset; // 0x04 uint32_t dataSectionCount; // 0x08 uint32_t imageNameLength; // 0x0C char imageName[1]; // 0x10 } ZynqImageHeaderStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqImageHeaderTable : public ImageHeaderTable { public: ZynqImageHeaderTable(); ZynqImageHeaderTable(std::ifstream& ifs); ~ZynqImageHeaderTable(); void ValidateSecurityCombinations(Authentication::Type, Encryption::Type, Checksum::Type) {}; void RealignSectionDataPtr(void); uint8_t GetMaxNumOfPartitions(void) { return MAX_NUM_PARTITIONS_ZYNQ; } void SetImageHeaderTableVersion(uint32_t version); void SetPartitionCount(uint32_t count); void SetFirstPartitionHeaderOffset(uint32_t offset); void SetFirstImageHeaderOffset(uint32_t offset); void SetHeaderAuthCertificateOffset(uint32_t offset); void SetReservedFields(void); void SetChecksum(void) {} void SetBootDevice(BootDevice::Type type) {} uint32_t GetImageHeaderTableVersion(void); uint32_t GetPartitionCount(void); uint32_t GetFirstPartitionHeaderOffset(void); uint32_t GetFirstImageHeaderOffset(void); uint32_t GetHeaderAuthCertificateOffset(void); private: ZynqImageHeaderTableStructure *iHTable; }; /******************************************************************************/ class ZynqImageHeader : public ImageHeader { public: ZynqImageHeader(std::string& filename); ZynqImageHeader(std::ifstream& f); ~ZynqImageHeader(); void Build(BootImage& bi, Binary& cache); void Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageheader); void ValidateEncryptionAttributes(BootImage & bi); void ImportFpgaDataFile(BootImage & bi); void ImportBit(BootImage & bi); void ImportBin(BootImage & bi); void CreateElfPartitions(BootImage& bi, ElfFormat* elf, uint8_t proc_state); uint64_t GetExecAddrForXip(uint64_t execAddr); void SetNextImageHeaderOffset(uint32_t addr); void SetPartitionHeaderOffset(uint32_t addr); void SetDataSectionCount(uint32_t cnt); void SetImageNameLength(uint32_t len); void SetImageName(void); Binary::Address_t GetNextImageHeaderOffset(); uint32_t GetPartitionHeaderOffset(void); uint32_t GetDataSectionCount(void); uint32_t GetImageNameLength(void); private: ZynqImageHeaderStructure *imageHeader; }; #endif xilinx-bootgen-2024.2/imageheadertable-zynqmp.cpp000077500000000000000000000712621475706442400221040ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable-zynqmp.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqMpImageHeader::ZynqMpImageHeader(std::string& filename) : ImageHeader(filename) , imageHeader(NULL) { Name = StringUtils::BaseName(filename); /* Include null terminator and round up to word */ uint32_t size = (uint32_t)Name.length() + 1; size = (size + 3) & ~3; size += 4; size += 16; section = new Section("ImageHeader " + Name, size); memset(section->Data, 0, size); } /******************************************************************************/ ZynqMpImageHeader::ZynqMpImageHeader(std::ifstream& ifs) : ImageHeader(ifs) , imageHeader(NULL) { bool firstValidHdr = false; ZynqMpImageHeaderStructure importedIH; /* Import the Image Header from a boot image file Read the image header from the file to extract image name for section creation */ long pos = ifs.tellg(); ifs.read((char*)&importedIH, 4 * sizeof(uint32_t)); char buffer[4]; char name[256]; uint32_t i = 0; do { ifs.read(buffer, 4); name[i + 0] = buffer[3]; name[i + 1] = buffer[2]; name[i + 2] = buffer[1]; name[i + 3] = buffer[0]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } Name = name; /* Include null terminator and round upto word */ uint32_t size = (uint32_t)Name.length() + 1; size = (size + 3) & ~3; size += 4; size += 16; /* Go to start and read the image header to populate other fields */ ifs.seekg(pos); section = new Section("ImageHeader " + Name, size); imageHeader = (ZynqMpImageHeaderStructure*)section->Data; ifs.read((char*)imageHeader, size); /* This is a work around of a bug in the old bootgen. The partition header counter is stored in the wrong field. */ long count = (importedIH.dataSectionCount == 0) ? importedIH.imageNameLength : importedIH.dataSectionCount; long offset = importedIH.partitionHeaderWordOffset * sizeof(uint32_t); for (uint8_t index = 0; indexfirstValidIndex = true; firstValidHdr = true; } ifs.seekg(offset); hdr->ReadHeader(ifs); hdr->ReadData(ifs); partitionHeaderList.push_back(hdr); Bootloader = false; Alignment = 0; Offset = 0; Reserve = 0; destCpu = (DestinationCPU::Type)hdr->GetDestinationCpu(); exceptionLevel = (ExceptionLevel::Type)hdr->GetExceptionLevel(); trustzone = (TrustZone::Type)hdr->GetTrustZone(); early_handoff = hdr->GetEarlyHandoff(); hivec = hdr->GetHivec(); authBlock = hdr->GetAuthblock(); switch (hdr->GetDestinationDevice()) { case DestinationDevice::DEST_DEV_PS: SetDomain(Domain::PS); destDevice = DestinationDevice::DEST_DEV_PS; break; case DestinationDevice::DEST_DEV_PMU: SetDomain(Domain::PL); destDevice = DestinationDevice::DEST_DEV_PMU; break; case DestinationDevice::DEST_DEV_PL: domain = Domain::PL; destDevice = DestinationDevice::DEST_DEV_PL; break; case DestinationDevice::DEST_DEV_NONE: LOG_DEBUG(DEBUG_STAMP, "Bad destination field in imported partition header - %s", hdr->section->Name.c_str()); LOG_ERROR("Failure parsing imported bootimage"); } offset += hdr->GetPartitionHeaderSize(); } } /******************************************************************************/ ZynqMpImageHeader::~ZynqMpImageHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqMpImageHeader::ImportFpgaDataFile(BootImage& bi) { ByteFile data(Filename); PartitionHeader* partHdr = new ZynqMpPartitionHeader(this, 0); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(data.len > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { data.len = Reserve.Value(); } } } partHdr->partition = new Partition(partHdr, data.bytes, data.len); partitionHeaderList.push_back(partHdr); } /******************************************************************************/ void ZynqMpImageHeader::CreateElfPartitions(BootImage& bi, ElfFormat* elf, uint8_t proc_state) { Binary::Length_t total_size = 0; Binary::Address_t load_addr = 0; Binary::Address_t exec_addr = 0; uint8_t *partition_data = NULL; uint32_t hdr_index = 0; SetDomain(Domain::PS); for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { if (Bootloader) { Binary::Length_t fsbl_size = 0; std::string pmu_fw = bi.bifOptions->GetPmuFwImageFile(); if (pmu_fw != "") { uint8_t* fsbl_data = CombineElfSections(elf, &fsbl_size, &load_addr); fsblFwSize = totalFsblFwSize = total_size = fsbl_size; if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { fsblFwSize = totalFsblFwSize = total_size = fsbl_size = Reserve.Value(); } } } partition_data = AttachPmuFw(fsbl_data, &total_size, pmu_fw); free(fsbl_data); } else { partition_data = CombineElfSections(elf, &total_size, &load_addr); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { fsblFwSize = totalFsblFwSize = total_size = fsbl_size = Reserve.Value(); } } } fsblFwSize = totalFsblFwSize = total_size; } bi.SetCoreFromDestCpu(destCpu, (A53ExecState::Type)proc_state); if (bi.XipMode) { Offset.IsSet() ? SetFsblSourceAddrIh(Offset.Value()) : SetFsblSourceAddrIh(GetExecAddrForXip(load_addr)); } } else { partition_data = GetElfSections(elf, &total_size, &load_addr, iprog); if(updateReserveInPh == true) { if(Reserve.IsSet() && non_zero_elf_sec_count > 1) { LOG_WARNING("Multiple sections in elf. Hence reserve attribute is ignored."); } if(Reserve.IsSet() && non_zero_elf_sec_count == 1) { if(total_size > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { total_size = Reserve.Value(); } } } if (partition_data == NULL) { continue; } } /* Override the exec and load address, if startup & load are set through BIF attributes */ Startup.IsSet() ? (exec_addr = Startup.Value()) : (exec_addr = elf->GetStartUpAddress()); if (Load.IsSet() && iprog == 0) { load_addr = Load.Value(); } PartitionHeader* partHdr = new ZynqMpPartitionHeader(this, hdr_index); (hdr_index == 0) ? (partHdr->firstValidIndex = true) : (partHdr->firstValidIndex = false); partHdr->elfEndianess = elf->endian; partHdr->execAddress = exec_addr; partHdr->loadAddress = load_addr; partHdr->execState = proc_state; partHdr->partition = new Partition(partHdr, partition_data, total_size); free(partition_data); // This length also includes padding size necessary for 16-byte alignment partHdr->partitionSize = partHdr->partition->section->Length; hdr_index++; partitionHeaderList.push_back(partHdr); if (Bootloader) { /* All the sections are already combined using CombineElfSections, so break*/ break; } } } /******************************************************************************/ uint8_t* ZynqMpImageHeader::AttachPmuFw(uint8_t* fsbl_data, uint64_t* size, std::string pmu_fw) { uint8_t* partition_data = NULL; ByteFile pmu_fw_data(pmu_fw); Binary::Length_t pmu_size = 0; Binary::Address_t pmu_addr = 0; uint8_t pmu_padding = 0; /* If PMU FW is an ELF file */ if (StringUtils::EndsWith(pmu_fw, ".elf")) { ElfFormat32 pmu_elf(pmu_fw_data.bytes); partition_data = CombineElfSections((ElfFormat*)&pmu_elf, &pmu_size, &pmu_addr); } else { pmu_size = pmu_fw_data.len; partition_data = (uint8_t*)malloc(pmu_size); memcpy(partition_data, pmu_fw_data.bytes, pmu_size); } pmu_padding = (4 - (pmu_size & 3)) & 3; pmuFwSize = totalPmuFwSize = pmu_size + pmu_padding; partition_data = (uint8_t*)realloc(partition_data, pmuFwSize + *size); memset(partition_data + pmu_size, 0, pmu_padding); memcpy(partition_data + pmuFwSize, fsbl_data, *size); *size += pmuFwSize; return partition_data; } /******************************************************************************/ void ZynqMpImageHeader::ImportBit(BootImage& bi) { if (Bootloader) { LOG_ERROR("Bit stream can not be marked [bootloader]"); } SetDomain(Domain::PL); SetDestDevice(DestinationDevice::DEST_DEV_PL); std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read BIT file - %s ", Filename.c_str()); } BitFile *bit = new ZynqMpBitFile(stream); bit->ParseBit(bi); bit->SetEncryptionType(Encrypt->Type()); bi.bitFilename = Filename.c_str(); PartitionHeader* hdr = new ZynqMpPartitionHeader(this, 0); hdr->firstValidIndex = true; /* The endianess is different (Big Endian) in case of Zynq MP/FPGA encryption cases. All other cases the bitstream is copied as Little Endian */ OutputStream *os = bit->GetOutputStreamType(); /* If the Zynq/FPGA bitstream partition is encrypted, then we need to strip the normal BIT header (sync data, etc) before encryption. All other cases, just copy the entire bitstream as is */ if (bit->GetBitStripFlag()) { bit->Strip(os); } else { bit->Copy(os); } /* Bitstream sizes should be word aligned. Otherwise bitstream is invalid */ if (os->Size() % 4) { LOG_DEBUG(DEBUG_STAMP, "BIT stream %s does not have a word aligned number of bytes (0xX)", Name.c_str(), (uint32_t)os->Size()); LOG_ERROR("BIT file parsing error !!!"); } /* As bitstreams are configured in the PL section There should be no load / start-up (execution) addresses in case of bitstreams. */ if (this->Startup.IsSet()) { LOG_ERROR("[startup=...] attribute not supported for BIT partition - %s", this->Name.c_str()); } hdr->execAddress = 0; hdr->SetBitLoadAddress(this->Load.IsSet(), this->Load.Value()); hdr->partitionSize = os->Size(); if (bit->GetBitPadFlag(bi.options.GetLegacyFlag())) { /* Pad the bit stream with NOPS to get a chunk useful for DMA Bit streams must have the length 32 byte aligned because of a HW bug in the PCAP DMA engine. This increases the os to a multiple of 32 bytes */ while (os->Size() % 32) { os->WriteLong(BITSTREAM_NOP); } hdr->partitionSize = os->Size(); } hdr->transferSize = os->Size(); hdr->preservedBitstreamHdr = os->pHdr; hdr->partition = new Partition(hdr, os->Start(), os->Size()); if(updateReserveInPh == true) { if(Reserve.IsSet()) { if(hdr->transferSize > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { hdr->transferSize = Reserve.Value(); hdr->partitionSize = Reserve.Value(); hdr->partition = new Partition(hdr, os->Start(),Reserve.Value()); } } } partitionHeaderList.push_back(hdr); } /******************************************************************************/ void ZynqMpImageHeader::ImportBin(BootImage& bi) { SetDomain(Domain::PS); ByteFile data(Filename); PartitionHeader* hdr = new ZynqMpPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = Startup.ValueOrDefault(0); hdr->loadAddress = 0; if (Load.IsSet()) { hdr->loadAddress = Load.Value(); } if (bigEndian) { hdr->elfEndianess = Endianness::BigEndian; } if (a32Mode) { hdr->execState = A53ExecState::AARCH32; } if (Bootloader) { /* PMUFW + SPL */ std::string pmu_fw = bi.bifOptions->GetPmuFwImageFile(); ByteFile pmu_fw_data(pmu_fw); Binary::Length_t pmu_size = pmu_fw_data.len; uint8_t *partition_data = (uint8_t *)malloc(pmu_size); memcpy(partition_data, pmu_fw_data.bytes, pmu_size); uint8_t pmu_padding = (4 - (pmu_size & 3)) & 3; pmuFwSize = totalPmuFwSize = pmu_size + pmu_padding; partition_data = (uint8_t *)realloc(partition_data, pmuFwSize + data.len); memset(partition_data + pmu_size, 0, pmu_padding); memcpy(partition_data + pmuFwSize, data.bytes, data.len); data.bytes = partition_data; fsblFwSize = totalFsblFwSize = data.len + ((4 - (data.len & 3)) & 3); data.len += pmuFwSize; if (Load.IsSet()) hdr->execAddress = Load.Value(); } if (updateReserveInPh == true) { if(Reserve.IsSet()) { if(data.len > Reserve.Value()) { LOG_WARNING("Total Partition length is more than Reserve Length. Hence reserve attribute is ignored."); } else { data.len = Reserve.Value(); } } } hdr->partition = new Partition(hdr, data.bytes, data.len); hdr->partitionSize = data.len; partitionHeaderList.push_back(hdr); } /******************************************************************************/ Binary::Address_t ZynqMpImageHeader::GetNextImageHeaderOffset() { return imageHeader->nextImageHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqMpImageHeader::GetPartitionHeaderOffset(void) { return imageHeader->partitionHeaderWordOffset * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqMpImageHeader::GetDataSectionCount(void) { return imageHeader->dataSectionCount; } /******************************************************************************/ uint32_t ZynqMpImageHeader::GetImageNameLength(void) { return imageHeader->imageNameLength; } /******************************************************************************/ void ZynqMpImageHeader::Build(BootImage& bi, Binary& cache) { cache.Sections.push_back(section); uint32_t defaultAlignment = bi.options.GetDefaultAlignment(); if (imageHeader == NULL) { imageHeader = (ZynqMpImageHeaderStructure*)section->Data; SetImageName(); SetImageNameLength((uint32_t)Name.length()); SetDataSectionCount(0); SetPartitionHeaderOffset(0); SetNextImageHeaderOffset(0); if (Alignment.IsSet() && Offset.IsSet()) { LOG_ERROR("[alignment] and [offset] attributes are mutually exclusive"); } if (Alignment.IsSet() && (Alignment.Value() & (defaultAlignment - 1))) { LOG_ERROR("Alignment (0x%X) is not a multiple of %d", Alignment.Value(), defaultAlignment); } if (Reserve.IsSet() && (Reserve.Value() & (defaultAlignment - 1))) { LOG_ERROR("Reserve (0x%X) is not a multiple of %d", Reserve.Value(), defaultAlignment); } if (Offset.IsSet() && (Offset.Value() & (defaultAlignment - 1))) { LOG_ERROR("Offset (0x%X) is not a multiple of %d", Offset.Value(), defaultAlignment); } partitionHeaderList.clear(); std::string comparison = Filename; StringUtils::ToLower(comparison); std::ifstream stream(Filename.c_str(), std::ios_base::binary); if (!stream) { LOG_ERROR("Cannot read file - %s ", Filename.c_str()); } std::string line; while(line == "") { getline(stream, line); } if (IsElf(line)) { ImportElf(bi); } else if (StringUtils::EndsWith(comparison, ".bit") || StringUtils::EndsWith(comparison, ".rbt")) { ImportBit(bi); } else if (StringUtils::EndsWith(comparison, ".hashbit")) { ImportBin(bi); SetDomain(Domain::PL); SetDestDevice(DestinationDevice::DEST_DEV_PL); } else { ImportBin(bi); } SetDataSectionCount(0); SetImageNameLength((uint32_t)partitionHeaderList.size()); stream.close(); } bi.partitionHeaderList.insert(bi.partitionHeaderList.end(),partitionHeaderList.begin(),partitionHeaderList.end()); } /******************************************************************************/ void ZynqMpImageHeader::Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageHeader) { slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; imageHeader = (ZynqMpImageHeaderStructure*)section->Data; if (partitionHeader->section != NULL) { SetPartitionHeaderOffset((uint32_t)partitionHeader->section->Address); } if (nextImageHeader) { SetNextImageHeaderOffset((uint32_t)(nextImageHeader->section->Address)); } else { SetNextImageHeaderOffset(0); } } /******************************************************************************/ ZynqMpImageHeaderTable::ZynqMpImageHeaderTable() { section = new Section("ImageHeaderTable", sizeof(ZynqMpImageHeaderTableStructure)); iHTable = (ZynqMpImageHeaderTableStructure*)section->Data; } /******************************************************************************/ ZynqMpImageHeaderTable::ZynqMpImageHeaderTable(std::ifstream& src) { section = new Section("ImageHeaderTable", sizeof(ZynqMpImageHeaderTableStructure)); iHTable = (ZynqMpImageHeaderTableStructure*)section->Data; /* Import the Image Header Table from a boot image file */ src.read((char*)section->Data, section->Length); } /******************************************************************************/ ZynqMpImageHeaderTable::~ZynqMpImageHeaderTable() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqMpImageHeaderTable::SetImageHeaderTableVersion(uint32_t version) { iHTable->version = version; } /******************************************************************************/ void ZynqMpImageHeaderTable::SetPartitionCount(uint32_t count) { iHTable->partitionTotalCount = count; } /******************************************************************************/ void ZynqMpImageHeaderTable::SetFirstPartitionHeaderOffset(uint32_t offset) { iHTable->firstPartitionHeaderWordOffset = offset; if (slaveBootSplitMode && (iHTable->firstPartitionHeaderWordOffset != 0)) { iHTable->firstPartitionHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpImageHeaderTable::SetFirstImageHeaderOffset(uint32_t offset) { iHTable->firstImageHeaderWordOffset = offset; if (slaveBootSplitMode && (iHTable->firstImageHeaderWordOffset != 0)) { iHTable->firstImageHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpImageHeaderTable::SetHeaderAuthCertificateOffset(uint32_t offset) { iHTable->headerAuthCertificateWordOffset = offset; if (slaveBootSplitMode && (iHTable->headerAuthCertificateWordOffset != 0)) { iHTable->headerAuthCertificateWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpImageHeaderTable::SetBootDevice(BootDevice::Type type) { iHTable->bootDevice = type; } /******************************************************************************/ void ZynqMpImageHeaderTable::SetReservedFields(void) { memset(&iHTable->reserved, 0x00, MAX_IHT_RESERVED_ZYNQMP * sizeof(uint32_t)); } /******************************************************************************/ void ZynqMpImageHeaderTable::SetChecksum(void) { iHTable->ihtChecksum = ComputeWordChecksum(iHTable, sizeof(ZynqMpImageHeaderTableStructure) - sizeof(iHTable->ihtChecksum) /* bytes*/); } /******************************************************************************/ void ZynqMpImageHeaderTable::RealignSectionDataPtr(void) { iHTable = (ZynqMpImageHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t ZynqMpImageHeaderTable::GetImageHeaderTableVersion(void) { return iHTable->version; } /******************************************************************************/ uint32_t ZynqMpImageHeaderTable::GetPartitionCount(void) { return iHTable->partitionTotalCount; } /******************************************************************************/ uint32_t ZynqMpImageHeaderTable::GetFirstPartitionHeaderOffset(void) { return iHTable->firstPartitionHeaderWordOffset; } /******************************************************************************/ uint32_t ZynqMpImageHeaderTable::GetFirstImageHeaderOffset(void) { return iHTable->firstImageHeaderWordOffset; } /******************************************************************************/ uint32_t ZynqMpImageHeaderTable::GetHeaderAuthCertificateOffset(void) { return iHTable->headerAuthCertificateWordOffset; } /******************************************************************************/ void ZynqMpImageHeaderTable::ValidateSecurityCombinations(Authentication::Type authType, Encryption::Type encryptType, Checksum::Type cksumType) { if ((authType != Authentication::None) && (cksumType != Checksum::None)) { LOG_ERROR("Checksum is not supported with Authentication"); } if ((encryptType != Encryption::None) && (cksumType != Checksum::None)) { LOG_ERROR("Checksum is not supported with Encryption"); } } /******************************************************************************/ void ZynqMpImageHeader::SetNextImageHeaderOffset(uint32_t addr) { imageHeader->nextImageHeaderWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (imageHeader->nextImageHeaderWordOffset != 0)) { imageHeader->nextImageHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpImageHeader::SetPartitionHeaderOffset(uint32_t addr) { imageHeader->partitionHeaderWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (imageHeader->partitionHeaderWordOffset != 0)) { imageHeader->partitionHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpImageHeader::SetDataSectionCount(uint32_t cnt) { imageHeader->dataSectionCount = cnt; } /******************************************************************************/ void ZynqMpImageHeader::SetImageNameLength(uint32_t len) { imageHeader->imageNameLength = len; } /******************************************************************************/ void ZynqMpImageHeader::SetImageName(void) { for (uint32_t i = 0;iimageName[j] = Name[i]; } } /******************************************************************************/ void ZynqMpImageHeader::SetBigEndian(bool flag) { bigEndian = flag; } /******************************************************************************/ void ZynqMpImageHeader::SetA32ExecMode(bool flag) { a32Mode = flag; } /******************************************************************************/ void ZynqMpImageHeader::ValidateEncryptionAttributes(BootImage& bi) { if (bi.bootHeader->GetPrebuiltFlag() == false) { if (IsBootloader() && (bi.options.GetEncryptedKeySource() != KeySource::None) && (bi.bifOptions->GetAuthOnly() != AuthOnly::Enabled)) { LOG_ERROR("Key Source can be enabled only if bootloader is encrypted or auth_only is used in [fsbl_config] attribute."); } } if (IsBootloader() && bi.bifOptions->GetOptKey() == OptKey::OptKeyinSecHdr) { LOG_ERROR("Optional key cannot be used, if bootloader is not encrypted\n Cannot use 'opt_key' in [fsbl_config] attribute when encryption is not used"); } } /******************************************************************************/ void ZynqMpImageHeader::SetAuthBlock(size_t blockSize, bool flag) { if (flag) { authBlock = 0; } else { if (blockSize == 0) { authBlock = 8; } else { authBlock = blockSize; } } } /******************************************************************************/ uint64_t ZynqMpImageHeader::GetExecAddrForXip(uint64_t execAddr) { if ((execAddr < LQSPI_BASE_ADDR_ZYNQMP) || (execAddr >(LQSPI_BASE_ADDR_ZYNQMP + LQSPI_SIZE_ZYNQMP))) { LOG_DEBUG(DEBUG_STAMP, "LQSPI Range: 0x%x-0x%x, Exec Addr: 0x%x", LQSPI_BASE_ADDR_ZYNQMP, LQSPI_BASE_ADDR_ZYNQMP + LQSPI_SIZE_ZYNQMP, execAddr); LOG_ERROR("Execution Address of FSBL is out of Linear QSPI range in XIP mode"); } return (execAddr & LQSPI_RANGE_MASK_ZYNQMP); } xilinx-bootgen-2024.2/imageheadertable-zynqmp.h000077500000000000000000000127471475706442400215540ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _IMAGEHEADERTABLE_ZYNQMP_H_ #define _IMAGEHEADERTABLE_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "imageheadertable.h" #include "partitionheadertable-zynqmp.h" #include "bootimage.h" #include "fileutils.h" #include "elftools.h" #include "bitutils.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MAX_IHT_RESERVED_ZYNQMP 9 #define MAX_NUM_PARTITIONS_ZYNQMP 32 /* 128MB Linear QSPI range */ #define LQSPI_BASE_ADDR_ZYNQMP (0xC0000000) #define LQSPI_SIZE_ZYNQMP (0x8000000) #define LQSPI_RANGE_MASK_ZYNQMP (0x7FFFFFF) /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t version; // 0x00 uint32_t partitionTotalCount; // 0x04 uint32_t firstPartitionHeaderWordOffset; // 0x08 uint32_t firstImageHeaderWordOffset; // 0x0C uint32_t headerAuthCertificateWordOffset; // 0x10 uint32_t bootDevice; // 0x14 uint32_t reserved[MAX_IHT_RESERVED_ZYNQMP]; // 0x18 uint32_t ihtChecksum; // 0x3C } ZynqMpImageHeaderTableStructure; typedef struct { uint32_t nextImageHeaderWordOffset; // 0x00 uint32_t partitionHeaderWordOffset; // 0x04 uint32_t dataSectionCount; // 0x08 uint32_t imageNameLength; // 0x10 char imageName[1]; // 0x14 } ZynqMpImageHeaderStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpImageHeaderTable : public ImageHeaderTable { public: ZynqMpImageHeaderTable(); ZynqMpImageHeaderTable(std::ifstream& ifs); ~ZynqMpImageHeaderTable(); void ValidateSecurityCombinations(Authentication::Type, Encryption::Type, Checksum::Type); void RealignSectionDataPtr(void); void SetImageHeaderTableVersion(uint32_t version); void SetPartitionCount(uint32_t count); void SetFirstPartitionHeaderOffset(uint32_t offset); void SetFirstImageHeaderOffset(uint32_t offset); void SetHeaderAuthCertificateOffset(uint32_t offset); void SetReservedFields(void); void SetChecksum(void); void SetBootDevice(BootDevice::Type type); uint32_t GetImageHeaderTableVersion(void); uint32_t GetPartitionCount(void); uint32_t GetFirstPartitionHeaderOffset(void); uint32_t GetFirstImageHeaderOffset(void); uint32_t GetHeaderAuthCertificateOffset(void); uint8_t GetMaxNumOfPartitions(void) { return MAX_NUM_PARTITIONS_ZYNQMP; } private: ZynqMpImageHeaderTableStructure *iHTable; }; /******************************************************************************/ class ZynqMpImageHeader : public ImageHeader { public: ZynqMpImageHeader(std::string& filename); ZynqMpImageHeader(std::ifstream& f); ~ZynqMpImageHeader(); void Build(BootImage& bi, Binary& cache); void Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageheader); void ValidateEncryptionAttributes(BootImage & bi); void SetAuthBlock(size_t blockSize, bool flag); void ImportFpgaDataFile(BootImage & bi); void ImportBit(BootImage & bi); void ImportBin(BootImage & bi); void CreateElfPartitions(BootImage& bi, ElfFormat* elf, uint8_t proc_state); uint8_t* AttachPmuFw(uint8_t* partition_data, uint64_t* total_size, std::string pmu_fw); uint64_t GetExecAddrForXip(uint64_t execAddr); Binary::Address_t GetNextImageHeaderOffset(); uint32_t GetPartitionHeaderOffset(void); uint32_t GetDataSectionCount(void); uint32_t GetImageNameLength(void); void SetNextImageHeaderOffset(uint32_t addr); void SetPartitionHeaderOffset(uint32_t addr); void SetDataSectionCount(uint32_t cnt); void SetImageNameLength(uint32_t len); void SetImageName(void); void SetBigEndian(bool); void SetA32ExecMode(bool); private: ZynqMpImageHeaderStructure *imageHeader; }; #endif xilinx-bootgen-2024.2/imageheadertable.cpp000077500000000000000000000500461475706442400205450ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "elftools.h" #include "stringutils.h" #include "fileutils.h" #include "options.h" #include "bifoptions.h" #include "bitutils.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void ImageHeaderTable::Build(BootImage& bi, Binary& cache) { if(section != NULL) { cache.Sections.push_back(section); } SetImageHeaderTableVersion(VERSION_ZYNQ_ZYNQMP); for(std::list::iterator image = bi.imageList.begin(); image != bi.imageList.end(); image++) { (*image)->Build(bi,cache); /* Validate the security combinations, like checksum is not supported with encryption & authentication in ZynqMP */ ValidateSecurityCombinations((*image)->GetAuthenticationType(), (*image)->GetEncryptContext()->Type(), (*image)->GetChecksumContext()->Type()); imageHeaderList.push_back(*image); } if (bi.options.DoPadHeaderTable()) { if ( bi.imageList.size() == 0) { std::list outFileNames = bi.options.GetOutputFileNames(); if (outFileNames.size() > 0) { std::cerr << "WARNING: -padimageheader was requested, but no images were specified." << std::endl; } } else { int paddingsize = GetMaxNumOfPartitions() - bi.imageList.size(); if (paddingsize > 0) { bi.imageList.back()->section->Reserve = (1 + paddingsize) * 64; } } } } /******************************************************************************/ void ImageHeaderTable::Link(BootImage &bi) { /* Realigning the data ptr is necessary because Section->Data ptr gets changed in the RSAAuthenticationContext::ResizeIfNecessary() function call */ RealignSectionDataPtr(); slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; if(bi.partitionHeaderTable->firstSection != NULL) { SetFirstPartitionHeaderOffset((uint32_t)bi.partitionHeaderTable->firstSection->WordAddress()); } if(bi.imageList.size() != 0) { if(bi.imageList.front()->section != NULL) { uint32_t size = (bi.imageList.size() > 0) ? (uint32_t) bi.imageList.front()->section->WordAddress() : 0; SetFirstImageHeaderOffset(size); } } SetPartitionCount((uint32_t)bi.partitionHeaderList.size()); uint32_t acOffset = (bi.headerAC != 0) ? (bi.headerAC->section->WordAddress()) : 0; SetHeaderAuthCertificateOffset(acOffset); for( std::list::iterator currentImage = imageHeaderList.begin(); currentImage != imageHeaderList.end(); ) { std::list::iterator prevImage = currentImage; currentImage++; if (currentImage == imageHeaderList.end()) { (*prevImage)->Link(bi, (*prevImage)->GetPartitionHeaderList().front(), 0); } else { (*prevImage)->Link(bi, (*prevImage)->GetPartitionHeaderList().front(), (*currentImage)); } } SetBootDevice(bi.bifOptions->GetBootDevice()); SetReservedFields(); SetChecksum(); } /******************************************************************************/ bool IsBootloaderx(ImageHeader* x) { return x->IsBootloader(); } /******************************************************************************/ ImageHeader* ImageHeaderTable::GetFSBLImageHeader() { std::list::iterator x = std::find_if(imageHeaderList.begin(),imageHeaderList.end(),IsBootloaderx); if (x == imageHeaderList.end()) { return NULL; } else { return (*x); } } /******************************************************************************/ ImageHeader::ImageHeader(std::string& filename) : Filename(filename) , domain(Domain::PS) , Auth(0) , Encrypt(0) , Checksum(0) , Bootloader(false) , Boot(false) , Multiboot(false) , Noautostart(false) , Protected(false) , Static(false) , User(false) , PartOwner(PartitionOwner::FSBL) , pmuFwSize(0) , fsblFwSize(0) , totalPmuFwSize(0) , totalFsblFwSize(0) , sourceAddr(0) , trustzone(TrustZone::NonSecure) , exceptionLevel(ExceptionLevel::EL3) , early_handoff(false) , hivec(false) , xipMode(false) , destCpu(DestinationCPU::NONE) , destDevice(DestinationDevice::DEST_DEV_PS) , elfClass(ElfClass::ELFCLASS32) , slaveBootSplitMode(false) , fullBhSize(0) , allHdrSize(0) , defEncrBlockSize(0) , authBlock(0) , isUserPartitionNum(false) , userPartitionNum(0) , spkId(0x000000000) , spkSelect(1) , ppkSelect(0) , generateAesKeyFile(false) , partitionUid(0) , pmcdataSize(0) , bufferSize(0) , buffer(NULL) , totalpmcdataSize(0) , ihMemCpyAddr(0xFFFFFFFFFFFFFFFF) , ihDelayLoad(false) , ihDelayHandoff(false) , authType(Authentication::None) , bigEndian(false) , a32Mode(false) , updateReserveInPh(false) , keySrc(KeySource::None) , partitionType(PartitionType::RESERVED) , partitionRevokeId(0) , dpacm(DpaCM::DpaCMDisable) , isSlrPartition(false) , pufHdLoc(PufHdLoc::PUFinEFuse) , imageId(0) , uniqueId(0) , parentUniqueId(0) , functionId(0) , uidInfoFoundInCdo(false) , isIhFullPowerDomain(false) , isIhLowPowerDomain(false) , isIhPLPowerDomain(false) , isIhSystemPowerDomain(false) , lockstep(false) , cluster(0) , delayAuth(false) , tcmBoot(false) { } /******************************************************************************/ ImageHeader::ImageHeader(std::ifstream& ifs) : Filename("") , domain(Domain::PS) , Auth(0) , Encrypt(0) , Checksum(0) , Bootloader(false) , Boot(false) , Multiboot(false) , Noautostart(false) , Protected(false) , Static(false) , User(false) , PartOwner(PartitionOwner::FSBL) , pmuFwSize(0) , fsblFwSize(0) , totalPmuFwSize(0) , totalFsblFwSize(0) , sourceAddr(0) , trustzone(TrustZone::NonSecure) , exceptionLevel(ExceptionLevel::EL3) , early_handoff(false) , hivec(false) , xipMode(false) , destCpu(DestinationCPU::NONE) , destDevice(DestinationDevice::DEST_DEV_PS) , elfClass(ElfClass::ELFCLASS32) , slaveBootSplitMode(false) , fullBhSize(0) , allHdrSize(0) , defEncrBlockSize(0) , authBlock(0) , isUserPartitionNum(false) , userPartitionNum(0) , spkId(0x000000000) , spkSelect(1) , ppkSelect(0) , generateAesKeyFile(false) , partitionUid(0) , pmcdataSize(0) , bufferSize(0) , buffer(NULL) , totalpmcdataSize(0) , ihMemCpyAddr(0xFFFFFFFFFFFFFFFF) , ihDelayLoad(false) , ihDelayHandoff(false) , authType(Authentication::None) , bigEndian(false) , a32Mode(false) , updateReserveInPh(false) , keySrc(KeySource::None) , partitionType(PartitionType::RESERVED) , partitionRevokeId(0) , dpacm(DpaCM::DpaCMDisable) , isSlrPartition(false) , pufHdLoc(PufHdLoc::PUFinEFuse) , imageId(0) , uniqueId(0) , parentUniqueId(0) , functionId(0) , uidInfoFoundInCdo(false) , isIhFullPowerDomain(false) , isIhLowPowerDomain(false) , isIhPLPowerDomain(false) , isIhSystemPowerDomain(false) , lockstep(false) , cluster(0) , delayAuth(false) , tcmBoot(false) { } /******************************************************************************/ ImageHeader::ImageHeader(uint8_t* data, uint64_t len) : Filename("") , domain(Domain::PS) , Auth(0) , Encrypt(0) , Checksum(0) , Bootloader(false) , Boot(false) , Multiboot(false) , Noautostart(false) , Protected(false) , Static(false) , User(false) , PartOwner(PartitionOwner::FSBL) , pmuFwSize(0) , fsblFwSize(0) , totalPmuFwSize(0) , totalFsblFwSize(0) , sourceAddr(0) , trustzone(TrustZone::NonSecure) , exceptionLevel(ExceptionLevel::EL3) , early_handoff(false) , hivec(false) , xipMode(false) , destCpu(DestinationCPU::NONE) , destDevice(DestinationDevice::DEST_DEV_PS) , partitionUid(0) , elfClass(ElfClass::ELFCLASS32) , slaveBootSplitMode(false) , fullBhSize(0) , allHdrSize(0) , authBlock(0) , pmcdataSize(0) , totalpmcdataSize(0) , buffer(data) , bufferSize(len) , generateAesKeyFile(false) , ihMemCpyAddr(0xFFFFFFFFFFFFFFFF) , ihDelayLoad(false) , ihDelayHandoff(false) , authType(Authentication::None) , isUserPartitionNum(false) , userPartitionNum(0) , spkId(0x000000000) , spkSelect(1) , ppkSelect(0) , defEncrBlockSize(0) , bigEndian(false) , a32Mode(false) , updateReserveInPh(false) , keySrc(KeySource::None) , partitionType(PartitionType::RESERVED) , partitionRevokeId(0) , dpacm(DpaCM::DpaCMDisable) , isSlrPartition(false) , pufHdLoc(PufHdLoc::PUFinEFuse) , imageId(0) , uniqueId(0) , parentUniqueId(0) , functionId(0) , uidInfoFoundInCdo(false) , isIhFullPowerDomain(false) , isIhLowPowerDomain(false) , isIhPLPowerDomain(false) , isIhSystemPowerDomain(false) , lockstep(false) , cluster(0) , delayAuth(false) , tcmBoot(false) { } /******************************************************************************/ void ImageHeader::Relink() { for(std::list::iterator i = partitionHeaderList.begin(); i!=partitionHeaderList.end();i++) { (*i)->imageHeader = this; } } /******************************************************************************/ void ImageHeader::ImportElf(BootImage& bi) { uint8_t proc_state = 0; ByteFile data(Filename); /* Get the ELF Class format - 32-bit elf vs 64-bit elf */ elfClass = GetElfClass(data.bytes); ElfFormat* elf = ElfFormat::GetElfFormat(elfClass, data.bytes, &proc_state); /* Check for no. of executable sections & non-zero size LOAD sections */ uint8_t exec_count = 0; non_zero_elf_sec_count = 0; for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { if (elf->GetProgramHeaderFlags(iprog) & PF_X) { exec_count++; } if ((elf->GetProgramHeaderFileSize(iprog) > 0) && (elf->GetProgramHeaderType(iprog) == xPT_LOAD)) { non_zero_elf_sec_count++; } } if (non_zero_elf_sec_count == 0) { LOG_ERROR("No non-empty program sections in %s", Filename.c_str()); } CreateElfPartitions(bi, elf, proc_state); } /******************************************************************************/ uint8_t* ImageHeader::CombineElfSections(ElfFormat* elf, Binary::Length_t* p_size, Binary::Address_t* p_addr) { // Variables for combining sections uint32_t num_hdrs = 0; Binary::Length_t size = 0; Binary::Length_t prev_end = 0; Binary::Length_t total_size = 0; Binary::Address_t addr = 0; Binary::Address_t offset = 0; uint8_t* p_data = NULL; /* Loop through all the program headers and populate the fields exec, load address etc. */ for (uint8_t iprog = 0; iprog < elf->programHdrEntryCount; iprog++) { size = elf->GetProgramHeaderFileSize(iprog); addr = elf->GetPhysicalAddress(iprog); /* Only loadable sections with non-zero size are considered */ if ((elf->GetProgramHeaderType(iprog) == xPT_LOAD) && (size > 0)) { num_hdrs++; /* Consider load address of first section */ if (num_hdrs == 1) { *p_addr = addr; } else { /* Calculate filler bytes and pad to combine different sections */ Binary::Length_t filler_bytes = addr - prev_end; if (filler_bytes != 0) { total_size += filler_bytes; p_data = (uint8_t*)realloc(p_data, total_size); memset(p_data + offset, 0, filler_bytes); offset = total_size; } } total_size += size; p_data = (uint8_t*)realloc(p_data, total_size); memcpy(p_data + offset, elf->GetProgramHeaderData(iprog), size); prev_end = addr + size; *p_size = offset = total_size; /* Loop through till last entry */ if (iprog < elf->programHdrEntryCount - 1) { continue; } } } return p_data; } /******************************************************************************/ uint8_t* ImageHeader::GetElfSections(ElfFormat* elf, Binary::Length_t* tsize, Binary::Address_t* addr, uint32_t iprog) { /* Only loadable sections with non-size are considered */ if ((elf->GetProgramHeaderType(iprog) == xPT_LOAD) && (elf->GetProgramHeaderFileSize(iprog) > 0)) { *tsize = elf->GetProgramHeaderFileSize(iprog); *addr = elf->GetPhysicalAddress(iprog); return elf->GetProgramHeaderData(iprog); } return NULL; } /******************************************************************************/ void ImageHeader::SetPmuFwSizeIh(uint32_t size) { pmuFwSize = size; } /******************************************************************************/ void ImageHeader::SetFsblFwSizeIh(uint32_t size) { fsblFwSize = size; } /******************************************************************************/ void ImageHeader::SetTotalPmuFwSizeIh(uint32_t size) { totalPmuFwSize = size; } /******************************************************************************/ void ImageHeader::SetTotalPmcDataSizeIh(uint32_t size) { totalpmcdataSize = size; } /******************************************************************************/ void ImageHeader::SetPmcDataSizeIh(uint32_t size) { pmcdataSize = size; } /******************************************************************************/ void ImageHeader::SetTotalFsblFwSizeIh(uint32_t size) { if(IsBootloader()) { totalFsblFwSize = size; } } /******************************************************************************/ void ImageHeader::SetTotalPmcFwSizeIh(uint32_t size) { totalpmcdataSize = size; } /******************************************************************************/ void ImageHeader::SetFsblSourceAddrIh(Binary::Address_t addr) { if(IsBootloader()) { sourceAddr = addr; } } /******************************************************************************/ uint32_t ImageHeader::GetPmuFwSizeIh(void) { return pmuFwSize; } /******************************************************************************/ uint32_t ImageHeader::GetFsblFwSizeIh(void) { if(IsBootloader()) { return fsblFwSize; } return 0; } /******************************************************************************/ uint32_t ImageHeader::GetTotalPmuFwSizeIh(void) { if(IsBootloader()) { return totalPmuFwSize; } return 0; } /******************************************************************************/ uint32_t ImageHeader::GetTotalFsblFwSizeIh(void) { return totalFsblFwSize; } /******************************************************************************/ Binary::Address_t ImageHeader::GetFsblSourceAddrIh(void) { return sourceAddr; } /******************************************************************************/ std::vector& ImageHeader::GetEncrBlocksList(void) { return encrBlocks; } /******************************************************************************/ uint32_t ImageHeader::GetDefaultEncrBlockSize(void) { return defEncrBlockSize; } /******************************************************************************/ void ImageHeader::InsertEncrBlocksList(uint32_t blk) { encrBlocks.push_back(blk); } /******************************************************************************/ void ImageHeader::SetDefaultEncrBlockSize(uint32_t blk) { defEncrBlockSize = blk; } /******************************************************************************/ ElfClass::Type ImageHeader::GetElfClass(uint8_t* elfdata) { return (ElfClass::Type)elfdata[EI_CLASS]; } /******************************************************************************/ void ImageHeader::SetDestDevice(DestinationDevice::Type type) { destDevice = type; } /******************************************************************************/ void ImageHeader::SetDestCpu(DestinationCPU::Type type) { static bool destCpuPmuExists = false; /* Destination Device will be deprecated in future, so set it to dest_cpu = pmu */ destCpu = type; if (destCpu == DestinationCPU::PMU) { destDevice = DestinationDevice::DEST_DEV_PMU; } else if (destDevice == DestinationDevice::DEST_DEV_PMU) { destCpu = DestinationCPU::PMU; } if (destCpu == DestinationCPU::PMU && destCpuPmuExists) { //LOG_ERROR("Bif attribute Error!!!'core=psm/pmu' cannot be specified on multiple partitions."); } else if (destCpu == DestinationCPU::PMU) { destCpuPmuExists = true; } } /******************************************************************************/ size_t ImageHeader::GetAuthBlock(void) { return (authBlock); } /******************************************************************************/ uint32_t ImageHeader::GetTotalPmcFwSizeIh(void) { if (IsBootloader()) { return totalpmcdataSize; } return 0; } /******************************************************************************/ uint32_t ImageHeader::GetPmcFwSizeIh(void) { return pmcdataSize; } /******************************************************************************/ uint32_t ImageHeader::GetImageId(void) { return imageId; } /******************************************************************************/ uint32_t ImageHeader::GetParentUniqueId(void) { return parentUniqueId; } /******************************************************************************/ uint32_t ImageHeader::GetUniqueId(void) { return uniqueId; } /******************************************************************************/ uint32_t ImageHeader::GetFunctionId(void) { return functionId; } /******************************************************************************/ bool ImageHeader::IsUidInfoFoundInCdo(void) { return uidInfoFoundInCdo; } /******************************************************************************/ bool ImageHeader::IsElf(std::string line) { bool status = false; if ((line.at(0) == 0x7f) && (line.at(1) == 0x45) && (line.at(2) == 0x4C) && (line.at(3) == 0x46)) { status = true; } return status; } xilinx-bootgen-2024.2/imageheadertable.h000077500000000000000000000432301475706442400202070ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _IMAGEHEADERTABLE_H_ #define _IMAGEHEADERTABLE_H_ /* Zynq/ZynqMp Version Updates */ #define VERSION_ZYNQ_ZYNQMP 0x01020000 /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "authentication.h" #include "elftools.h" typedef enum { BOOT, CONFIG, MASTER_CDO, } SlrPdiType; struct SlrId { typedef enum { INVALID, SLR_1, SLR_2, SLR_3, MASTER, } Type; }; typedef struct { std::string file; SlrId::Type index; SlrPdiType type; } SlrPdiInfo; typedef struct { std::string file; uint32_t id; } ImageStorePdiInfo; /* Forward Class References */ class BaseThing; class Options; class BootImage; class Section; class PartitionHeader; class ChecksumContext; class MD5ChecksumContext; class AuthenticationContext; class EncryptionContext; class BifOptions; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ImageHeader : public BaseThing { public: ImageHeader() {} ImageHeader(std::string& filename); ImageHeader(std::ifstream& f); ImageHeader(uint8_t* data, uint64_t len); virtual ~ImageHeader() {} virtual void Build(BootImage& bi, Binary& cache) { return; } virtual void Link(BootImage &bi, PartitionHeader* partitionHeader, ImageHeader* nextImageheader) { return; } virtual void ValidateEncryptionAttributes(BootImage & bi) {}; void Relink(); virtual void SetNextImageHeaderOffset(uint32_t addr) { } virtual void SetPartitionHeaderOffset(uint32_t addr) { } virtual void SetDataSectionCount(uint32_t cnt) { } virtual void SetImageNameLength(uint32_t len) { } virtual void SetImageName(void) { } virtual Binary::Address_t GetNextImageHeaderOffset(void) { return 0; } virtual uint32_t GetPartitionHeaderOffset(void) { return 0; } virtual uint32_t GetDataSectionCount(void) { return 0; } virtual uint32_t GetImageNameLength(void) { return 0; } virtual uint32_t GetPartitionUid(void) { return 0; } virtual KeySource::Type GetEncryptionKeySrc() { return KeySource::None; } int NumPartitions() { return (int)partitionHeaderList.size(); } void SetDomain(Domain::Type type) { domain = type; } void SetName(std::string name) { Name = name; } void SetFilename(std::string name) { Filename = name; } void SetBootloader(bool flag) { Bootloader = flag; } void SetBootFlag(bool flag) { Boot = flag; } void SetMultibootFlag(bool flag) { Multiboot = flag; } void SetNoAutoStartFlag(bool flag) { Noautostart = flag; } void SetProtectedFlag(bool flag) { Protected = flag; } void SetStaticFlag(bool flag) { Static = flag; } void SetUserFlag(bool flag) { User = flag; } void SetEarlyHandoff(bool flag) { early_handoff = flag; } void SetHivec(bool flag) { hivec = flag; } void SetSlrPartition(bool flag) { isSlrPartition = flag; } void SetAuthenticationType(Authentication::Type type) { authType = type; } void SetAuthContext(AuthenticationContext* ctx) { Auth = ctx; } void SetEncryptContext(EncryptionContext* ctx) { Encrypt = ctx; } void SetChecksumContext(ChecksumContext* ctx) { Checksum = ctx; } void SetPartOwner(PartitionOwner::Type type) { PartOwner = type; } void SetPartitionType(PartitionType::Type type) { partitionType = type; } void SetDestCpu(DestinationCPU::Type type); void SetDestDevice(DestinationDevice::Type type); void SetExceptionLevel(ExceptionLevel::Type type) { exceptionLevel = type; } void SetTrustZone(TrustZone::Type type) { trustzone = type; } void SetAlignment(Override data) { Alignment = data; } void SetOffset(Override data) { Offset = data; } void SetReserve(Override data, bool updateReserveFlag) { Reserve = data; updateReserveInPh = updateReserveFlag;} void SetLoad(Override data) { Load = data; } void SetStartup(Override data) { Startup = data; } void InsertPartitionHeaderList(PartitionHeader* ph) { partitionHeaderList.push_back(ph); } void SetFileList(std::vector files) { filelist = files; } virtual void SetAuthBlock(size_t blockSize, bool flag) { }; virtual void SetPartitionUid(uint32_t id) { }; virtual void SetBigEndian(bool) { }; virtual void SetA32ExecMode(bool) { }; virtual void SetDpacm(DpaCM::Type) { }; virtual void SetPufHdLocation(PufHdLoc::Type type) { }; virtual void SetClusterNum(uint8_t num) { cluster = num; } virtual void SetLockStepFlag(bool flag) { lockstep = flag; } virtual void SetDelayAuthFlag (bool flag) { delayAuth = flag; } virtual void SetTcmBoot(bool flag) { tcmBoot = flag; } virtual void SetEncryptionKeySrc(KeySource::Type type) { }; virtual void SetPartitionRevocationId(uint32_t id) { }; virtual uint32_t GetPartitionRevocationId() { return 0; } virtual void SetSlrBootPartitions(std::list) { }; virtual void SetSlrConfigPartitions(std::list) { }; virtual void SetWriteImageStorePartitions(ImageStorePdiInfo*) { }; void SetMemCopyAddress(uint64_t addr) { ihMemCpyAddr = addr; } void SetDelayLoadHandOffFlags(bool load_flag, bool handoff_flag) { ihDelayLoad = load_flag; ihDelayHandoff = handoff_flag; } void SetUserPartitionNum(size_t num) { userPartitionNum = num; if (num != 0) { isUserPartitionNum = true; } } Domain::Type GetDomain(void) { return domain; } std::string GetName(void) { return Name; } std::string GetFilename(void) { return Filename; } bool IsBootloader(void) { return Bootloader; } bool IsBootFlagSet(void) { return Boot; } bool IsMultibootFlagSet(void) { return Multiboot; } bool IsNoAutoStartFlagSet(void) { return Noautostart; } bool IsProtectedFlagSet(void) { return Protected; } bool IsStaticFlagSet(void) { return Static; } bool IsUserFlagSet(void) { return User; } bool GetEarlyHandoff(void) { return early_handoff; } bool GetHivec(void) { return hivec; } bool IsSlrPartition(void) { return isSlrPartition; } Authentication::Type GetAuthenticationType(void) { return authType; } AuthenticationContext* GetAuthContext(void) { return Auth; } EncryptionContext* GetEncryptContext(void) { return Encrypt; } ChecksumContext* GetChecksumContext(void) { return Checksum; } PartitionOwner::Type GetPartOwner(void) { return PartOwner; } PartitionType::Type GetPartitionType(void) { return partitionType; } DestinationCPU::Type GetDestCpu(void) { return destCpu; } DestinationDevice::Type GetDestinationDevice(void) { return destDevice; } ExceptionLevel::Type GetExceptionLevel(void) { return exceptionLevel; } TrustZone::Type GetTrustZone(void) { return trustzone; } Override GetAlignment(void) { return Alignment; } Override GetOffset(void) { return Offset; } Override GetReserve(void) { return Reserve; } Override GetLoad(void) { return Load; } Override GetStartup(void) { return Startup; } std::list& GetPartitionHeaderList(void) { return partitionHeaderList; } ElfClass::Type GetElfClass(uint8_t* elfdata); size_t GetAuthBlock(void); size_t GetUserPartitionNum(void) { return userPartitionNum; } bool IsUserPartitionNumSet(void) { return isUserPartitionNum; } uint64_t GetMemCopyAddress(void) { return ihMemCpyAddr; } virtual DpaCM::Type GetDpacm(void) { return DpaCM::DpaCMDisable; } virtual std::string GetKekIV() { return ""; } virtual PufHdLoc::Type GetPufHdLocation(void) { return PufHdLoc::PUFinEFuse; } std::vector GetFileList(void) { return filelist; } virtual uint8_t GetClusterNum(void) { return cluster; } virtual bool GetLockStepFlag(void) { return lockstep; } virtual bool GetDelayAuthFlag(void) { return delayAuth; } virtual bool GetTcmBootFlag(void) { return tcmBoot; } // For multiple key files and auth parameters void SetAesKeyFile(std::string filename) { aesKeyFile = filename; } void SetAesKeyFileGeneration(bool flag) { generateAesKeyFile = flag; } void SetPpkFile(std::string filename) { ppkFile = filename; } void SetPskFile(std::string filename) { pskFile = filename; } void SetSpkFile(std::string filename) { spkFile = filename; } void SetSskFile(std::string filename) { sskFile = filename; } void SetSpkSignFile(std::string filename) { spkSignFile = filename; } void SetBhSignFile(std::string filename) { bhSignFile = filename; } void SetPpkSelect(uint32_t id) { ppkSelect = id; } void SetSpkSelect(uint32_t id) { spkSelect = id; } void SetSpkId(uint32_t id) { spkId = id; } std::string GetAesKeyFile (void) { return aesKeyFile; } bool GetAesKeyFileGeneration(void) { return generateAesKeyFile; } std::string GetPpkFile(void) { return ppkFile; } std::string GetPskFile(void) { return pskFile; } std::string GetSpkFile (void) { return spkFile; } std::string GetSskFile (void) { return sskFile; } std::string GetSpkSignFile (void) { return spkSignFile; } std::string GetBhSignFile (void) { return bhSignFile; } uint32_t GetPpkSelect(void) { return ppkSelect; } uint32_t GetSpkSelect(void) { return spkSelect; } uint32_t GetSpkId(void) { return spkId; } void SetPmuFwSizeIh(uint32_t); void SetFsblFwSizeIh(uint32_t); void SetTotalPmuFwSizeIh(uint32_t); void SetTotalFsblFwSizeIh(uint32_t); void SetFsblSourceAddrIh(Binary::Address_t); void SetTotalPmcDataSizeIh(uint32_t size); void SetPmcDataSizeIh(uint32_t size); void SetTotalPmcFwSizeIh(uint32_t size); uint32_t GetPmuFwSizeIh(void); uint32_t GetFsblFwSizeIh(void); uint32_t GetTotalPmuFwSizeIh(void); uint32_t GetTotalFsblFwSizeIh(void); Binary::Address_t GetFsblSourceAddrIh(void); std::vector& GetEncrBlocksList(void); uint32_t GetDefaultEncrBlockSize(void); uint32_t GetTotalPmcFwSizeIh(void); uint32_t GetPmcFwSizeIh(void); void InsertEncrBlocksList(uint32_t blk); void SetDefaultEncrBlockSize(uint32_t blk); uint32_t GetImageId(void); uint32_t GetParentUniqueId(void); uint32_t GetUniqueId(void); uint32_t GetFunctionId(void); bool IsUidInfoFoundInCdo(void); bool GetPLPowerDomainFlag() { return isIhPLPowerDomain; } bool GetLowPowerDomainFlag() { return isIhLowPowerDomain; } bool GetFullPowerDomainFlag() { return isIhFullPowerDomain; } bool GetSystemPowerDomainFlag() { return isIhSystemPowerDomain; } protected: Domain::Type domain; uint8_t* buffer; uint64_t bufferSize; std::string Name; std::string Filename; std::vector filelist; bool Bootloader; bool Boot; bool Multiboot; bool Noautostart; bool Protected; bool Static; bool User; bool xipMode; bool early_handoff; bool hivec; bool lockstep; uint32_t cluster; uint32_t pmuFwSize; uint32_t pmcdataSize; uint32_t fsblFwSize; uint32_t totalPmuFwSize; uint32_t totalpmcdataSize; uint32_t totalFsblFwSize; uint8_t non_zero_elf_sec_count; Binary::Address_t sourceAddr; uint64_t ihMemCpyAddr; bool ihDelayLoad; bool ihDelayHandoff; bool isSlrPartition; bool isIhFullPowerDomain; bool isIhLowPowerDomain; bool isIhSystemPowerDomain; bool isIhPLPowerDomain; // For multiple key files & auth parameters std::string aesKeyFile; bool generateAesKeyFile; std::string ppkFile; std::string pskFile; std::string spkFile; std::string sskFile; std::string spkSignFile; std::string bhSignFile; uint32_t ppkSelect; uint32_t spkSelect; uint32_t spkId; bool delayAuth; Authentication::Type authType; AuthenticationContext* Auth; EncryptionContext* Encrypt; ChecksumContext* Checksum; PartitionType::Type partitionType; PartitionOwner::Type PartOwner; DestinationCPU::Type destCpu; DestinationDevice::Type destDevice; ExceptionLevel::Type exceptionLevel; TrustZone::Type trustzone; uint32_t partitionUid; uint32_t partitionRevokeId; KeySource::Type keySrc; Override Alignment; Override Offset; Override Reserve; Override Load; Override Startup; size_t userPartitionNum; bool isUserPartitionNum; bool a32Mode; bool bigEndian; bool updateReserveInPh; DpaCM::Type dpacm; PufHdLoc::Type pufHdLoc; std::string kekIvFile; bool tcmBoot; std::list partitionHeaderList; ElfClass::Type elfClass; std::vector encrBlocks; uint32_t defEncrBlockSize; size_t authBlock; virtual void ImportElf(BootImage& bi); virtual void ImportBit(BootImage& bi) { }; virtual void ImportBin(BootImage& bi) { }; virtual bool IsElf(std::string line); virtual void ImportFpgaDataFile(BootImage& bi) { }; uint8_t* CombineElfSections(ElfFormat* elf, Binary::Length_t* size, Binary::Address_t* load_addr); uint8_t* GetElfSections(ElfFormat* elf, Binary::Length_t* size, Binary::Address_t* load_addr, uint32_t iprog); virtual void CreateElfPartitions(BootImage& bi, ElfFormat* elf, uint8_t proc_state) {}; bool slaveBootSplitMode; uint32_t fullBhSize; uint32_t allHdrSize; std::list slrBootPdiInfo; std::list slrConfigPdiInfo; ImageStorePdiInfo* imageStorePdiInfo; uint32_t imageId; uint32_t uniqueId; uint32_t parentUniqueId; uint32_t functionId; bool uidInfoFoundInCdo; }; /******************************************************************************/ class ImageHeaderTable : public BaseThing { public: ImageHeaderTable() : slaveBootSplitMode(false) , fullBhSize(0) , allHdrSize(0) , metaHeaderLength(0) , metaHdrSecHdrIv(NULL) , metaHdrKeySrc(KeySource::None) , encrypt(NULL) , iht_optional_data(NULL) , iht_optional_data_length(0) , idCodeCheck(0) , nonApuSubSysCnt(0) { } virtual ~ImageHeaderTable() {} virtual void Build(BootImage& bi, Binary& cache); virtual void Link(BootImage& bi); virtual void RealignSectionDataPtr(void) = 0; ImageHeader* GetFSBLImageHeader(); std::list imageHeaderList; virtual void SetImageHeaderTableVersion(uint32_t version) = 0; virtual void SetHeaderTablesSize() {}; virtual void SetTotalMetaHdrLength(uint32_t size) {}; virtual void SetMetaHdrSecureHdrIv(uint8_t* iv) {}; virtual void SetMetaHdrKeySrc(KeySource::Type, BifOptions* bifOptions) {}; virtual void SetPartitionCount(uint32_t count) = 0; virtual void SetFirstPartitionHeaderOffset(uint32_t offset) = 0; virtual void SetFirstImageHeaderOffset(uint32_t offset) = 0; virtual void SetHeaderAuthCertificateOffset(uint32_t offset) = 0; virtual void SetReservedFields(void) = 0; virtual void SetChecksum(void) = 0; virtual void SetBootDevice(BootDevice::Type type) {}; virtual void SetBootDeviceAddress(uint32_t address) {}; virtual void ValidateSecurityCombinations(Authentication::Type, Encryption::Type, Checksum::Type) = 0; virtual void SetOptionalData(uint32_t*, uint32_t) {}; virtual void SetUserOptionalData(std::vector> optionalDataInfo, uint32_t hashTableSize) {}; virtual void SetXplmModulesData(BootImage& bi, uint32_t*, uint32_t) {}; virtual void SetOptionalDataSize(void) {}; virtual uint32_t GetImageHeaderTableVersion(void) { return 0; } virtual uint32_t GetPartitionCount(void) { return 0; } virtual uint32_t GetImageCount(void) { return 0; } virtual uint32_t GetFirstPartitionHeaderOffset(void) { return 0; } virtual uint32_t GetFirstImageHeaderOffset(void) { return 0; } virtual uint32_t GetHeaderAuthCertificateOffset(void) { return 0; } virtual uint8_t GetMaxNumOfPartitions(void) { return 0; } virtual uint32_t GetTotalMetaHdrLength(void) { return 0; } void SetEncryptContext(EncryptionContext* ctx) { encrypt = ctx; } EncryptionContext* GetEncryptContext(void) { return encrypt; } uint32_t metaHeaderLength; KeySource::Type metaHdrKeySrc; uint8_t* metaHdrSecHdrIv; void* iht_optional_data; uint32_t iht_optional_data_length; uint32_t copied_iht_optional_data_length; uint8_t idCodeCheck; int nonApuSubSysCnt; protected: bool slaveBootSplitMode; uint32_t fullBhSize; uint32_t allHdrSize; EncryptionContext* encrypt; }; #endif xilinx-bootgen-2024.2/kdf.cpp000077500000000000000000000721251475706442400160500ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include "kdf.h" #include #include #include #include #include #include #include #include using namespace std; /************************************************************************ Example of NIST SP 800-108 in Counter Mode i is chosen to be 32 bits. This allows the 128(2^32 -1) bits of keying material can be generated. L will be 40 bits which allows for the full amount of i. So Ko of 128(2^32 -1) bits of data can be and is limited by the size of i. If Ko is being used to generate both the 256-bit AES key and the 96-bit IV for AES-GCM, then this allows for about 1.56 x 10^9 key/IV pairs. Looking at worst case scenarios, key rolling every 32 AES encryption blocks would allow us to encrypt ~800 GB of data with a single root key. Because the CMAC implementation provided only handles even 128-bit blocks, the length of [i]2 || Label || 0x00 || Context || [L]2 must always be evenly divisible by 128 bits. The CMAC implementation needs fixed so the customer can provide any Context and Label. Just as an example, these values are being used i = 32 bits Label = 256 bits Separator = 8 bits Context = 48 bits L = 40 bits These are just arbitrary values. Really anything can be used and anything should be permitted for the Context and Label. The spec defines the separator. The i and L lengths are defined to sensible values for our implementation. divisible by 128. The same cmac key is used as the earlier cmac example. This would be the customer provided secret seed or root key. *************************************************************************/ #define VERBOSE_OUT_KDF kdfLogFile /* Read a big endian 32 bit word from a byte stream. */ #define read_big_endian_32( addr ) \ ( ( (uint32_t)( *( (uint8_t *)(addr) + 0 ) ) << 24 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 1 ) ) << 16 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 2 ) ) << 8 ) | \ (uint32_t)( *( (uint8_t *)(addr) + 3 ) ) ) /* Read a little endian 32 bit word from a byte stream. */ #define read_little_endian_32( addr ) \ ( ( (uint32_t)( *( (uint8_t *)(addr) + 3 ) ) << 24 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 2 ) ) << 16 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 1 ) ) << 8 ) | \ (uint32_t)( *( (uint8_t *)(addr) + 0 ) ) ) /* Write a big endian 32 bit word to a byte stream. */ #define write_big_endian_32( addr, value ) \ *( (uint8_t *)(addr) + 0 ) = ( ( (value) >> 24 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( ( (value) >> 16 ) & 0xFF ); \ *( (uint8_t *)(addr) + 2 ) = ( ( (value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 3 ) = ( (value) & 0xFF ); static const uint8_t sbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static const uint8_t rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; static const uint8_t Rcon[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; uint8_t expanded_key[240]; uint8_t cmac_key[32]; uint8_t K1[16]; uint8_t K2[16]; /******************************************************************************/ static void memcpy_be(uint8_t* dst, const uint32_t* src, size_t size) { uint32_t value = 0; uint8_t *addr; for (uint32_t i = 0; i= '0') && (str[char_index] <= '9')) { nibble = (str[char_index] - '0'); } else if ((str[char_index] >= 'a') && (str[char_index] <= 'f')) { nibble = (str[char_index] - 'a' + 10); } else if ((str[char_index] >= 'A') && (str[char_index] <= 'F')) { nibble = (str[char_index] - 'F' + 10); } else { nibble = 0; } /* Shift in the nibble */ dst[byte_index] = (dst[byte_index] << 4) | nibble; /* Increment the byte pointer as needed */ if (char_index % 2 == 1) { byte_index++; } } } /******************************************************************************/ void uint64_t_2_str(char *str, uint64_t *src, int word_count) { int word_index; int nibble_count; int mychar; for (word_index = 0; word_index> (60 - 4 * (nibble_count))) & 0xF; #ifdef __GNUC__ sprintf(&str[16 * word_index + nibble_count], "%x", mychar); #else sprintf_s(&str[16 * word_index + nibble_count], 64, "%x", mychar); #endif } } } /******************************************************************************/ static void rotate_word(uint8_t *t, int size, int stride, int offset) { uint8_t temp; int index; int shift_count; /* Count how many shifts happen */ for (shift_count = 0; shift_count> 7); } K1[15] = L[i] << 1; if ((L[0] & 0x80) != 0) { for (i = 0; i<16; i = i + 1) { K1[i] ^= Rb[i]; } } /* NIST SP 800-38B 6.1 Step 3 */ for (i = 0; i<15; i = i + 1) { K2[i] = (K1[i] << 1) | (K1[i + 1] >> 7); } K2[15] = K1[i] << 1; if ((K1[0] & 0x80) != 0) { for (i = 0; i<16; i = i + 1) { K2[i] ^= Rb[i]; } } } /******************************************************************************/ void cmac(uint8_t *mac, uint8_t *msg, int total_bytes) { int block; uint8_t ct[16]; uint8_t pt[16]; int lastBlockSize = total_bytes - ((total_bytes / 16) * 16); int total_blocks = (total_bytes / 16) + ((total_bytes % 16) == 0 ? 0 : 1); for (block = 0; block < total_blocks; block++) { copy_array_uint8_t(pt, &msg[16 * block], 16); if (block == total_blocks - 1) { if (lastBlockSize == 0) { xor_array_uint8_t(pt, K1, 16); } else { pt[lastBlockSize++] = 0x80; while (lastBlockSize & 15) pt[lastBlockSize++] = 0x00; xor_array_uint8_t(pt, K2, 16); } } if (block != 0) { xor_array_uint8_t(pt, ct, 16); } ecb_encrypt(cmac_key, pt, ct, 1); } copy_array_uint8_t(mac, ct, 16); } /*******************************************************************************************************************/ static void pack_hex(const std::string& hex_string, uint8_t* hex_data) { uint32_t hex_string_length = (uint32_t)hex_string.size(); if (hex_string_length & 1) { std::cout << "Hex String - " << hex_string.c_str() << " - does not have even no. of hex digits" << std::endl; exit(KDF_CAVP_HEXKEY_IMPROPER); } for (uint32_t i = 0; i < hex_string_length; i += 2) { std::string byte = hex_string.substr(i, 2); if (!isxdigit(byte[0]) || !isxdigit(byte[1])) { std::cout << "Hex String - " << hex_string.c_str() << " - is has a non hex digit" << std::endl; exit(KDF_CAVP_HEXKEY_IMPROPER); } *hex_data++ = (uint8_t)strtoul(byte.c_str(), NULL, 16); } } /******************************************************************************/ void Kdf::SetKdfLogFilename(std::string filename) { kdf_log_file = filename; } /******************************************************************************/ std::string Kdf::GetKdfLogFilename(void) { return kdf_log_file; } /******************************************************************************/ std::string Kdf::GetVersion(void) { return VERSION; } /******************************************************************************/ uint32_t Kdf::CounterModeKDF(uint32_t* k_in, uint32_t* fid, uint32_t fid_byte_length, uint32_t* ko_buf, uint32_t ko_bytes, bool reset_cntr) { if (fid_byte_length == 0) { std::cout << "Fixed Input Data is not available. Seed and Fixed Input Data are mandatory for KDF." << std::endl; return KDF_INPUT_FID_UNAVAILABLE; } if (k_in == NULL) { std::cout << "Seed is not available. Seed and Fixed Input Data are mandatory for KDF." << std::endl; return KDF_INPUT_SEED_UNAVAILABLE; } if((fixed_input_data_byte_length != fid_byte_length) || (fixed_input_data == NULL)) { fixed_input_data_byte_length = fid_byte_length; delete[] fixed_input_data; fixed_input_data = new uint8_t[fixed_input_data_byte_length]; } memcpy_be(fixed_input_data, fid, fixed_input_data_byte_length); /* This KDF accepts a seed of fixed length - 32bytes */ if (key_seed == NULL) { key_seed = new uint8_t[BYTES_PER_AES_SEED]; } memcpy_be(key_seed, k_in, BYTES_PER_AES_SEED); /* An example generating 4 key/IV pairs will have 4*(32+12) number_of_Ko_bytes. This should be flexible based on number of keys or key/iv pair required or it can just pull off key/IV as needed; it is acceptable to discard 32-bits and use 384 bits of Ko per 352-bits of key/iv pair. */ KDF(ko_bytes, reset_cntr); for (uint32_t index = 0; index < (ko_bytes/sizeof(uint32_t)); index++) { ko_buf[index] = read_little_endian_32( (key_out + (index * sizeof(uint32_t))) ); } return 0; } /******************************************************************************/ uint32_t Kdf::ParseKDFTestVectorFile(std::string filename) { std::cout << "Reading the Counter Mode KDF test file" << std::endl; std::ifstream testFile(filename.c_str()); if (!testFile) { std::cout << "Failure reading Counter Mode KDF test file - " << filename.c_str() << std::endl; return KDF_CAVP_TESTFILE_UNAVAILABLE; } while (testFile) { std::string word; testFile >> word; if (word == "") { return 0; } if (word == "L") { testFile >> word; if (word == "=") { testFile >> word; key_out_length = (uint32_t)strtoul(word.c_str(), NULL, 10); } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected '=''." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } else if (word == "KI") { testFile >> word; if (word == "=") { testFile >> word; if (word.size() != BYTES_PER_AES_SEED * 2) { std::cout << "KI must be 256 bits long - " << word.c_str() << std::endl; exit(KDF_CAVP_KI_LENGTH_IMPROPER); } key_seed = new uint8_t[(uint32_t)word.size()]; pack_hex(word, key_seed); } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected '=''." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } else if (word == "FixedInputDataByteLen") { testFile >> word; if (word == "=") { testFile >> word; fixed_input_data_byte_length = (uint32_t)strtoul(word.c_str(), NULL, 10); } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected '=''." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } else if (word == "FixedInputData") { testFile >> word; if (word == "=") { testFile >> word; if (fixed_input_data_byte_length > 0) { fixed_input_data = new uint8_t[fixed_input_data_byte_length]; pack_hex(word, fixed_input_data); } else { std::cout << "FixedInputDataByteLen is expected prior to FixedInputData" << std::endl; exit(KDF_CAVP_KI_LENGTH_IMPROPER); } } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected '=''." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } else if (word == "KO") { testFile >> word; if (word == "=") { testFile >> word; verify_ko = new uint8_t[key_out_length / 8]; pack_hex(word, verify_ko); } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected '=''." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } else { std::cout << "Error parsing KDF test vector file - " << filename.c_str() << "\n\t Expected 'L','KI','FixedInputDataByteLen', and 'FixedInputData'." << std::endl; return KDF_CAVP_TESTFILE_IMPROPER; } } return 0; } /******************************************************************************/ uint32_t Kdf::CAVPonCounterModeKDF(std::string filename) { uint32_t ret_value = ParseKDFTestVectorFile(filename); if (ret_value != 0) { return ret_value; } std::cout << "Generating Ko using Counter-Mode KDF..." << std::endl; std::cout << "KO = "; uint32_t number_of_Ko_bytes = key_out_length / 8; KDF(number_of_Ko_bytes); for (uint32_t y = 0; y < number_of_Ko_bytes; y++) { std::cout << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << uint32_t(key_out[y]); } std::cout << std::endl << std::endl; if (verify_ko != NULL) { if (memcmp(key_out, verify_ko, number_of_Ko_bytes) == 0) { std::cout << "Verified with given Ko" << std::endl; return 0; } else { std::cout << "Failed to verify with given Ko" << std::endl; return KDF_CAVP_VERIFY_KO_FAILED; } } std::cout << std::endl; return 0; } /******************************************************************************/ void Kdf::ResetKdfCounter() { for(int32_t i = 0; i < KDF_COUNTER_BYTES; ++i) { kdf_counter[i] = 0x00; } } /******************************************************************************/ bool Kdf::IsKdfCounterMax() { for(int32_t i = 0; i < KDF_COUNTER_BYTES; ++i) { if(kdf_counter[i] != 0xFF) { return false; } } /* This function should practically never return 'true' since the num of keys generated by KDF will always be less than 2^32 keys.i */ return true; } /******************************************************************************/ void Kdf::KDF(uint32_t ko_bytes, bool reset_cntr) { static std::ofstream kdfLogFile; if (kdf_log_file != "") { kdfLogFile.open(kdf_log_file.c_str(), std::fstream::app); VERBOSE_OUT_KDF << std::endl << "------------------------------------"; VERBOSE_OUT_KDF << std::endl << " Generating Ko of " << ko_bytes << " bytes"; VERBOSE_OUT_KDF << std::endl << "------------------------------------" << std::endl; } if (reset_cntr || IsKdfCounterMax()) { ResetKdfCounter(); } uint64_t number_of_input_bytes = KDF_COUNTER_BYTES + fixed_input_data_byte_length; uint8_t* input = new uint8_t[number_of_input_bytes]; if((ko_bytes != key_out_length) || (key_out == NULL)) { key_out_length = ko_bytes; delete[] key_out; key_out = new uint8_t[key_out_length]; } gen_cmac_subkeys(key_seed); copy_array_uint8_t(&input[0], kdf_counter, KDF_COUNTER_BYTES); copy_array_uint8_t(&input[KDF_COUNTER_BYTES], fixed_input_data, fixed_input_data_byte_length); uint32_t cmac_iterations = ko_bytes / 16; cmac_iterations += ((ko_bytes % 16) == 0 ? 0 : 1); /* Run the KDF for the amount of data needed */ uint32_t x; int32_t y; for (x = 0; x < cmac_iterations; x++) { /* Increment kdf_counter. The first value used is 1 */ y = 3; do { kdf_counter[y]++; y--; } while (kdf_counter[y + 1] == 0 && y >= 0); copy_array_uint8_t(&input[0], kdf_counter, KDF_COUNTER_BYTES); /* Run the PRF */ if (ko_bytes % 16 != 0 && x == cmac_iterations - 1) { uint8_t* last_ko = new uint8_t[16]; cmac(&last_ko[0], input, number_of_input_bytes); memcpy(&key_out[16 * x], &last_ko[0], (ko_bytes - (16 * x))); if (kdf_log_file != "") { for (y = 0; y < 16; y++) { VERBOSE_OUT_KDF << std::setfill('0') << std::setw(2) << std::hex << uint32_t(last_ko[y]); } VERBOSE_OUT_KDF << std::endl; } delete[] last_ko; } else { cmac(&key_out[16 * x], input, number_of_input_bytes); if (kdf_log_file != "") { for (y = 0; y < 16; y++) { VERBOSE_OUT_KDF << std::setfill('0') << std::setw(2) << std::hex << uint32_t(key_out[16 * x + y]); } VERBOSE_OUT_KDF << std::endl; } } } if (kdf_log_file != "") { kdfLogFile.close(); } delete[] input; } xilinx-bootgen-2024.2/kdf.h000077500000000000000000000064471475706442400155210ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /***************************************************************************** * * This source contains the implementation of the interface functions for secure * library. * * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- --- -------- ------------------------------------------------------- * 1.0 Ramya 08/27/2021 Initial release * ******************************************************************************/ #pragma once #ifndef _KDF_H_ #define _KDF_H_ #include #include #include #include #include #define VERSION "v1.0" #define BYTES_PER_AES_SEED 32 #define KDF_COUNTER_BYTES 4 /* Error Codes */ #define KDF_INPUT_FID_UNAVAILABLE 0x00000001 #define KDF_INPUT_SEED_UNAVAILABLE 0x00000002 #define KDF_CAVP_TESTFILE_UNAVAILABLE 0x00010001 #define KDF_CAVP_TESTFILE_IMPROPER 0x00010002 #define KDF_CAVP_KI_LENGTH_IMPROPER 0x00010003 #define KDF_CAVP_HEXKEY_IMPROPER 0x00010004 #define KDF_CAVP_VERIFY_KO_FAILED 0x00010005 #define KDF_CAVP_FID_LENGTH_IMPROPER 0x00010006 /********************************************************************************/ class Kdf { public: Kdf() : key_out_length(0) , key_seed(NULL) , fixed_input_data_byte_length(0) , fixed_input_data(NULL) , verify_ko(NULL) , key_out(NULL) , kdf_log_file("") { }; ~Kdf() { if (key_seed != NULL) { delete[] key_seed; } if (fixed_input_data != NULL) { delete[] fixed_input_data; } if (verify_ko != NULL) { delete[] verify_ko; } if(key_out != NULL) { delete[] key_out; } }; uint32_t CounterModeKDF(uint32_t* k_in, uint32_t* fid, uint32_t fid_byte_length, uint32_t* ko_buf, uint32_t ko_bytes, bool reset_cntr = true); uint32_t CAVPonCounterModeKDF(std::string filename); void ResetKdfCounter(); void SetKdfLogFilename(std::string filename); std::string GetKdfLogFilename(void); std::string GetVersion(void); private: uint8_t* key_out; uint8_t* key_seed; uint32_t key_out_length; uint8_t* verify_ko; uint8_t* fixed_input_data; uint32_t fixed_input_data_byte_length; uint32_t version; uint8_t kdf_counter[KDF_COUNTER_BYTES]; std::string kdf_log_file; void KDF(uint32_t ko_bytes, bool reset_cntr = true); uint32_t ParseKDFTestVectorFile(std::string filename); bool IsKdfCounterMax(); }; #endif xilinx-bootgen-2024.2/link.h000077500000000000000000000041021475706442400156740ustar00rootroot00000000000000#pragma once /******************************************************************************* * Copyright (c) 2007-2018 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * You may elect to redistribute this code under either of these licenses. * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ /* * Double linked list support. */ #ifndef D_link #define D_link #include typedef struct LINK LINK; struct LINK { LINK * next; LINK * prev; }; #define TCF_LIST_INIT(list) {&(list), &(list)} #define list_init(list) { \ (list)->next = (list)->prev = (list); \ } #define list_is_empty(list) ((list)->next == (list) || (list)->next == NULL) #define list_remove(item) { \ LINK * _l_ = item; \ _l_->prev->next = _l_->next; \ _l_->next->prev = _l_->prev; \ _l_->next = _l_->prev = _l_; \ } #define list_add_first(item, list) { \ (item)->next = (list)->next; (item)->prev = (list); \ (list)->next->prev = (item); (list)->next = (item); \ } #define list_add_last(item, list) { \ (item)->next = (list); (item)->prev = (list)->prev; \ (list)->prev->next = (item); (list)->prev = (item); \ } #define list_concat(item, list) { \ if (!list_is_empty(list)) { \ (item)->prev->next = (list)->next; \ (list)->next->prev = (item)->prev; \ (item)->prev = (list)->prev; \ (list)->prev->next = (item); \ } \ } #define list_foreach(trav, list) \ for (trav = (list)->next; trav != list; trav = trav->next) #define list_item_type(item, type, link) \ ((type *)((char *)(item) - offsetof(type, link))) #endif /* D_link */ xilinx-bootgen-2024.2/location.hh000066400000000000000000000116511475706442400167230ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Locations for Bison parsers in C++ Copyright (C) 2002-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file ../bisonflex/location.hh ** Define the BIF::location class. */ #ifndef YY_YY_BISONFLEX_LOCATION_HH_INCLUDED # define YY_YY_BISONFLEX_LOCATION_HH_INCLUDED # include "position.hh" /* Line 166 of location.cc */ #line 24 "../s/bif.y" namespace BIF { /* Line 166 of location.cc */ #line 48 "../bisonflex/location.hh" /// Abstract a location. class location { public: /// Construct a location from \a b to \a e. location (const position& b, const position& e) : begin (b) , end (e) { } /// Construct a 0-width location in \a p. explicit location (const position& p = position ()) : begin (p) , end (p) { } /// Construct a 0-width location in \a f, \a l, \a c. explicit location (std::string* f, unsigned int l = 1u, unsigned int c = 1u) : begin (f, l, c) , end (f, l, c) { } /// Initialization. void initialize (std::string* f = YY_NULL, unsigned int l = 1u, unsigned int c = 1u) { begin.initialize (f, l, c); end = begin; } /** \name Line and Column related manipulators ** \{ */ public: /// Reset initial location to final location. void step () { begin = end; } /// Extend the current location to the COUNT next columns. void columns (unsigned int count = 1) { end += count; } /// Extend the current location to the COUNT next lines. void lines (unsigned int count = 1) { end.lines (count); } /** \} */ public: /// Beginning of the located region. position begin; /// End of the located region. position end; }; /// Join two location objects to create a location. inline const location operator+ (const location& begin, const location& end) { location res = begin; res.end = end.end; return res; } /// Add two location objects. inline const location operator+ (const location& begin, unsigned int width) { location res = begin; res.columns (width); return res; } /// Add and assign a location. inline location& operator+= (location& res, unsigned int width) { res.columns (width); return res; } /// Compare two location objects. inline bool operator== (const location& loc1, const location& loc2) { return loc1.begin == loc2.begin && loc1.end == loc2.end; } /// Compare two location objects. inline bool operator!= (const location& loc1, const location& loc2) { return !(loc1 == loc2); } /** \brief Intercept output stream redirection. ** \param ostr the destination output stream ** \param loc a reference to the location to redirect ** ** Avoid duplicate information. */ template inline std::basic_ostream& operator<< (std::basic_ostream& ostr, const location& loc) { position last = loc.end - 1; ostr << loc.begin; if (last.filename && (!loc.begin.filename || *loc.begin.filename != *last.filename)) ostr << '-' << last; else if (loc.begin.line != last.line) ostr << '-' << last.line << '.' << last.column; else if (loc.begin.column != last.column) ostr << '-' << last.column; return ostr; } /* Line 296 of location.cc */ #line 24 "../s/bif.y" } // BIF /* Line 296 of location.cc */ #line 182 "../bisonflex/location.hh" #endif /* !YY_YY_BISONFLEX_LOCATION_HH_INCLUDED */ xilinx-bootgen-2024.2/logger.cpp000077500000000000000000000154531475706442400165640ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "logger.h" Logger* Logger::logger = NULL; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ Logger* Logger::Instance(void) { if(logger == NULL) { logger = new Logger(); } return logger; } /******************************************************************************/ void Logger::SetLogLevel(LogLevel::Type level) { log_level = level; if(!outFile.is_open()) { outFile.open("bootgen_log.txt"); } } /******************************************************************************/ LogLevel::Type Logger::GetLogLevel(void) { return log_level; } /******************************************************************************/ void Logger::Error(const char* format, ...) { if(log_level < LogLevel::ERROR) { return; } va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); Logger::outFile << "[ERROR] : " << msg.c_str() << std::endl; throw BootGenException(msg.c_str()); } /******************************************************************************/ void Logger::Warning(const char* format, ...) { if(log_level < LogLevel::WARNING) { return; } va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); std::cout << "[WARNING]: " << msg.c_str() << std::endl; Logger::outFile << "[WARNING]: " << msg.c_str() << std::endl; } /******************************************************************************/ void Logger::Info(const char* format, ...) { if(log_level < LogLevel::INFO) { return; } va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); std::cout << "[INFO] : " << msg.c_str() << std::endl; Logger::outFile << "[INFO] : " << msg.c_str() << std::endl; } /******************************************************************************/ void Logger::Debug(std::string filename, int line, const char* format, ...) { if(log_level < LogLevel::DEBUG) { return; }; va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); std::cout << "[DEBUG] : " << msg.c_str() << std::endl; std::cout << " " << "FILE: " << StringUtils::BaseName(filename).c_str() << std::endl; std::cout << " " << "LINE: " << line << std::endl; Logger::outFile << "[DEBUG] : " << msg.c_str() << std::endl; Logger::outFile << " " << "FILE: " << StringUtils::BaseName(filename).c_str() << std::endl; Logger::outFile << " " << "LINE: " << line << std::endl; } /******************************************************************************/ void Logger::Trace(const char* format, ...) { if(log_level < LogLevel::TRACE) { return; } va_list ap; va_start(ap, format); msg = StringUtils::vFormat(format,ap); va_end(ap); std::cout << "[TRACE] : " << msg.c_str() << std::endl; Logger::outFile << "[TRACE] : " << msg.c_str() << std::endl; } /******************************************************************************/ void Logger::DumpBinaryImage(Binary &cache) { if(log_level < LogLevel::INFO) { return; } std::cout << " -- Dump of Binary Image ----\n"; Logger::outFile << " -- Dump of Binary Image ----\n"; std::cout << " Offset" << " Length" << " Reserve"<< " Name\n"; Logger::outFile << " Offset" << " Length" << " Reserve"<< " Name\n"; for(SectionList::iterator i=cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& sec(**i); std::cout << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Address << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Length << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Reserve << " " << sec.Name << "" << std::endl; Logger::outFile << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Address << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Length << " " << std::hex << std::setfill('0') << std::setw(8) << sec.Reserve << " " << sec.Name << "" << std::endl; } std::cout << " -- End of Dump" << std::endl; Logger::outFile << " -- End of Dump" << std::endl; } /******************************************************************************/ void Logger::DumpBytes(uint8_t* ptr, int count) { if(log_level < LogLevel::TRACE) { return; } std::cout << " "; Logger::outFile << " "; for(int i=0;i #include #include #include #include "stringutils.h" #include "bootgenenum.h" #include "bootgenexception.h" #include "binary.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define DEBUG_STAMP __FILE__,__LINE__ #define LOG_LEVEL(a) Logger::Instance()->SetLogLevel(a) #define LOG_ERROR Logger::Instance()->Error #define LOG_WARNING Logger::Instance()->Warning #define LOG_INFO Logger::Instance()->Info #define LOG_DEBUG Logger::Instance()->Debug #define LOG_TRACE Logger::Instance()->Trace #define LOG_DUMP_IMAGE Logger::Instance()->DumpBinaryImage #define LOG_DUMP_BYTES Logger::Instance()->DumpBytes #define LOG_OUT Logger::Instance()->Out #define LOG_MSG Logger::Instance()->Message #define GET_LOG_LEVEL Logger::Instance()->GetLogLevel struct LogLevel { typedef enum { ERROR, WARNING, INFO, DEBUG, TRACE, } Type; }; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Logger { public: static Logger* Instance(void); void Error(const char* format, ...); void Warning(const char* format, ...); void Info(const char* format, ...); void Debug(std::string filename, int line, const char* format, ...); void Trace(const char* format, ...); void DumpBinaryImage(Binary &cache); void DumpBytes(uint8_t* ptr, int count); void Out(std::string stringout); void Message(const char* format, ...); void SetLogLevel(LogLevel::Type level); LogLevel::Type GetLogLevel(void); private: Logger() { log_level = LogLevel::WARNING; } ~Logger() { }; std::string msg; std::ofstream outFile; LogLevel::Type log_level; static Logger* logger; }; #endif xilinx-bootgen-2024.2/main.cpp000077500000000000000000000066441475706442400162330ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include "bootimage.h" #include "bootgenexception.h" #include "options.h" #include "bifoptions.h" #include "stringutils.h" #include "version.h" #include "encryption-zynqmp.h" #ifdef _WIN32 #include "openssl/ms/applink.c" #endif static const char* time_stamp = __TIME__; static const char* date_stamp = __DATE__; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ static void DisplayBanner() { char version[64], *year; strncpy(version, RDI_VERSION, sizeof version); version[sizeof version - 1] = '\0'; year = strtok(version, "."); LOG_MSG("\n"); LOG_MSG("****** %s v%s", PROGRAMNAME, RDI_VERSION); LOG_MSG(" **** Build date : %s-%s", date_stamp, time_stamp); LOG_MSG(" ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved."); LOG_MSG(" ** Copyright 2022-%s Advanced Micro Devices, Inc. All Rights Reserved.\n", year ? year : "2023"); } /******************************************************************************/ class BootGenApp { public: void Run(int argc, const char* argv[]) { Options options; options.ParseArgs(argc, argv); options.ProcessVerifyKDF(); options.ProcessReadImage(); std::string bifFile = options.GetBifFilename(); LOG_TRACE("BIF File: %s", bifFile.c_str()); if (bifFile.length() > 0) { BIF_File bif(bifFile); bif.Process(options); LOG_MSG("\n[INFO] : Bootimage generated successfully\n"); } } }; /******************************************************************************/ int main(int argc, const char* argv[]) { try { BootGenApp app; DisplayBanner(); app.Run(argc,argv); return 0; } catch(std::exception& ex) { std::cerr << "[ERROR] : " << ex.what() << std::endl; return 1; } catch(const char* msg) { std::cerr << "FATAL: Internal Assertion: " << msg << std::endl; return 2; } catch(...) { std::cerr << "FATAL: Unknown Exception caught."<< std::endl; return 3; } } xilinx-bootgen-2024.2/mcsfile.cpp000077500000000000000000000325261475706442400167270ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "outputfile.h" #include "systemutils.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define DATA_RECORD 0x00 #define END_OF_FILE_RECORD 0x01 #define EXTENDED_SEGMENT_ADDRESS_RECORD 0x02 #define START_SEGMENT_ADDRESS_RECORD 0x03 #define EXTENDED_LINEAR_ADDRESS_RECORD 0x04 #define START_LINEAR_ADDRESS_RECORD 0x05 #define LINEAR_ADDRESS_RECORD_BIGENDIAN /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ McsFile::McsFile() : pageAddress(0) , lineLength(16) , eofrWritten(false) , newFile(false) , shiftLength(0) , maskByte(0) { } /******************************************************************************/ void McsFile::Open() { std::string fName1 = filename.c_str(); std::string fName2 = filename.c_str(); /* QSPI Mode: It is useful for generating the output file in a split format, so that the files can directly be put in the repsective flashes DUAL PARALLEL Mode: 2 files are generated everytime DUAL STACKED Mode: 2 files are generated in case the image size > QSPI flash size */ if((qspiDualMode == QspiMode::PARALLEL_LQSPI) || (qspiDualMode == QspiMode::PARALLEL_GQSPI) || ((qspiDualMode == QspiMode::STACKED) && (totalImageSize > qspiSizeInBytes))) { fName1 = fName1.substr(0, fName1.find_last_of(".")); //remove extension fName1.append("_1.mcs"); fName2 = fName2.substr(0, fName2.find_last_of(".")); //remove extension fName2.append("_2.mcs"); ofs1.open(fName2.c_str()); if (!ofs1) { LOG_ERROR("MCS output file writing error !!! - %s", fName2.c_str()); } } ofs.open(fName1.c_str()); if (!ofs) { LOG_ERROR("MCS output file writing error !!! - %s", fName1.c_str()); } pageAddress = 0xFFFFFFFF; for(uint8_t i=0; i sizeof(buffer)) { LOG_DEBUG(DEBUG_STAMP, "Internal Error : LineLength (%d) > sizeof(buffer) (%d)", lineLength, sizeof(buffer)); LOG_ERROR("Internal Error : Line Length > sizeof(buffer)"); } memset(buffer,fillByte,sizeof(buffer)); Binary::Address_t lineAddress = start; while(lineAddress < end) { if(qspiDualMode == QspiMode::STACKED) { if(lineAddress >= qspiSizeInBytes) { lineAddress -= qspiSizeInBytes; end -= qspiSizeInBytes; if(!eofrWritten) { Write(0, END_OF_FILE_RECORD, NULL,0); eofrWritten = true; } newFile = true; } } Binary::Length_t bytesToWrite = (end - lineAddress); if (bytesToWrite > lineLength) bytesToWrite = lineLength; if(qspiDualMode == QspiMode::STACKED) { if ((bytesToWrite+lineAddress) > qspiSizeInBytes) { bytesToWrite = qspiSizeInBytes - lineAddress; } } Binary::Address_t newPage = lineAddress >> shiftLength; if (newPage != pageAddress) { uint8_t addr[2]; // Is the extended record big-endian? or little-endian? // The record address is big-endian, always. // The extended record is not well defined. // It looks like the old bootgen did little endian. #ifdef LINEAR_ADDRESS_RECORD_BIGENDIAN addr[0] = (uint8_t)(newPage >> 8); addr[1] = (uint8_t)newPage; #else addr[0] = (uint8_t)(newPage); addr[1] = (uint8_t)(newPage>>8); #endif Write(0,EXTENDED_LINEAR_ADDRESS_RECORD,addr,2); pageAddress = newPage; } Write(lineAddress & maskByte, DATA_RECORD, buffer, (int) bytesToWrite); lineAddress += bytesToWrite; } } /******************************************************************************/ void McsFile::Write(Binary::Address_t start, Binary::Length_t length, const uint8_t *buffer) { start = start - splitOffset; Binary::Address_t lineAddress = start; Binary::Address_t endAddress = start + length; while(lineAddress < endAddress) { if(qspiDualMode == QspiMode::STACKED) { if(lineAddress >= qspiSizeInBytes) { lineAddress -= qspiSizeInBytes; endAddress = start + length - qspiSizeInBytes; if(!eofrWritten) { Write(0, END_OF_FILE_RECORD, NULL,0); eofrWritten = true; } newFile = true; } } Binary::Length_t bytesToWrite = length; if (bytesToWrite > lineLength) bytesToWrite = lineLength; if(qspiDualMode == QspiMode::STACKED) { if ((bytesToWrite+lineAddress) > qspiSizeInBytes) { bytesToWrite = qspiSizeInBytes - lineAddress; } } Binary::Address_t newPage = lineAddress >> shiftLength; if (newPage != pageAddress) { uint8_t addr[2]; // Is the extended record big-endian? or little-endian? // The record address is big-endian, always. // The extended record is not well defined. // It looks like the old bootgen did little endian. #ifdef LINEAR_ADDRESS_RECORD_BIGENDIAN addr[0] = (uint8_t)(newPage >> 8); addr[1] = (uint8_t)newPage; #else addr[0] = (uint8_t)(newPage); addr[1] = (uint8_t)(newPage>>8); #endif Write(0,EXTENDED_LINEAR_ADDRESS_RECORD,addr,2); pageAddress = newPage; } Write(lineAddress & maskByte, DATA_RECORD, buffer, (int) bytesToWrite); lineAddress += bytesToWrite; buffer += bytesToWrite; length -= bytesToWrite; } } /******************************************************************************/ void McsFile::Write(uint32_t address, uint8_t command, const uint8_t* data, int len) { uint8_t buffer[128]; uint8_t writedata[128]; if((qspiDualMode != QspiMode::PARALLEL_LQSPI) && (qspiDualMode != QspiMode::PARALLEL_GQSPI)) { buffer[0] = len; buffer[1] = (uint8_t)(address >> 8); buffer[2] = (uint8_t)(address ); buffer[3] = command; memcpy(writedata, data, len); /* Only applicable to Data Records To match the MCS file generation in different interface formats according to write_cfgmem of Vivado */ if(command == DATA_RECORD) { } memcpy(buffer+4,writedata,len); uint8_t checksum = 0; for(int i=0;i> 8); buffer[2] = buffer2[2] = (uint8_t)(add ); buffer[3] = buffer2[3] = command; if (command == DATA_RECORD) { if (qspiDualMode == QspiMode::PARALLEL_LQSPI) { int k = 0; for (int i = 0; i < len; i += 2, k++) { //buffer[4+j] = (data[i] & 0xF0) | ((data[i+1] & 0xF0) >> 4); //buffer2[4+j] = ((data[i] & 0x0F) << 4) | (data[i+1] & 0x0F); uint8_t lsb = 0, lsbNxt = 0; uint8_t msb = 0, msbNxt = 0; uint8_t tempData = data[i]; uint8_t tempDataNxt = data[i + 1]; for (int j = 0; j < 4; j++) { lsb = lsb | ((tempData & 0x1) << j); msb = msb | (((tempData & 0x2) >> 1) << j); tempData = tempData >> 2; lsbNxt = lsbNxt | ((tempDataNxt & 0x1) << j); msbNxt = msbNxt | (((tempDataNxt & 0x2) >> 1) << j); tempDataNxt = tempDataNxt >> 2; } buffer[4 + k] = (lsb << 4) | lsbNxt; buffer2[4 + k] = (msb << 4) | msbNxt; } } else if (qspiDualMode == QspiMode::PARALLEL_GQSPI) { for (int i = 0, j = 0; i < len; i += 2, j++) { buffer[4 + j] = (data[i]); buffer2[4 + j] = (data[i + 1]); } } } else { memcpy(buffer + 4, data, length); memcpy(buffer2 + 4, data, length); } uint8_t checksum = 0; uint8_t checksum2 = 0; for(int i=0;i= 1020) # pragma once #endif #ifdef _MSC_VER # define ISL_HAS_DECLSPEC # define ISL_MSVC #endif #define yellow (unsigned) #define lemon const char #define green (signed) #define plum (char) #define brown (int) #define pink (const) #define black struct #define red const unsigned char #define white (const unsigned char *) #define coral a kind of red #define orchid const unsigned char #define orange black #define salmon a kind of orange #define purple black #define crimson const char #define tomato (const char *) #ifdef ISL_HAS_DECLSPEC # ifdef ISL_IOSTREAMS_SOURCE # define ISL_IOSTREAMS_DECL __declspec(dllexport) # else # define ISL_IOSTREAMS_DECL __declspec(dllimport) # endif # else # define ISL_IOSTREAMS_DECL __attribute__((visibility("default"))) # define ISL_IOSTREAMS_LOCAL __attribute__ ((visibility("hidden"))) #endif purple i0{red *i1; orchid *i2;i0(orchid *i1,red *i2,lemon *i3,crimson *i4):i1(i1),i2(i2),i3(i3),i4(i4){}crimson *i3; lemon *i4;}; #ifndef ISL_IOSTREAMS_DECL # define ISL_IOSTREAMS_DECL #endif #ifndef ISL_IOSTREAMS_LOCAL # define ISL_IOSTREAMS_LOCAL #endif #define test i0 #define test1 i1 #define test2 i2 #define test3 i3 #define test4 i4 #define obfs test ISL_IOSTREAMS_DECL void obfsk(void *); #endif xilinx-bootgen-2024.2/options.cpp000077500000000000000000000512721475706442400167770ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "options.h" #include "cmdoptionsscanner.h" #include "readimage.h" #include "readimage-zynq.h" #include "readimage-zynqmp.h" #include "readimage-versal.h" #include "logger.h" #include "encryption.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void Options::ParseArgs(int argc, const char * argv[]) { CO::FlexScanner scanner; CO::BisonParser parser(scanner,*this); std::string merged; for(int i=1;iGetVersion().c_str()); uint32_t ret_value = kdfCtx->CAVPonCounterModeKDF(GetKDFTestVectorFile()); delete kdfCtx; if (ret_value != 0) { exit(1); } else { exit(0); } } } } /******************************************************************************/ void Options::ProcessReadImage() { std::string readFile = GetReadImageFile(); if (readFile != "") { ReadImage* readImage = NULL; if (archType == Arch::ZYNQ) { readImage = new ZynqReadImage(readFile); } else if (archType == Arch::ZYNQMP) { readImage = new ZynqMpReadImage(readFile); } else if (archType == Arch::VERSAL) { readImage = new VersalReadImage(readFile); readImage->versalNetSeries = versalNetSeries; } if (GetVerifyImageOption()) { if (archType == Arch::ZYNQ) { LOG_ERROR("'-verify' option supported only for ZynqMP and Versal architectures, '-arch zynqmp','-arch versal'."); } readImage->VerifyAuthentication(GetVerifyImageOption()); } else { readImage->DisplayImageDetails(GetReadImageOption(), GetDumpOption(), GetDumpDirectory()); } delete readImage; exit(0); } } /******************************************************************************/ void Options::SetBifFilename (std::string filename) { std::ifstream f(filename.c_str()); if (!f) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } bifFileName = filename; } /******************************************************************************/ void Options::SetEncryptedKeySource (KeySource::Type type) { if(archType == Arch::ZYNQ) { if( (type!=KeySource::BbramRedKey) && (type!=KeySource::EfuseRedKey) && (type!=KeySource::None) ) { LOG_DEBUG(DEBUG_STAMP, "Key Source = %d", type); LOG_ERROR("BIF attribute error !!!\n\t\tUnknown option for 'keysrc_encryption' in BIF file\n\t\tZynq Architecture supports 'efuse' & 'bbram' key sources"); } } cmdEncryptOptions->encryptedKeySource = type; if (type != KeySource::None) { LOG_TRACE("Setting Encryption Key Source as %d", type); } } /******************************************************************************/ void Options::SetEncryptionKeyFile(std::string filename) { cmdEncryptOptions->encryptionKeyFile = filename; } /******************************************************************************/ void Options::SetHmac(std::string val) { cmdEncryptOptions->hmac = val; } /******************************************************************************/ void Options::SetKey0(std::string val) { cmdEncryptOptions->key0 = val; } /******************************************************************************/ void Options::SetStartCbc(std::string val) { cmdEncryptOptions->startCBC = val; } /******************************************************************************/ void Options::SetDoFill(bool flag) { doFill = flag; } /******************************************************************************/ void Options::SetOutputFillByte(uint8_t byte) { outputFillByte = byte; } /******************************************************************************/ void Options::SetSecureDebugAuthType(Authentication::Type type) { secureDebugAuthType = type; } /******************************************************************************/ void Options::SetSecureDebugImageFile(std::string file) { secureDebugImageFilename = file; } /******************************************************************************/ void Options::SetSplitType(File::Type type) { splitType = type; } /******************************************************************************/ void Options::SetProcessBitstreamType(File::Type type) { processBitstream = type; } /******************************************************************************/ void Options::SetDualQspiMode(QspiMode::Type type) { dualQspiMode = type; } /******************************************************************************/ void Options::SetQspiSize(uint16_t size) { if (size == 16 || size == 32 || size == 64 || size == 128) { qspiSize = size; } else { LOG_ERROR("Supported QSPI sizes (in MB) for -dual_qspi_mode option are 16, 32, 64 & 128"); } } /******************************************************************************/ void Options::SetOspiSize(uint16_t size) { if (size == 16 || size == 32 || size == 64 || size == 128 || size == 256) { qspiSize = size; } else { LOG_ERROR("Supported OSPI sizes (in MB) for -dual_ospi_mode option are 16, 32, 64, 128 & 256"); } } /******************************************************************************/ void Options::SetBaseAddress(Binary::Address_t addr) { baseAddress = addr; } /******************************************************************************/ void Options::SetDefaultAlignment(uint32_t val) { defaultAlignment = val; } /******************************************************************************/ void Options::SetDevicePartName(std::string partname) { devicePartName = partname; } /******************************************************************************/ void Options::SetKDFTestVectorFile(std::string filename) { kdfTestVectorFile = filename; } /******************************************************************************/ void Options::SetDevicePackageName(std::string packageName) { devicePackageName = packageName; } /******************************************************************************/ void Options::SetEfuseHashFileName(std::string filename) { efuseHashFileName = filename; } /******************************************************************************/ void Options::SetSpkSigFileName(std::string filename) { spkSignatureFileName = filename; } /******************************************************************************/ void Options::InsertOutputFileNames(std::string filename) { outputFileNames.push_back(filename); } /******************************************************************************/ void Options::SetLogLevel(LogLevel::Type level) { LOG_LEVEL(level); } /******************************************************************************/ void Options::SetArchType(Arch::Type type) { archType = type; if (archType == Arch::VERSALNET) { archType = Arch::VERSAL; versalNetSeries = true; } } /******************************************************************************/ void Options::SetGenerateHashes(bool flag) { generateHashes = flag; } /******************************************************************************/ void Options::SetNoAuthBlocksFlag(bool flag) { noauthblocks = flag; } /******************************************************************************/ void Options::SetOverwrite(bool flag) { overwriteMode = flag; } /******************************************************************************/ void Options::SetLegacyFlag(bool flag) { legacy = flag; } /******************************************************************************/ void Options::SetPadHeaderTable(bool flag) { padImageHeaderTable = flag; } /******************************************************************************/ void Options::SetNonBootingFlag(bool flag) { nonBooting = flag; } /******************************************************************************/ void Options::SetOutputMode(OutputMode::Type mode, File::Type fmt) { outputMode = mode; outputFmt = fmt; } /******************************************************************************/ void Options::SetDumpOption(DumpOption::Type type) { dumpOption = type; } /******************************************************************************/ void Options::SetVerifyImageOption(bool) { verifyImage = true; } /******************************************************************************/ void Options::SetReadImageOption(ReadImageOption::Type type) { readImageOption = type; } /******************************************************************************/ void Options::SetReadImageFile(std::string file) { readImageFile = file; } /******************************************************************************/ void Options::SetOverlayCDOFileName(std::string filename) { overlayCDOFile = filename; } /******************************************************************************/ void Options::SetOutType(File::Type type) { outType = type; } /******************************************************************************/ void Options::SetDumpDirectory(std::string path) { dumpPath = path; } /******************************************************************************/ void Options::SetAuthOptimization(void) { authOptimizationEnabled = true; } /******************************************************************************/ bool Options::IsAuthOptimizationEnabled(void) { return authOptimizationEnabled; } /******************************************************************************/ OutputMode::Type Options::GetOutputMode(void) { return outputMode; } /******************************************************************************/ File::Type Options::GetOutputFormat(void) { return outputFmt; } /******************************************************************************/ std::string Options::GetReadImageFile(void) { return readImageFile; } /******************************************************************************/ ReadImageOption::Type Options::GetReadImageOption(void) { return readImageOption; } /******************************************************************************/ bool Options::GetVerifyImageOption() { return verifyImage; } /******************************************************************************/ std::string Options::GetBifFilename(void) { return bifFileName; } //check-R chnage to always access key src from bif options /******************************************************************************/ KeySource::Type Options::GetEncryptedKeySource(void) { return cmdEncryptOptions->encryptedKeySource; } /******************************************************************************/ std::string Options::GetEncryptionKeyFile(void) { return cmdEncryptOptions->encryptionKeyFile; } /******************************************************************************/ std::string Options::GetHmac(void) { return cmdEncryptOptions->hmac; } /******************************************************************************/ std::string Options::GetKey0(void) { return cmdEncryptOptions->key0; } /******************************************************************************/ std::string Options::GetStartCbc(void) { return cmdEncryptOptions->startCBC; } /******************************************************************************/ Authentication::Type Options::GetSecureDebugAuthType(void) { return secureDebugAuthType; } /******************************************************************************/ std::string Options::GetSecureDebugImageFile(void) { return secureDebugImageFilename; } /******************************************************************************/ std::string Options::GetFsblFilename(void) { return fsblFilename; } /******************************************************************************/ bool Options::GetDoFill(void) { return doFill; } /******************************************************************************/ uint8_t Options::GetOutputFillByte(void) { return outputFillByte; } /******************************************************************************/ File::Type Options::GetSplitType(void) { return splitType; } /******************************************************************************/ File::Type Options::GetProcessBitstreamType(void) { return processBitstream; } /******************************************************************************/ QspiMode::Type Options::GetDualQspiMode(void) { return dualQspiMode; } /******************************************************************************/ uint16_t Options::GetQspiSize(void) { return qspiSize; } /******************************************************************************/ Binary::Address_t Options::GetBaseAddress(void) { return baseAddress; } /******************************************************************************/ uint32_t Options::GetDefaultAlignment(void) { return defaultAlignment; } /******************************************************************************/ std::string Options::GetDevicePartName(void) { return devicePartName; } /******************************************************************************/ std::string Options::GetKDFTestVectorFile(void) { return kdfTestVectorFile; } /******************************************************************************/ std::string Options::GetEfuseHashFileName(void) { return efuseHashFileName; } /******************************************************************************/ std::string Options::GetDevicePackageName(void) { return devicePackageName; } /******************************************************************************/ std::string Options::GetSpkSigFileName(void) { return spkSignatureFileName; } /******************************************************************************/ std::list& Options::GetOutputFileNames(void) { return outputFileNames; } /******************************************************************************/ LogLevel::Type Options::GetLogLevel(void) { return logLevel; } /******************************************************************************/ Arch::Type Options::GetArchType(void) { return archType; } /******************************************************************************/ bool Options::DoGenerateHashes(void) { return generateHashes; } /******************************************************************************/ bool Options::GetNoAuthBlocksFlag(void) { return noauthblocks; } /******************************************************************************/ bool Options::DoOverwrite(void) { return overwriteMode; } /******************************************************************************/ bool Options::GetLegacyFlag(void) { return legacy; } /******************************************************************************/ bool Options::DoPadHeaderTable(void) { return padImageHeaderTable; } /******************************************************************************/ bool Options::GetNonBootingFlag(void) { return nonBooting; } /******************************************************************************/ void Options::SetAuthKeyGeneration(GenAuthKeys::Type type) { genKey = type; } /******************************************************************************/ bool Options::GetGreyKeyGeneration(void) { return generateGreyKey; } /******************************************************************************/ bool Options::GetMetalKeyGeneration(void) { return generateMetalKey; } /******************************************************************************/ File::Type Options::GetOutType(void) { return outType; } /******************************************************************************/ void Options::SetGreyKeyGeneration(bool flag) { generateGreyKey = flag; } /******************************************************************************/ void Options::SetMetalKeyGeneration(bool flag) { generateMetalKey = flag; } /******************************************************************************/ GenAuthKeys::Type Options::GetAuthKeyGeneration(void) { return genKey; } /******************************************************************************/ void Options::SetEncryptionDump(bool type, std::string filename) { encryptionDump = type; std::ofstream exists(filename); if (exists) { std::ofstream remove(filename); } aesLogFilename = filename; } /******************************************************************************/ void Options::CloseEncryptionDumpFile(void) { if (GetEncryptionDumpFlag()) { aesLogFile.close(); } } /******************************************************************************/ void Options::SetZynqmpes1Flag(bool type) { zynqmpes1 = type; } /******************************************************************************/ bool Options::GetEncryptionDumpFlag(void) { return encryptionDump; } /******************************************************************************/ bool Options::GetZynqmpes1Flag(void) { if (archType != Arch::ZYNQMP && zynqmpes1) { LOG_ERROR("'-zynqmpes1' option supported only for ZynqMp architecture, '-arch zynqmp'"); } return zynqmpes1; } /******************************************************************************/ DumpOption::Type Options::GetDumpOption(void) { return dumpOption; } /******************************************************************************/ std::string Options::GetDumpDirectory(void) { return dumpPath; } /******************************************************************************/ std::string Options::GetOverlayCDOFileName(void) { return overlayCDOFile; } /******************************************************************************/ bool Options::IsSsitBif() { bool ssit_bif = false; for (std::vector::iterator bifoptions = bifOptionsList.begin(); bifoptions != bifOptionsList.end(); bifoptions++) { if ((*bifoptions)->slrBootCnt != 0 || (*bifoptions)->slrConfigCnt != 0) { ssit_bif = true; break; } } return ssit_bif; } xilinx-bootgen-2024.2/options.h000077500000000000000000000230341475706442400164370ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _OPTIONS_H_ #define _OPTIONS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "outputfile.h" #include "logger.h" #include "encryption.h" #include "baseclass.h" /* Forward Class References */ class BifOptions; /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ struct Arch { typedef enum { ZYNQ, ZYNQMP, FPGA, VERSAL, VERSALNET } Type; }; typedef struct { KeySource::Type encryptedKeySource; std::string encryptionKeyFile; std::string hmac; std::string key0; std::string startCBC; } CommndLineEncryptOptions; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Options { public: Options() : bifFileName("bootimage.bif") , doFill(false) , outputFillByte(0xFF) , splitType(File::Unknown) , baseAddress(0x00000000) , defaultAlignment(64) , generateHashes(false) , noauthblocks(false) , overwriteMode(false) , debugstr(new std::ostream(0)) , legacy(false) , padImageHeaderTable(true) , dualQspiMode(QspiMode::Unknown) , nonBooting(false) , processBitstream(File::Unknown) , devicePackageName("") , archType(Arch::ZYNQ) , genKey(GenAuthKeys::None) , encryptionDump(false) , zynqmpes1(false) , generateGreyKey(false) , generateMetalKey(false) , outputMode(OutputMode::OUT_NORMAL) , totalHeadersSize(0) , bootheaderSize(0) , allHeaderSize(0) , bootloaderSize(0) , qspiSize(0) , logLevel(LogLevel::WARNING) , outputFmt(File::Unknown) , readImageOption(ReadImageOption::NONE) , readImageFile("") , verifyImage(false) , bifOptions(NULL) , secHdrIv(NULL) , secHdrIvPmcData(NULL) , secureDebugAuthType(Authentication::None) , secureDebugImageFilename("") , dumpOption(DumpOption::NONE) , dumpPath("") , deviceKeyStored(false) , versalNetSeries(false) , outType(File::Unknown) , authOptimizationEnabled(false) { cmdEncryptOptions = new CommndLineEncryptOptions(); }; ~Options() { if (debugstr != &std::cout) { delete debugstr; } if (cmdEncryptOptions) { delete cmdEncryptOptions; } if (secHdrIv) { delete secHdrIv; } } void ParseArgs(int argc,const char* argv[]); std::ostream* debugstr; void ProcessVerifyKDF(void); void ProcessReadImage(void); void SetBifFilename (std::string); void SetEncryptedKeySource (KeySource::Type); void SetEncryptionKeyFile (std::string); void SetHmac (std::string); void SetKey0 (std::string); void SetStartCbc (std::string); void SetOutputByteWidth (uint8_t); void SetDoFill (bool); void SetOutputFillByte (uint8_t); void SetSplitType (File::Type); void SetProcessBitstreamType (File::Type); void SetDualQspiMode (QspiMode::Type); void SetQspiSize (uint16_t); void SetOspiSize(uint16_t size); void SetBaseAddress (Binary::Address_t); void SetDefaultAlignment (uint32_t); void SetDevicePartName (std::string); void SetKDFTestVectorFile(std::string); void SetDevicePackageName (std::string); void SetEfuseHashFileName (std::string); void SetSpkSigFileName (std::string); void InsertOutputFileNames (std::string); void SetLogLevel (LogLevel::Type); void SetArchType (Arch::Type); void SetGenerateHashes (bool); void SetNoAuthBlocksFlag (bool); void SetOverwrite (bool); void SetLegacyFlag (bool); void SetPadHeaderTable (bool); void SetNonBootingFlag (bool); void SetAuthKeyGeneration (GenAuthKeys::Type); void SetGreyKeyGeneration (bool flag); void SetMetalKeyGeneration (bool flag); void SetEncryptionDump(bool, std::string filename); void CloseEncryptionDumpFile(void); void SetZynqmpes1Flag (bool); void SetOutputMode (OutputMode::Type, File::Type); void SetDumpOption(DumpOption::Type); void SetDumpDirectory(std::string); void SetVerifyImageOption(bool); void SetReadImageOption(ReadImageOption::Type); void SetReadImageFile(std::string); void SetSecureDebugAuthType(Authentication::Type type); void SetSecureDebugImageFile(std::string); void SetOverlayCDOFileName (std::string); void SetOutType (File::Type); void SetAuthOptimization(void); bool IsAuthOptimizationEnabled(void); std::string GetBifFilename (void); KeySource::Type GetEncryptedKeySource (void); std::string GetEncryptionKeyFile (void); std::string GetHmac (void); std::string GetKey0 (void); std::string GetStartCbc (void); std::string GetFsblFilename (void); uint8_t GetOutputByteWidth (void); bool GetDoFill (void); uint8_t GetOutputFillByte (void); File::Type GetSplitType (void); File::Type GetProcessBitstreamType (void); QspiMode::Type GetDualQspiMode (void); uint16_t GetQspiSize (void); Binary::Address_t GetBaseAddress (void); uint32_t GetDefaultAlignment (void); std::string GetDevicePartName (void); std::string GetKDFTestVectorFile(void); std::string GetDevicePackageName (void); std::string GetEfuseHashFileName (void); std::string GetSpkSigFileName (void); std::list& GetOutputFileNames (void); LogLevel::Type GetLogLevel (void); Arch::Type GetArchType (void); bool DoGenerateHashes (void); bool GetNoAuthBlocksFlag (void); bool DoOverwrite (void); bool GetLegacyFlag (void); bool DoPadHeaderTable (void); bool GetNonBootingFlag (void); GenAuthKeys::Type GetAuthKeyGeneration (void); bool GetGreyKeyGeneration (void); bool GetMetalKeyGeneration (void); bool GetEncryptionDumpFlag (void); bool GetZynqmpes1Flag (void); OutputMode::Type GetOutputMode (void); File::Type GetOutputFormat (void); std::string GetReadImageFile(void); ReadImageOption::Type GetReadImageOption(void); bool GetVerifyImageOption(); DumpOption::Type GetDumpOption(void); std::string GetDumpDirectory(void); Authentication::Type GetSecureDebugAuthType(void); std::string GetSecureDebugImageFile(void); std::string GetOverlayCDOFileName (void); bool IsSsitBif(void); bool IsVersalNetSeries(void) { return versalNetSeries; } File::Type GetOutType (void); uint32_t totalHeadersSize; uint32_t bootheaderSize; uint32_t allHeaderSize; uint32_t bootloaderSize; uint8_t *secHdrIv; uint8_t *secHdrIvPmcData; //private: std::string bifFileName; std::string devicePartName; std::string efuseHashFileName; std::string spkSignatureFileName; std::string devicePackageName; std::string kdfTestVectorFile; std::list outputFileNames; LogLevel::Type logLevel; QspiMode::Type dualQspiMode; GenAuthKeys::Type genKey; Arch::Type archType; OutputMode::Type outputMode; File::Type outputFmt; File::Type splitType; File::Type processBitstream; std::string readImageFile; ReadImageOption::Type readImageOption; bool verifyImage; DumpOption::Type dumpOption; std::string dumpPath; bool overwriteMode; bool doFill; bool legacy; bool padImageHeaderTable; bool generateHashes; bool nonBooting; bool encryptionDump; bool zynqmpes1; bool noauthblocks; bool generateGreyKey; bool generateMetalKey; bool deviceKeyStored; std::ofstream aesLogFile; std::string aesLogFilename; uint8_t outputFillByte; uint16_t qspiSize; uint32_t defaultAlignment; Binary::Address_t baseAddress; CommndLineEncryptOptions *cmdEncryptOptions; BifOptions* bifOptions; std::vector bifOptionsList; std::list includeBifOptionsList; std::string fsblFilename; Authentication::Type secureDebugAuthType; std::string secureDebugImageFilename; std::string overlayCDOFile; File::Type outType; private: bool versalNetSeries; bool authOptimizationEnabled; }; #endif xilinx-bootgen-2024.2/outputfile-versal.cpp000077500000000000000000000152751475706442400210010ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "outputfile.h" #include "stringutils.h" #include "bootgenexception.h" #include "binary.h" #include "options.h" #include "bootgenenum.h" #include "bootimage.h" /******************************************************************************/ void OutputFile::OutputVersal(Options& options, Binary& cache) { bool splitMode = options.GetSplitType() != File::Unknown; /* Setup the options for Dual QSPI/OSPI mode */ qspiDualMode = options.GetDualQspiMode(); if ((qspiDualMode == QspiMode::PARALLEL_LQSPI) && options.GetArchType() == Arch::VERSAL) { qspiDualMode = QspiMode::PARALLEL_GQSPI; } qspiSizeInBytes = options.GetQspiSize() * 1024 * 1024; totalImageSize = cache.TotalSize; bool overwrite = options.DoOverwrite(); if (!overwrite) { if (std::ifstream(filename.c_str())) { LOG_ERROR("Output File %s already exists in the path\n Use '-w on' option to force overwrite", filename.c_str()); } } uint8_t adjust_len = 0; /* Open the file handle for the filename set above & write preamble (if any) */ Open(); WritePreamble(); Binary::Address_t runningAddress = 0; std::string acBootloader = ""; Binary::Address_t unalignedRunningAddress = 0; for (SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); //ProcessEverestImage(section, options); /* Write to output file */ if (!section.Name.compare("BootHeader")) { if (options.bifOptions->pdiType != PartitionType::SLR_SLAVE_BOOT) { if (options.bifOptions->GetSmapWidth() == 0) { // For SSIT slave devices, the PDI should not have the SMAP bus width adjust_len = 16; } } Write(section.Address, section.Length - adjust_len, section.Data + adjust_len); if (options.GetDumpOption() == DumpOption::BH) { WriteBootHeaderToFile(options.GetOutputFileNames().front(), section.Data + adjust_len, section.Length - adjust_len); } unalignedRunningAddress = section.Address + section.Length - adjust_len; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); } if (section.isBootloader) { acBootloader = section.Name + ".sha384"; } } for (SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); if (!section.Name.compare(acBootloader)) { section.Address = runningAddress; Write(section.Address, section.Length, section.Data); unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); } } for (SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); if (section.isBootloader) { section.Address = runningAddress; if ((mode == OutputMode::OUT_SPLIT_NORMAL) || splitMode) { ProcessSplitMode(section, options); } Write(section.Address, section.Length, section.Data); unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); /* Fill the gap(if any) between sections will fill byte */ if (runningAddress > unalignedRunningAddress) { if (options.bifOptionsList.back()->GetSmapWidth() != 0) { Fill(unalignedRunningAddress, runningAddress, options.GetDoFill(), options.GetOutputFillByte()); } } } } for (SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); /* Write to output file */ if (section.Name.compare("BootHeader") && !(section.isBootloader) && section.Name.compare(acBootloader)) { if (section.Address < runningAddress) { LOG_ERROR("Sequential addresses are going backwards!"); } /* Fill the gap(if any) between sections will fill byte */ if (section.Address > runningAddress) { if (options.bifOptionsList.back()->GetSmapWidth() != 0) { Fill(runningAddress, section.Address, options.GetDoFill(), options.GetOutputFillByte()); } } if ((mode == OutputMode::OUT_SPLIT_NORMAL) || splitMode) { ProcessSplitMode(section, options); } Write(section.Address, section.Length, section.Data); unalignedRunningAddress = section.Address + section.Length; runningAddress = (unalignedRunningAddress + (options.GetDefaultAlignment() - 1)) & ~(options.GetDefaultAlignment() - 1); /* Fill the gap(if any) between sections will fill byte */ if (runningAddress > unalignedRunningAddress) { if (options.bifOptionsList.back()->GetSmapWidth() != 0) { Fill(unalignedRunningAddress, runningAddress, options.GetDoFill(), options.GetOutputFillByte()); } } } } /* Close the file handle, after writing the post script */ WritePostscriptAndClose(); } xilinx-bootgen-2024.2/outputfile.cpp000077500000000000000000000372701475706442400175060ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "outputfile.h" #include "stringutils.h" #include "bootgenexception.h" #include "binary.h" #include "options.h" #include "bootgenenum.h" #include "bootimage.h" #include "bitutils.h" /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { const char* extension; File::Type type; } fileFormatTableType; fileFormatTableType fileFormatTable[] = { { ".mem", File::MEM }, { ".bit", File::BIT }, { ".rbt", File::RBT }, { ".bin", File::BIN }, { ".hex", File::HEX }, { ".mcs", File::MCS }, { NULL }, }; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ File::Type OutputFile::GetType(const std::string& filename) { std::string extension = StringUtils::GetExtension(filename); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); for(fileFormatTableType* ptr = fileFormatTable;ptr->extension;ptr++) { if (ptr->extension == extension) { return ptr->type; } } return File::BIN; } /******************************************************************************/ OutputFile* OutputFile::Factory(const std::string& filename) { File::Type type = GetType(filename); OutputFile* file = NULL; switch(type) { case File::MCS: file = new McsFile(); break; case File::BIN: file = new BinFile(); break; default: LOG_ERROR("File extension (type %d) not supported for %s",type,filename.c_str()); } file->filename = filename; return file; } /******************************************************************************/ static std::string AddSplitModeExtention(std::string fName, File::Type type, bool isFirstSection) { std::string extension = (type == File::MCS) ? ".mcs" : ".bin"; /* If there are multiple partitions for same elf partition, then add a no. before the extn Example: There are 2 partitions in app.elf, then 2 partition files would be app.elf.bin app.elf.1.bin */ if(!isFirstSection) { std::size_t pos = fName.find("elf"); if(pos != std::string::npos) { std::size_t temp = fName.find_last_of("."); extension = fName.substr(temp, temp+1) + extension; } } return fName.substr(0, fName.find_last_of(".")) + extension; } /******************************************************************************/ void OutputFile::Output(Options& options, Binary& cache) { if (options.GetArchType() == Arch::VERSAL) { OutputVersal(options, cache); } else { /* Get all modes */ bool splitMode = options.GetSplitType() != File::Unknown; //bool processBitstream = options.GetProcessBitstreamType() != File::Unknown; mode = options.GetOutputMode(); /* Setup the options for Dual QSPI mode */ qspiDualMode = options.GetDualQspiMode(); if ((qspiDualMode == QspiMode::PARALLEL_LQSPI) && options.GetArchType() == Arch::ZYNQMP) { qspiDualMode = QspiMode::PARALLEL_GQSPI; } qspiSizeInBytes = options.GetQspiSize() * 1024 * 1024; totalImageSize = cache.TotalSize; splitOffset = 0; encrypted = false; /* Create output files as per mode, depending on overwrite flag */ CreateOutputFiles(options); /* Open the file handle for the filename set above & write preamble (if any) */ Open(); WritePreamble(); /* Iterate through all sections and push the section to approprite file, depending on mode */ Binary::Address_t runningAddress = 0; for (SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); /* Process Bitstream Mode Only bitstream files will be output to a file */ if (mode == OutputMode::OUT_BITSTREAM) { if (section.isBitStream) { ProcessBitstreamMode(section); } else { continue; } } else { if (section.Address < runningAddress) { LOG_ERROR("Sequential addresses are going backwards!"); } /* Fill the gap(if any) between sections will fill byte */ if (section.Address > runningAddress) { Fill(runningAddress, section.Address, options.GetDoFill(), options.GetOutputFillByte()); } /* Split Mode All headers and FSBL are part of the main output file and all other partitions have one output file each */ //if (splitMode) if ((mode == OutputMode::OUT_SPLIT_NORMAL) || splitMode) { ProcessSplitMode(section, options); } /* Slave Boot Split Mode Bootheader+FSBL are part of the main output file, headers are part of one output file and all other partitions to another output file */ if (mode == OutputMode::OUT_SPLIT_SLAVEBOOT) { ProcessSplitSlaveBootMode(section, options); } } /* Write to output file */ Write(section.Address, section.Length, section.Data); runningAddress = section.Address + section.Length; } /* Close the file handle, after writing the post script */ WritePostscriptAndClose(); } } /******************************************************************************/ void OutputFile::CreateOutputFiles(Options& options) { bool overwrite = options.DoOverwrite(); bootFile = filename; /* Slave Boot Split mode Create two more files other than original file - for headers & partitions Files are created if overwrite flag is not set, otherwise they are freshly opened (not in append mode) */ if(mode == OutputMode::OUT_SPLIT_SLAVEBOOT) { std::string extn = (options.GetOutputFormat() == File::BIN) ? ".bin": ".mcs"; std::string basename = StringUtils::RemoveExtension(filename.c_str()); /* Headers file */ headersFile = basename + "_headers" + extn; if(!overwrite && std::ifstream(headersFile.c_str())) { LOG_ERROR("Output File %s already exists in the path\n Use '-w on' option to force overwrite", headersFile.c_str()); } filename = headersFile; Open(); WritePreamble(); Close(); /* Partitions file */ partitionFile = basename + "_partitions" + extn; if(!overwrite && std::ifstream(partitionFile.c_str())) { LOG_ERROR("Output File %s already exists in the path\n Use '-w on' option to force overwrite", partitionFile.c_str()); } filename = partitionFile; Open(); WritePreamble(); Close(); this->filename = bootFile; } else { /* Original output file If overwrite flag not enabled, throw error if already exists */ if(!overwrite) { if (std::ifstream(filename.c_str())) { LOG_ERROR("Output File %s already exists in the path\n Use '-w on' option to force overwrite", filename.c_str()); } } } } /******************************************************************************/ void OutputFile::ProcessSplitSlaveBootMode(Section& section, Options& options) { /* If the section is a Bootheader, then ignore, as it will be part of the main output file opened in the caller function */ if(section.Name.compare("BootHeader")) { /* Close previous file handle Don't write the post script, as this is not the end of file */ Close(); /* If section is bootloader OR bootloader's authentication certificate Use the orginal output file name */ if( section.isBootloader || ((section.Name.find(StringUtils::BaseName(options.GetFsblFilename())) != std::string::npos) && section.isCertificate) ) { splitOffset = options.allHeaderSize; fileIndex = 0; this->filename = bootFile; } /* All the header sections except bootheader Includes authentication certificate(if any) of the all header tables Excludes partitions and their authentication certificates(if any) Use the _headers. */ if( (section.Name.compare("BootHeader") && !section.isPartitionData && !section.isCertificate) || ((section.Name.find("ImageHeaderTable") != std::string::npos) && section.isCertificate) ) { splitOffset = options.bootheaderSize; fileIndex = 1; this->filename = headersFile; } /* All the other partitions except bootloader/fsbl Includes their authentication certificates(if any) Excludes header's and bootloaders's authentication certificate(if any) Use the _partitions. */ if( !section.isBootloader && (section.isPartitionData || section.isCertificate) && !((section.Name.find("ImageHeaderTable") != std::string::npos) && section.isCertificate) && !((section.Name.find(StringUtils::BaseName(options.GetFsblFilename())) != std::string::npos) && section.isCertificate) ) { splitOffset = options.bootheaderSize + options.bootloaderSize + options.allHeaderSize; fileIndex = 2; this->filename = partitionFile; } LOG_TRACE("Adding section %s to %s", section.Name.c_str(), StringUtils::BaseName(this->filename.c_str()).c_str()); /* Opens the file handle in append mode */ Append(); } } /******************************************************************************/ void OutputFile::ProcessSplitMode(Section& section, Options& options) { /* If the section is a partition and not an FSBL partition */ if( section.isPartitionData && section.Name.find(StringUtils::BaseName(options.GetFsblFilename())) != 0 ) { /* Close the previous file handle */ WritePostscript(); Close(); /* Create the filename, based on the partition name & extension */ File::Type extn = options.GetSplitType(); if(extn == File::Unknown) { extn = options.GetOutputFormat(); } this->filename = AddSplitModeExtention(section.Name, extn, section.isFirstElfSection); /* Open the new file handle */ Open(); WritePreamble(); LOG_TRACE("File %s created for partition %s in Split Mode", filename.c_str(), section.Name.c_str()); } } /******************************************************************************/ void OutputFile::ProcessBitstreamMode(Section& section) { WritePostscript(); Close(); Open(); WritePreamble(); /* The 0 section address, means the bitstream data starts from beginning of the file */ section.Address = 0; } /******************************************************************************/ void OutputFile::WritePostscriptAndClose(void) { WritePostscript(); Close(); /* The above functions will write the post script and close the file handle. Incase of Spilt Slave mode, the last file written is always partitions file, hence the above functions will write the post script and close the files. Only bootfile & headers file need to handled separately and is done in below block */ if(mode == OutputMode::OUT_SPLIT_SLAVEBOOT) { this->filename = bootFile; Append(); WritePostscript(); Close(); this->filename = headersFile; Append(); WritePostscript(); Close(); } } /******************************************************************************/ void FpgaPartitionOutput::GeneratePartitionFiles(BootImage& bi, Binary& cache) { SectionList tempSecList; Binary::Address_t *addr = new Binary::Address_t [bi.imageList.size()]; int i = 0; for(std::list::iterator image = bi.imageList.begin(); image != bi.imageList.end(); image++, i++) { addr[i] = (Binary::Address_t)(*image)->GetOffset().ValueOrDefault(0); } int j = 0; for(SectionList::iterator i = cache.Sections.begin(); i != cache.Sections.end(); i++) { Section& section(**i); if(section.isPartitionData) { tempSecList.push_back(§ion); section.Address = addr[j++]; } } cache.Sections = tempSecList; delete[] addr; } /******************************************************************************/ void OutputFile::OutputInterface(Options& options, uint8_t* buffer, uint32_t size) { encrypted = false; /* If overwrite flag not enabled, throw error if already exists */ if (!options.DoOverwrite()) { if (std::ifstream(filename.c_str())) { LOG_ERROR("Output File %s already exists in the path\n Use '-w on' option to force overwrite", filename.c_str()); } } /* Open the file handle for the filename set above & write preamble (if any) */ Open(); WritePreamble(); Write(0, size, buffer); /* Close the file handle, after writing the post script */ WritePostscriptAndClose(); } /******************************************************************************/ void OutputFile::WriteBootHeaderToFile(std::string fileName, uint8_t* data, uint64_t size) { FILE* filePtr; size_t result; std::string fName = StringUtils::RemoveExtension(fileName); fName += "_bh.bin"; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { /* First 16 bytes are not required by BootRoM/PLM, they should not be part of BH */ result = fwrite(data + 16, 1, size - 16, filePtr); if (result != (size - 16)) { LOG_ERROR("Error dumping Boot Header to a file"); } fclose(filePtr); } LOG_INFO("Boot header binary file created - %s", fName.c_str()); } xilinx-bootgen-2024.2/outputfile.h000077500000000000000000000151221475706442400171430ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _OUTPUTFILE_H_ #define _OUTPUTFILE_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "binary.h" #include "bootgenenum.h" #include "logger.h" /* Forward Class References */ class Options; class BootImage; class OutputStream; /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define NO_SPLIT_SLAVE_FILES 3 /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class OutputFile { public: OutputFile() : totalByteOutputCount(0) , fileIndex(0) , qspiDualMode(QspiMode::Unknown) , qspiSizeInBytes(0) , totalImageSize(0) , encrypted(false) , splitOffset(0) , mode(OutputMode::OUT_NORMAL) { } virtual ~OutputFile() {} static File::Type GetType(const std::string& filename); static OutputFile* Factory(const std::string& filename); void Output(Options& options, Binary& binary); void OutputVersal(Options& options, Binary& binary); void CreateOutputFiles(Options& options); void ProcessSplitMode(Section& section, Options& options); void ProcessSplitSlaveBootMode(Section& section, Options& options); void ProcessBitstreamMode(Section& section); void WritePostscriptAndClose(void); void OutputInterface(Options & options, uint8_t*, uint32_t); void WriteBootHeaderToFile(std::string fileName, uint8_t* data, uint64_t size); std::string filename; QspiMode::Type qspiDualMode; uint32_t qspiSizeInBytes; uint32_t totalImageSize; bool encrypted; uint32_t splitOffset; uint8_t fileIndex; private: std::string bootFile; std::string headersFile; std::string partitionFile; OutputMode::Type mode; protected: Binary::Length_t totalByteOutputCount; virtual void Open() = 0; virtual void Append() = 0; virtual void WritePreamble() = 0; virtual void Write(Binary::Address_t start, Binary::Length_t length, const uint8_t* buffer) = 0; virtual void Fill(Binary::Address_t start, Binary::Address_t end, bool doFill, uint8_t fillByte) = 0; virtual void WritePostscript() = 0; virtual void Close() = 0; protected: std::ofstream ofs; std::ofstream ofs1; }; /******************************************************************************/ class BinFile : public OutputFile { public: BinFile() {} virtual ~BinFile() {} virtual void Open() ; virtual void Append(); virtual void WritePreamble(); virtual void Write(Binary::Address_t start, Binary::Length_t length, const uint8_t* buffer); virtual void Fill(Binary::Address_t start, Binary::Address_t end, bool doFill, uint8_t fillByte); virtual void WritePostscript(); virtual void Close() ; }; /******************************************************************************/ class McsFile : public OutputFile { public: McsFile(); virtual ~McsFile() {} virtual void Open() ; virtual void Append(); virtual void WritePreamble(); virtual void Write(Binary::Address_t start, Binary::Length_t length, const uint8_t* buffer); virtual void Fill(Binary::Address_t start, Binary::Address_t end, bool doFill, uint8_t fillByte); virtual void WritePostscript(); virtual void Close() ; private: void Write(uint32_t address, uint8_t command, const uint8_t* data, int len); Binary::Address_t pageAddress; Binary::Address_t filePageAddr[NO_SPLIT_SLAVE_FILES]; uint32_t lineLength; uint32_t shiftLength; uint32_t maskByte; bool newFile; bool eofrWritten; }; /******************************************************************************/ class PartitionOutput { public: PartitionOutput() {} virtual ~PartitionOutput() {} virtual void GeneratePartitionFiles(BootImage& bi, Binary& cache) = 0; virtual PartitionArch::Type Type(void) = 0; }; /******************************************************************************/ class ZynqPartitionOutput : public PartitionOutput { public: ZynqPartitionOutput() {} ~ZynqPartitionOutput() {} void GeneratePartitionFiles(BootImage& bi, Binary& cache) { }; PartitionArch::Type Type(void) { return PartitionArch::NON_FPGA; } }; /******************************************************************************/ class ZynqMpPartitionOutput : public PartitionOutput { public: ZynqMpPartitionOutput() {} ~ZynqMpPartitionOutput() {} void GeneratePartitionFiles(BootImage& bi, Binary& cache) { }; PartitionArch::Type Type(void) { return PartitionArch::NON_FPGA; } }; /******************************************************************************/ class FpgaPartitionOutput : public PartitionOutput { public: FpgaPartitionOutput() {} ~FpgaPartitionOutput() {} void GeneratePartitionFiles(BootImage& bi, Binary& cache); PartitionArch::Type Type(void) { return PartitionArch::FPGA; } }; /******************************************************************************/ class VersalPartitionOutput : public PartitionOutput { public: void GeneratePartitionFiles(BootImage& bi, Binary& cache) { }; PartitionArch::Type Type(void) { return PartitionArch::VERSAL; } }; #endif xilinx-bootgen-2024.2/parsing.cpp000077500000000000000000000054431475706442400167460ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "parsing.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void Parsing::Error(const BIF::BisonParser::location_type &loc, const std::string &msg) { std::cerr << "\nERROR:BootGen - " << msg << "\n"; std::cerr << " Line #" << loc.begin.line << ", \"" << *loc.begin.filename << "\".\n"; std::string linedata; { std::ifstream echo(loc.begin.filename->c_str()); for(unsigned int line=0;line 10) { std::cerr << "... "; first = loc.begin.column - 10; } else { first = 1; } int len = loc.end.column - loc.begin.column; if (len > 70) { len = 70; } std::cerr << linedata.substr(first-1,70) << "\n"; unsigned int i; if (first != 1) { std::cerr << " "; } for(i=first;i /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class Parsing { public: static void Error(const BIF::BisonParser::location_type &loc, const std::string &msg); static void Error2(const BIF::BisonParser::location_type &loc,const std::string& linedata); }; #endif xilinx-bootgen-2024.2/partition-versal.cpp000077500000000000000000001024321475706442400206020ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "bootimage.h" #include "binary.h" #include "stringutils.h" #include "elftools.h" #include "partitionheadertable-versal.h" #include "partitionheadertable.h" #include "checksum-versal.h" #include "authentication-versal.h" #include "Keccak-compact-versal.h" extern "C" { #include "cdo-npi.h" #include "cdo-source.h" #include "cdo-command.h" #include "cdo-binary.h" #include "cdo-load.h" #include "cdo-overlay.h" }; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalPartition::VersalPartition(PartitionHeader* header0, Section* section0) : Partition(header0, section0) , header(header0) , firstChunkSize(0) , versalNetSeries(false) , secureChunkSize(SECURE_32K_CHUNK) { section = section0; // Populate bootloader flag here in the section object - needed in StackAndAlign stage section->isBootloader = header->imageHeader->IsBootloader(); // header->PartitionDataSize = section0->Length; } /******************************************************************************/ VersalPartition::VersalPartition(PartitionHeader* header0, const uint8_t* data, Binary::Length_t length) : Partition(header0, data, length) , header(header0) , firstChunkSize(0) , versalNetSeries(false) , secureChunkSize(SECURE_32K_CHUNK) { std::string partition_name = ""; for (size_t i = 0; i < header->imageHeader->GetFileList().size(); i++) { partition_name += StringUtils::BaseName(header->imageHeader->GetFileList().at(i)); if (i != (header->imageHeader->GetFileList().size() - 1)) { partition_name += "_"; } } std::string partName = partition_name + StringUtils::Format(".%d", header->index); /* Pad binary data with 0s, to get 32-bit word size. This is because bootgen stores partition sizes in terms of words, so partition data *MUST* be a multiple of 32-bits */ /* for everest - Pad the partition with 0's to make it 16 byte alligned */ int padding = (16 - (length & 15)) & 15; Binary::Length_t totallength = length + padding; section = new Section(partName, totallength); section->index = header->index; section->isPartitionData = true; section->isBitStream = (header->imageHeader->GetDomain() == Domain::PL) ? true : false; section->isFirstElfSection = (header->firstValidIndex); section->isBootloader = header->imageHeader->IsBootloader(); memcpy(section->Data, data, length); memset(section->Data + length, 0, padding); } /******************************************************************************/ size_t VersalPartition::GetTotalDataChunks(Binary::Length_t partitionSize, std::vector& dataChunks, bool encryptionFlag) { size_t newSectionLength = partitionSize; size_t chunkOnlength = 0; Binary::Length_t dataChunksCount = 0; chunkOnlength = partitionSize; if (encryptionFlag) { chunkOnlength -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } dataChunksCount = (chunkOnlength / secureChunkSize) + (((chunkOnlength % secureChunkSize) == 0 ? 0 : 1)); if (chunkOnlength % secureChunkSize != 0) { dataChunks.push_back(((chunkOnlength)-((dataChunksCount - 1) * secureChunkSize))); } else { dataChunks.push_back(secureChunkSize); } for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { dataChunks.push_back(SHA3_LENGTH_BYTES); newSectionLength += SHA3_LENGTH_BYTES; if (itr == dataChunksCount - 2) { if (encryptionFlag) { dataChunks.push_back(secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ; } else { dataChunks.push_back(secureChunkSize); firstChunkSize = secureChunkSize; } } else { dataChunks.push_back(secureChunkSize); } } return newSectionLength; } /******************************************************************************/ size_t VersalPartition::GetBootloaderTotalDataChunks(Binary::Length_t partitionSize, std::vector& dataChunks, bool encryptionFlag) { size_t newSectionLength = partitionSize; size_t chunkOnlength = 0; Binary::Length_t dataChunksCount = 0; //PMC DATA if (header->imageHeader->GetTotalPmcFwSizeIh() != 0) { chunkOnlength = header->imageHeader->GetTotalPmcFwSizeIh(); if (encryptionFlag) { chunkOnlength -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } dataChunksCount = (chunkOnlength / secureChunkSize) + (((chunkOnlength % secureChunkSize) == 0 ? 0 : 1)); if (dataChunksCount == 1) { if (chunkOnlength % secureChunkSize != 0) { size_t singleChunklength = (chunkOnlength)-((dataChunksCount - 1) * secureChunkSize); if (encryptionFlag) { dataChunks.push_back(singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ; LOG_TRACE("length of pmc data remaining length 0x%X:", singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ); } else { dataChunks.push_back(singleChunklength); firstChunkSize = singleChunklength; LOG_TRACE("length of pmc data remaining length 0x%X:", singleChunklength); } } else { if (encryptionFlag) { dataChunks.push_back(secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ; } else { dataChunks.push_back(secureChunkSize); firstChunkSize = secureChunkSize; } } } else { if (chunkOnlength % secureChunkSize != 0) { dataChunks.push_back(((chunkOnlength)-((dataChunksCount - 1) * secureChunkSize))); } else { dataChunks.push_back(secureChunkSize); } for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { dataChunks.push_back(SHA3_LENGTH_BYTES); newSectionLength += SHA3_LENGTH_BYTES; header->imageHeader->SetTotalPmcFwSizeIh(header->imageHeader->GetTotalPmcFwSizeIh() + SHA3_LENGTH_BYTES); if (itr == dataChunksCount - 2) { if (encryptionFlag) { dataChunks.push_back(secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ; } else { dataChunks.push_back(secureChunkSize); firstChunkSize = secureChunkSize; } } else { dataChunks.push_back(secureChunkSize); } } } } //PLM chunkOnlength = header->imageHeader->GetTotalFsblFwSizeIh(); if (encryptionFlag) { chunkOnlength -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } dataChunksCount = (chunkOnlength / secureChunkSize) + (((chunkOnlength % secureChunkSize) == 0 ? 0 : 1)); if (dataChunksCount == 1) { // If PMC CDO present, need to calculate the hash, so include hash if (header->imageHeader->GetTotalPmcFwSizeIh()) { dataChunks.push_back(SHA3_LENGTH_BYTES); newSectionLength += SHA3_LENGTH_BYTES; header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + SHA3_LENGTH_BYTES); } if (chunkOnlength % secureChunkSize != 0) { size_t singleChunklength = (chunkOnlength) - ((dataChunksCount - 1) * secureChunkSize); if (encryptionFlag) { dataChunks.push_back(singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ; LOG_TRACE("length of plm data remaining length 0x%X:", singleChunklength + SECURE_HDR_SZ + AES_GCM_TAG_SZ); } else { dataChunks.push_back(singleChunklength); firstChunkSize = singleChunklength; LOG_TRACE("length of plm data remaining length 0x%X:", singleChunklength); } } else { if (encryptionFlag) { dataChunks.push_back(secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ; LOG_TRACE("length of plm data remaining length 0x%X:", secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); } else { dataChunks.push_back(secureChunkSize); firstChunkSize = secureChunkSize; LOG_TRACE("length of plm data remaining length 0x%X:", secureChunkSize); } } } else { // If PMC CDO present, need to calculate the hash, so include hash if (header->imageHeader->GetTotalPmcFwSizeIh()) { dataChunks.push_back(SHA3_LENGTH_BYTES); newSectionLength += SHA3_LENGTH_BYTES; header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + SHA3_LENGTH_BYTES); } if (chunkOnlength % secureChunkSize != 0) { dataChunks.push_back(((chunkOnlength)-((dataChunksCount - 1) * secureChunkSize))); LOG_TRACE("length of plm data remaining length 0x%X:", ((chunkOnlength)-((dataChunksCount - 1) * secureChunkSize))); } else { dataChunks.push_back(secureChunkSize); LOG_TRACE("length of plm data remaining length 0x%X:", secureChunkSize); } for (uint32_t itr = 0; itr < dataChunksCount - 1; itr++) { dataChunks.push_back(SHA3_LENGTH_BYTES); newSectionLength += SHA3_LENGTH_BYTES; header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + SHA3_LENGTH_BYTES); if (itr == dataChunksCount - 2) { if (encryptionFlag) { dataChunks.push_back(secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ); firstChunkSize = secureChunkSize + SECURE_HDR_SZ + AES_GCM_TAG_SZ; } else { dataChunks.push_back(secureChunkSize); firstChunkSize = secureChunkSize; } } else { dataChunks.push_back(secureChunkSize); } } } if ((header->imageHeader->GetChecksumContext()->Type() != Checksum::None)) { newSectionLength += SHA3_LENGTH_BYTES; header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + SHA3_LENGTH_BYTES); } return newSectionLength; } /******************************************************************************/ void VersalPartition::ChunkifyAndHash(Section* section, bool encryptionFlag) { std::vector dataChunks; std::vector data; uint8_t* tempBuffer; int tempBufferSize = 0; /* Get the number/size data chunks and claculate the new section length*/ size_t length = section->Length; size_t newLength = 0; bool checksum_bootloader = false; if (section->isBootloader && versalNetSeries) { if (header->imageHeader->GetChecksumContext()->Type() != Checksum::None) { /* If checksum is enabled for VersalNet bootloader, then add the final checksum here only. VersalChecksumTable::Build & VersalChecksumTable::Link will not process anything for bootloader checksum */ checksum_bootloader = true; } newLength = GetBootloaderTotalDataChunks(length, dataChunks, encryptionFlag); } else { newLength = GetTotalDataChunks(length, dataChunks, encryptionFlag); } int itr = (dataChunks.size() - 3); /* Form a new section - Divide into data chunks of 64K and add sha pad - calculate hash to each chunk - prepend hash to chunk+shapad to form a complete partition. */ if (newLength Data, length); dataPtr += length; uint8_t* newDataPtr = new uint8_t[newLength]; memset(newDataPtr, 0, newLength); newDataPtr += newLength; /*-------------------------------CHUNK N------------------------------------*/ /* Insert Data */ tempBufferSize = dataChunks[0]; tempBuffer = new uint8_t[tempBufferSize]; memset(tempBuffer, 0, tempBufferSize); dataPtr -= tempBufferSize; memcpy(tempBuffer, dataPtr, tempBufferSize); newDataPtr -= tempBufferSize; memcpy(newDataPtr, tempBuffer, tempBufferSize); delete[] tempBuffer; /* Calculate hash */ uint8_t* shaHash; shaHash = new uint8_t[SHA3_LENGTH_BYTES]; Versalcrypto_hash(shaHash, newDataPtr, dataChunks[0], true); /*-------------------------------CHUNK N------------------------------------*/ for (int i = 2; i <= itr; i += 2) { /* Insert previous hash */ newDataPtr -= SHA3_LENGTH_BYTES; memcpy(newDataPtr, shaHash, SHA3_LENGTH_BYTES); delete[] shaHash; /* Insert Data */ tempBufferSize = dataChunks[i]; tempBuffer = new uint8_t[tempBufferSize]; memset(tempBuffer, 0, tempBufferSize); dataPtr -= tempBufferSize; memcpy(tempBuffer, dataPtr, tempBufferSize); newDataPtr -= tempBufferSize; memcpy(newDataPtr, tempBuffer, tempBufferSize); delete[] tempBuffer; /* Calculate hash */ shaHash = new uint8_t[SHA3_LENGTH_BYTES]; Versalcrypto_hash(shaHash, newDataPtr, dataChunks[i] + dataChunks[i - 1], true); } /*-------------------------------CHUNK 1------------------------------------*/ itr += 2; /* Insert previous hash */ newDataPtr -= SHA3_LENGTH_BYTES; memcpy(newDataPtr, shaHash, SHA3_LENGTH_BYTES); delete[] shaHash; /* Insert Data */ tempBufferSize = dataChunks[itr]; tempBuffer = new uint8_t[tempBufferSize]; memset(tempBuffer, 0, tempBufferSize); dataPtr -= tempBufferSize; memcpy(tempBuffer, dataPtr, tempBufferSize); newDataPtr -= tempBufferSize; memcpy(newDataPtr, tempBuffer, tempBufferSize); delete[] tempBuffer; /*-------------------------------CHUNK 1------------------------------------*/ if (checksum_bootloader) { /* Calculate hash of top chunk and previous hash */ shaHash = new uint8_t[SHA3_LENGTH_BYTES]; Versalcrypto_hash(shaHash, newDataPtr, tempBufferSize + SHA3_LENGTH_BYTES, true); /* Place the final hash at the start of PLM partition */ newDataPtr -= SHA3_LENGTH_BYTES; memcpy(newDataPtr, shaHash, SHA3_LENGTH_BYTES); delete[] shaHash; } delete[] dataPtr; delete[] section->Data; section->Data = newDataPtr; section->Length = newLength; LOG_TRACE("First Authentication Data Chunk Size 0x%X", firstChunkSize); } /******************************************************************************/ void VersalPartition::Build(BootImage& bi, Binary& cache) { versalNetSeries = bi.options.IsVersalNetSeries(); secureChunkSize = bi.GetSecureChunkSize(this->header->imageHeader->IsBootloader()); /* Get the image header from this partition header */ ImageHeader& imageHeader(*this->header->imageHeader); /* Get the contexts for Authentication & Encryption */ AuthenticationContext* currentAuthCtx = imageHeader.GetAuthContext(); EncryptionContext* encryptCtx = imageHeader.GetEncryptContext(); /* Set default values Set the address for relative placement for subsequence partitions in image Don't reserve anything for partition sections */ if (!bi.XipMode) { section->Address = 0; section->Reserve = 0; } /* If the partition is a bootloader & XIP mode is enabled, then address is directly populated based on the QSPI execution address. */ if (!(imageHeader.IsBootloader() && bi.XipMode)) { /* The offset and reserve attributes only apply to first partition in image subsequent partitions in the same image are packed right after another */ if (header->IsFirstPartitionInImage()) { section->Address = imageHeader.GetOffset().ValueOrDefault(0); section->Reserve = imageHeader.GetReserve().ValueOrDefault(0); } else { section->continuation = true; } } section->Alignment = imageHeader.GetAlignment().ValueOrDefault(0); /* If the head and tail of the partition destination are not on a word boundary we will prepad the data so that DMA can more easily copy the bulk of the data a whole word at a time. The head and tail bytes are treated seperately */ if (!header->prealigned) { /* Use the starting load address to get the number mis-align word boundry unused bytes at the beginning of a Partition data. Byte Addr Word Bytes headAlignment 0 00 00 00 00 0 1 XX 00 00 00 1 2 XX XX 00 00 2 3 XX XX XX 00 3 */ if ((header->imageHeader->GetDomain() != Domain::PL) && (header->imageHeader->GetPartitionType() != PartitionType::CONFIG_DATA_OBJ) && (header->imageHeader->GetPartitionType() != PartitionType::CFI)) { header->headAlignment = header->loadAddress % sizeof(uint32_t); /* Use the ending load address to get the number mis-align word boundry unused bytes at the end of a Partition data. Byte Addr Word Bytes tailAlignment 0 (1) 00 XX XX XX 3 1 (2) 00 00 XX XX 2 2 (3) 00 00 00 XX 1 3 (0) 00 00 00 00 0 */ uint32_t remainder = (header->loadAddress + section->Length) % sizeof(uint32_t); header->tailAlignment = (remainder == 0) ? 0 : (4 - remainder); } section->PadToWordAlignment(header->headAlignment, header->tailAlignment); } /* Encryption process on the partition */ if (header->preencrypted && encryptCtx->Type() != Encryption::None) { LOG_ERROR("Cannot reencrypt a partition that is already encrypted for %s", section->Name.c_str()); } /*******************************************************************************/ if ((imageHeader.GetPartitionType() == PartitionType::CONFIG_DATA_OBJ) && !header->preencrypted && !header->presigned) { size_t buffer_size = 0; uint32_t* syncpt_offsets = NULL; uint8_t num_of_sync_points = 0; std::vector sync_offsets; CdoSequence * cdo_seq; cdo_seq = decode_cdo_binary(header->partition->section->Data, header->partition->section->Length); /* Enable the search for sync points - only needs to be done for SSIT devices */ search_for_sync_points(); uint8_t* buffer = (uint8_t*)cdoseq_to_binary(cdo_seq, &buffer_size, 0); /* Get no. of sync points and sync points offsets */ num_of_sync_points = get_num_of_sync_points(); syncpt_offsets = get_slr_sync_point_offsets(); for (int i = 0; i < num_of_sync_points; i++) { size_t offset = (*(syncpt_offsets + i) * 4); bi.sync_offsets.push_back(offset); sync_offsets.push_back(offset); } delete syncpt_offsets; delete buffer; if (num_of_sync_points != 0) { std::string sync_addresses_filename = StringUtils::RemoveExtension(bi.options.GetOutputFileNames().front()) + "_" + bi.Name + "_" + std::to_string(imageHeader.GetPartitionUid()) + "_sync_offsets.txt"; std::ofstream f(sync_addresses_filename.c_str(), std::ios_base::out | std::ios_base::binary); f << "sync_offsets" << "\n"; for (size_t i = 0; i < sync_offsets.size(); i++) { f << sync_offsets[i] << "\n"; } f.close(); if (f.fail()) { LOG_ERROR("Failed to write sync addresses to the file: %s", sync_addresses_filename.c_str()); } LOG_TRACE("Sync addresses written to file %s successfully", sync_addresses_filename.c_str()); } } /*******************************************************************************/ if (versalNetSeries) { encryptCtx->ChunkifyAndProcess(bi, header); } else { encryptCtx->Process(bi, header); } uint32_t padLength = 0; /* Authentication process on the partition */ if (header->presigned) { // do nothing for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { *acs = 0; } } else { header->transferSize = section->Length; if ((imageHeader.GetChecksumContext()->Type() == Checksum::SHA3) || (currentAuthCtx->authAlgorithm->Type() != Authentication::None)) { /* No chunking on bootloader for versal - Data should be alligned to 104 bytes before calculating the hash */ if (imageHeader.IsBootloader() && !(versalNetSeries)) { Binary::Length_t shaPadOnLength = header->partition->section->Length; if (currentAuthCtx->authAlgorithm->Type() != Authentication::None) { /* Include AC but substract the Partition Signature Size, since it is not included in hash calculation */ shaPadOnLength += (currentAuthCtx->GetCertificateSize() - SIGN_LENGTH_VERSAL); } else if (imageHeader.GetChecksumContext()->Type() != Checksum::None) { /* Checksum length is added to the partition length, in case of bootloader. Substract the checksum length, since it should not be included in hash calculation */ shaPadOnLength -= imageHeader.GetChecksumContext()->Size(); } uint8_t shaPadLength = SHA3_PAD_LENGTH - (shaPadOnLength % SHA3_PAD_LENGTH); /* Create the SHA3 Padded partition */ section->IncreaseLengthAndPadSHA3(header->partition->section->Length + shaPadLength); if (bi.bifOptions->GetPmcdataFile() == "") { imageHeader.SetTotalFsblFwSizeIh(imageHeader.GetTotalFsblFwSizeIh() + shaPadLength); } else { imageHeader.SetTotalPmcFwSizeIh(imageHeader.GetTotalPmcFwSizeIh() + shaPadLength); } header->transferSize = section->Length - imageHeader.GetChecksumContext()->Size(); /* Checksum length is added to the partition length, in case of bootloader. Partiton length should not include checksum length, so substarct*/ } else if (imageHeader.IsBootloader() && versalNetSeries) { if (header->imageHeader->GetTotalPmcFwSizeIh() != 0) { ChunkifyAndHash(section, (encryptCtx->Type() != Encryption::None || header->preencrypted)); currentAuthCtx->SetFirstChunkSize(firstChunkSize); header->firstChunkSize = currentAuthCtx->GetFirstChunkSize(); header->partition->section->firstChunkSize = header->firstChunkSize; } else { Binary::Length_t chunkOnLength = header->partition->section->Length; if (encryptCtx->Type() != Encryption::None || header->preencrypted) { chunkOnLength -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } else if (imageHeader.GetChecksumContext()->Type() != Checksum::None) { /* Checksum length is not added to the partition length, in case of bootloader for VersalNet. Hence don't substract the checksum length, since it should not be included in hash calculation */ //chunkOnLength -= imageHeader.GetChecksumContext()->Size(); } Binary::Length_t dataChunksCount = (chunkOnLength / secureChunkSize) + ((((chunkOnLength) % secureChunkSize) == 0 ? 0 : 1)); if (dataChunksCount != 1) { ChunkifyAndHash(section, (encryptCtx->Type() != Encryption::None || header->preencrypted)); currentAuthCtx->SetFirstChunkSize(firstChunkSize); header->firstChunkSize = currentAuthCtx->GetFirstChunkSize(); header->partition->section->firstChunkSize = header->firstChunkSize; } else if (dataChunksCount == 1 && imageHeader.GetChecksumContext()->Type() != Checksum::None) { size_t newLength = section->Length + SHA3_LENGTH_BYTES; uint8_t* newDataPtr = new uint8_t[newLength]; memset(newDataPtr, 0, newLength); newDataPtr += SHA3_LENGTH_BYTES; memcpy(newDataPtr, section->Data, section->Length); /* Calculate hash */ uint8_t* shaHash; shaHash = new uint8_t[SHA3_LENGTH_BYTES]; Versalcrypto_hash(shaHash, newDataPtr, section->Length, true); /* Place the final hash at the start of PLM partition */ newDataPtr -= SHA3_LENGTH_BYTES; memcpy(newDataPtr, shaHash, SHA3_LENGTH_BYTES); header->imageHeader->SetTotalFsblFwSizeIh(header->imageHeader->GetTotalFsblFwSizeIh() + SHA3_LENGTH_BYTES); delete[] shaHash; delete[] section->Data; section->Data = newDataPtr; section->Length = newLength; } } if (bi.bifOptions->GetPmcdataFile() == "") { //imageHeader.SetTotalFsblFwSizeIh(section->Length); } else { //imageHeader.SetTotalPmcFwSizeIh(imageHeader.GetTotalPmcFwSizeIh() + shaPadLength); } header->transferSize = section->Length - imageHeader.GetChecksumContext()->Size(); /* Checksum length is added to the partition length, in case of bootloader. Partiton length should not include checksum length, so substarct*/ } /* Chunk the data into fixed 64KB/32KB */ else { Binary::Length_t chunkOnLength = header->partition->section->Length; if (encryptCtx->Type() != Encryption::None || header->preencrypted) { chunkOnLength -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } Binary::Length_t dataChunksCount = (chunkOnLength / secureChunkSize) + ((((chunkOnLength) % secureChunkSize) == 0 ? 0 : 1)); if (dataChunksCount != 1) { ChunkifyAndHash(section, (encryptCtx->Type() != Encryption::None || header->preencrypted)); currentAuthCtx->SetFirstChunkSize(firstChunkSize); header->firstChunkSize = currentAuthCtx->GetFirstChunkSize(); header->partition->section->firstChunkSize = header->firstChunkSize; } } } if((imageHeader.IsBootloader() && imageHeader.GetChecksumContext()->Type() != Checksum::None)) { if (!versalNetSeries) { padLength = imageHeader.GetChecksumContext()->Size(); } /* Don't add checksum length here, as the checksum calculation and insertion happen in ChunkifyAndHash() for VersalNet */ } else { // create AC/checksum section and add it to the end of the list. if (header->checksumSection != NULL) { cache.Sections.push_back(header->checksumSection); } AuthenticationCertificate* tempacs; tempacs = new VersalAuthenticationCertificate(currentAuthCtx); tempacs->Build(bi, cache, header->partition->section, imageHeader.IsBootloader(), false); header->ac.push_back(tempacs); currentAuthCtx->AddAuthCertSizeToTotalFSBLSize(header); } } if (imageHeader.IsBootloader() == true) { if (bi.bifOptions->GetPmcdataFile() == "") { bi.SetTotalFsblFwSize(imageHeader.GetTotalFsblFwSizeIh() + padLength); //below for everest //bi.SetTotalFsblFwSize(imageHeader.getTotalFsblFwSizeIh()); bi.bifOptions->SetTotalPmcFwSize(imageHeader.GetTotalPmcFwSizeIh()); } else { bi.SetTotalFsblFwSize(imageHeader.GetTotalFsblFwSizeIh()); bi.bifOptions->SetTotalPmcFwSize(imageHeader.GetTotalPmcFwSizeIh() + padLength); //below for everest //bi.SetTotalPmcFwSize(imageHeader.getTotalPmcFwSizeIh()); } //bi.SetTotalFsblFwSize(imageHeader.getTotalFsblFwSizeIh() + padLength); bi.SetTotalPmuFwSize(imageHeader.GetTotalPmuFwSizeIh()); //bi.SetTotalPmcFwSize(imageHeader.getTotalPmcFwSizeIh()); bi.SetPmuFwSize(imageHeader.GetPmuFwSizeIh()); bi.bifOptions->SetPmcFwSize(imageHeader.GetPmcFwSizeIh()); bi.SetFsblFwSize(imageHeader.GetFsblFwSizeIh()); if (bi.XipMode) { // Just to make sure, not to get a negative no. as address if (imageHeader.GetTotalPmuFwSizeIh() != 0) { if (imageHeader.GetFsblSourceAddrIh() > imageHeader.GetTotalPmuFwSizeIh()) { section->Address = imageHeader.GetFsblSourceAddrIh() - imageHeader.GetTotalPmuFwSizeIh(); bi.SetFsblSourceAddr(section->Address); } } // Just to make sure, not to get a negative no. as address if (imageHeader.GetTotalPmcFwSizeIh() != 0) { if (imageHeader.GetFsblSourceAddrIh() > imageHeader.GetTotalPmcFwSizeIh()) { section->Address = imageHeader.GetFsblSourceAddrIh() - imageHeader.GetTotalPmcFwSizeIh(); bi.SetFsblSourceAddr(section->Address); } } } } /* Push the section alloted into the Main section */ if (section != NULL) { cache.Sections.push_back(section); } } /******************************************************************************/ void VersalPartition::Link(BootImage &bi) { for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { if ((*acs)) { header->partition->section->partitionNum = header->partitionNum; (*acs)->Link(bi, header->partition->section); } } } xilinx-bootgen-2024.2/partition.cpp000077500000000000000000000302121475706442400173040ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "bootimage.h" #include "binary.h" #include "stringutils.h" #include "elftools.h" #include "authentication-zynq.h" #include "authentication-zynqmp.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ Partition::Partition(PartitionHeader* header0, Section* section0) : header(header0) { section = section0; // Populate bootloader flag here in the section object - needed in StackAndAlign stage section->isBootloader = header->imageHeader->IsBootloader(); } /******************************************************************************/ Partition::Partition(PartitionHeader* header0, const uint8_t* data, Binary::Length_t length) : header(header0) { std::string partName = header->imageHeader->GetName() + StringUtils::Format(".%d",header->index); /* Pad binary data with 0s, to get 32-bit word size. This is because bootgen stores partition sizes in terms of words, so partition data *MUST* be a multiple of 32-bits */ int padding = (4 - (length & 3)) & 3; #if 1 padding = 0; #endif Binary::Length_t totallength = length + padding; section = new Section(partName, totallength); section->index = header->index; section->isPartitionData = true; section->isBitStream = (header->imageHeader->GetDomain() == Domain::PL) ? true : false; section->isFirstElfSection = (header->firstValidIndex); section->isBootloader = header->imageHeader->IsBootloader(); memcpy(section->Data, data, length); memset(section->Data+length, 0, padding); } /******************************************************************************/ void Partition::ResizeIfNecessary(Section* section) { int padding = (16 - (section->Length & 15)) & 15; section->IncreaseLengthAndPadTo(section->Length + padding, 0x00); } /******************************************************************************/ void Partition::Build( BootImage& bi, Binary& cache) { /* Push the section alloted into the Main section */ if(section != NULL) { cache.Sections.push_back(section); } /* Get the image header from this partition header */ ImageHeader& imageHeader(*this->header->imageHeader); /* Get the contexts for Authentication & Encryption */ AuthenticationContext* currentAuthCtx = imageHeader.GetAuthContext(); EncryptionContext* encryptCtx = imageHeader.GetEncryptContext(); /* Set default values Set the address for relative placement for subsequence partitions in image Don't reserve anything for partition sections */ if(!bi.XipMode) { section->Address = 0; section->Reserve = 0; } /* If the partition is a bootloader & XIP mode is enabled, then address is directly populated based on the QSPI execution address. */ if(!(imageHeader.IsBootloader() && bi.XipMode)) { /* The offset and reserve attributes only apply to first partition in image subsequent partitions in the same image are packed right after another */ if (header->IsFirstPartitionInImage()) { section->Address = imageHeader.GetOffset().ValueOrDefault(0); section->Reserve = imageHeader.GetReserve().ValueOrDefault(0); } else { section->continuation = true; } } section->Alignment = imageHeader.GetAlignment().ValueOrDefault(0); /* If the head and tail of the partition destination are not on a word boundary we will prepad the data so that DMA can more easily copy the bulk of the data a whole word at a time. The head and tail bytes are treated seperately */ if (!header->prealigned) { /* Use the starting load address to get the number of mis-align word boundary unused bytes at the beginning of a Partition data. Byte Addr Word Bytes headAlignment 0 00 00 00 00 0 1 XX 00 00 00 1 2 XX XX 00 00 2 3 XX XX XX 00 3 */ if(header->imageHeader->GetDomain() != Domain::PL) { header->headAlignment = header->loadAddress % sizeof(uint32_t); /* Use the ending load address to get the number of mis-align word boundary unused bytes at the end of a Partition data. Byte Addr Word Bytes tailAlignment 0 (1) 00 XX XX XX 3 1 (2) 00 00 XX XX 2 2 (3) 00 00 00 XX 1 3 (0) 00 00 00 00 0 */ uint32_t remainder = (header->loadAddress + section->Length) % sizeof(uint32_t); header->tailAlignment = (remainder == 0)?0:(4-remainder); } section->PadToWordAlignment(header->headAlignment,header->tailAlignment); } /* Encryption process on the partition */ if(header->preencrypted && encryptCtx->Type() != Encryption::None) { LOG_ERROR("Cannot reencrypt a partition that is already encrypted for %s", section->Name.c_str()); } encryptCtx->Process(bi, header); if (bi.bootHeader->GetPrebuiltFlag() == false) { if (header->imageHeader->GetDestCpu() == DestinationCPU::R5_0 || header->imageHeader->GetDestCpu() == DestinationCPU::R5_1) { if ((header->loadAddress < (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH)) && (header->loadAddress + header->partition->section->Length >= (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH))) { LOG_ERROR("The length of %s has exceeded TCM and cannot be loaded by FSBL.\n\t Partition Length : 0x%llx , Partition Load Address : %llX.", header->section->Name.substr(header->section->Name.find(" ") + 1).c_str(), header->partition->section->Length, header->loadAddress); } else if ((header->loadAddress > R5_BTCM_START_ADDRESS) && (header->loadAddress < (R5_BTCM_START_ADDRESS + R5_TCM_BANK_LENGTH)) && (header->loadAddress + header->partition->section->Length >= (R5_BTCM_START_ADDRESS + R5_TCM_BANK_LENGTH))) { LOG_ERROR("The length of %s has exceeded TCM and cannot be loaded by FSBL.\n\t Partition Length : 0x%llx , Partition Load Address : %llX.", header->section->Name.substr(header->section->Name.find(" ") + 1).c_str(), header->partition->section->Length, header->loadAddress); } } else if (header->imageHeader->GetDestCpu() == DestinationCPU::R5_lockstep) { if ((header->loadAddress < (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH * 4)) && (header->loadAddress + header->partition->section->Length >= (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH * 4))) { LOG_ERROR("The length of %s has exceeded TCM and cannot be loaded by FSBL.\n\t Partition Length : 0x%llx , Partition Load Address : %llX.", header->section->Name.substr(header->section->Name.find(" ") + 1).c_str(), header->partition->section->Length, header->loadAddress); } } else if (header->imageHeader->GetDestCpu() == DestinationCPU::PMU) { if (header->loadAddress + header->partition->section->Length >= PMU_RAM_END_ADDRESS) { LOG_ERROR("The length of %s has exceeded PMU RAM and cannot be loaded by FSBL.\n\t Partition Length : 0x%llx, Partition Load Address : %llX.", header->section->Name.substr(header->section->Name.find(" ") + 1).c_str(), header->partition->section->Length, header->loadAddress); } } } uint32_t padLength = 0; /* Authentication process on the partition */ if(header->presigned) { // do nothing for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { *acs = 0; } } else { header->transferSize = section->Length; /* Integrity is replaced by Checksum from 2016.3, to maintain backward compatibility, the bootheader lengths should be populated in case of either checksum or integrity. Whenever checksum is enabled for FSBL, then add the checksum size to FSBL length */ if((imageHeader.IsBootloader() && imageHeader.GetChecksumContext()->Type() != Checksum::None)) { padLength = imageHeader.GetChecksumContext()->Size(); } else { if(currentAuthCtx->authAlgorithm->Type() != Authentication::None) { padLength = header->GetPartitionPadSize64bBoundary(section); } // create AC section and add it to the end of the list. currentAuthCtx->ResizeIfNecessary(section); size_t hashPartLen = header->partition->section->Length; size_t authblock = imageHeader.GetAuthBlock(); if (authblock != 0) { hashPartLen = (authblock *1024 *1024); } size_t len = 0; while (len < (header->partition->section->Length)) { len += hashPartLen; AuthenticationCertificate* tempacs = NULL; if (bi.options.archType == Arch::ZYNQ) { tempacs = new RSA2048AuthenticationCertificate(currentAuthCtx); } else if (bi.options.archType == Arch::ZYNQMP) { tempacs = new RSA4096AuthenticationCertificate(currentAuthCtx); } if(tempacs != NULL) { tempacs->Build(bi, cache, header->partition->section, imageHeader.IsBootloader(), false); header->ac.push_back(tempacs); } } currentAuthCtx->AddAuthCertSizeToTotalFSBLSize(header); currentAuthCtx->authBlocks = authblock; } } if(imageHeader.IsBootloader() == true) { bi.SetTotalFsblFwSize(imageHeader.GetTotalFsblFwSizeIh() + padLength); bi.SetTotalPmuFwSize(imageHeader.GetTotalPmuFwSizeIh()); bi.SetPmuFwSize(imageHeader.GetPmuFwSizeIh()); bi.SetFsblFwSize(imageHeader.GetFsblFwSizeIh()); if(bi.XipMode) { // Just to make sure, not to get a negative no. as address if(imageHeader.GetFsblSourceAddrIh() > imageHeader.GetTotalPmuFwSizeIh()) { section->Address = imageHeader.GetFsblSourceAddrIh() - imageHeader.GetTotalPmuFwSizeIh(); bi.SetFsblSourceAddr(section->Address); } } } } /******************************************************************************/ void Partition::Link(BootImage &bi) { for (std::list::iterator acs = header->ac.begin(); acs != header->ac.end(); acs++) { if ((*acs)) { (*acs)->Link(bi, header->partition->section); } } } xilinx-bootgen-2024.2/partitionheadertable-versal.cpp000077500000000000000000001470771475706442400230010ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable-versal.h" #include "bootheader-versal.h" #include "authentication-versal.h" typedef enum { atfHandoffExecStateShift = 0, atfHandoffEndiannessShift = 1, atfHandoffTrustzoneShift = 2, atfHandoffExceptionLevelShift = 3, atfHandoffDestCpuShift = 5, } atf_handoff_partition_attributes; #define FSBL_MAX_PARTITIONS 6 /* Structure corresponding to each partition entry */ struct atf_handoff_partition { uint64_t entry_point; uint64_t flags; }; /* Structure for hand off parameters to ARM Trusted Firmware (ATF) */ struct atf_handoff_params_struct { uint8_t magic[4]; uint32_t num_entries; struct atf_handoff_partition handoff_partition[FSBL_MAX_PARTITIONS]; } atf_handoff_params ; /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ VersalPartitionHeader::VersalPartitionHeader(ImageHeader* imageheader, int index) : partitionEncrypted(0) , partitionUid(0) , PartitionHeader(imageheader, index) , partitionKeySrc(KeySource::None) , dpaCM(DpaCM::DpaCMDisable) , pufHdLoc(PufHdLoc::PUFinEFuse) , kekIvFile("") , lockstep(Lockstep::LockstepDisable) , cluster(0) , tcmBoot(TcmBoot::TcmBootDisable) { std::string name; slr = 0; if (imageHeader) { std::string partition_name = ""; if ((imageHeader->GetFileList().size() > 0) && (imageHeader->IsSlrPartition() == false)) { for (size_t i = 0; i < imageHeader->GetFileList().size(); i++) { partition_name += StringUtils::BaseName(imageHeader->GetFileList().at(i)); if (i != (imageHeader->GetFileList().size() - 1)) { partition_name += "_"; } } } else { partition_name = imageHeader->GetName(); } name = "PartitionHeader " + partition_name + StringUtils::Format(".%d", index); partitionAesKeyFile = imageHeader->GetAesKeyFile(); generateAesKeyFile = imageHeader->GetAesKeyFileGeneration(); if (index != 0) { partitionAesKeyFile = StringUtils::RemoveExtension(imageHeader->GetAesKeyFile()) + StringUtils::Format(".%d", index) + ".nky"; std::ifstream keyFile(partitionAesKeyFile); bool exists = keyFile.good(); if (!generateAesKeyFile && !exists) { generateAesKeyFile = true; } } partitionUid = imageHeader->GetPartitionUid(); partitionKeySrc = imageHeader->GetEncryptionKeySrc(); kekIvFile = imageHeader->GetKekIV(); } else { name = "PartitionHeader Null"; } section = new Section(name, sizeof(VersalPartitionHeaderTableStructure)); memset(section->Data, 0, section->Length); pHTable = (VersalPartitionHeaderTableStructure*)section->Data; pHTable->partitionRevokeId = imageHeader->GetPartitionRevocationId(); } /******************************************************************************/ VersalPartitionHeader::~VersalPartitionHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ void VersalPartitionHeader::ReadHeader(std::ifstream& ifs) { ifs.read((char*)pHTable, sizeof(VersalPartitionHeaderTableStructure)); uint32_t checksum = ComputeWordChecksum(pHTable, sizeof(VersalPartitionHeaderTableStructure) - sizeof(uint32_t)); if (checksum != GetChecksum()) { LOG_DEBUG(DEBUG_STAMP, "Calculated Checksum = 0x%8X, Imported Checksum = 0x%8X", checksum, GetChecksum()); LOG_ERROR("Partition Header Checksum failed for %s", section->Name.c_str()); } execAddress = GetExecAddress(); loadAddress = GetLoadAddress(); partitionSize = GetUnencryptedPartitionLength(); transferSize = GetEncryptedPartitionLength(); prealigned = true; headAlignment = GetHeadAlignment(); tailAlignment = GetTailAlignment(); authCertPresent = GetAuthCertFlag(); encryptFlag = GetEncryptFlag(); checksumType = GetChecksumType(); ownerType = GetOwnerType(); destCpu = GetDestinationCpu(); destDevice = GetDestinationDevice(); execState = GetProcessorExecState(); elfEndianess = GetElfEndianess(); exceptionLevel = GetExceptionLevel(); trustzone = GetTrustZone(); early_handoff = GetEarlyHandoff(); hivec = GetHivec(); partitionUid = GetPartitionUid(); lockstep = GetLockStepFlag(); cluster = GetDestinationCluster(); tcmBoot = GetTcmBootFlag(); presigned = (authCertPresent != 0); if (presigned) { certificateRelativeByteOffset = (GetPartitionWordOffset() - GetAuthCertificateOffset()); } } /******************************************************************************/ void VersalPartitionHeader::ReadData(std::ifstream& ifs) { uint32_t dataLen = GetTotalPartitionLength(); std::string partName = imageHeader->GetName() + "_" + std::to_string(partitionUid) + StringUtils::Format(".%d", index); Section* dsection = new Section(partName, dataLen); if (presigned) { ifs.seekg(GetAuthCertificateOffset()); } else { ifs.seekg(GetPartitionWordOffset()); } ifs.read((char*)dsection->Data, dsection->Length); dsection->isPartitionData = true; partition = new VersalPartition(this, dsection); static uint8_t encryptionHeader[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x00,0x00,0x00, 0x44,0x00,0x22,0x11,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x55,0x99,0xAA }; preencrypted = (memcmp(dsection->Data, encryptionHeader, sizeof(encryptionHeader)) == 0); } /******************************************************************************/ void VersalPartitionHeader::Build(BootImage& bi, Binary& cache) { if (section != NULL) { bi.headers.push_back(section); bi.imageHeaderTable->metaHeaderLength += section->Length; } } /******************************************************************************/ void VersalPartitionHeader::Link(BootImage &bi, PartitionHeader* next_part_hdr) { slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; bootloaderSize = bi.options.bootloaderSize; isBootloader = partition->section->isBootloader; /* Realigning the data ptr is necessary because Section->Data ptr gets changed in the RSAAuthenticationContext::ResizeIfNecessary() function call */ RealignSectionDataPtr(); /* Exec address and section count are populated only for the first of the many partitions that can be created for any elf partition */ SetExecAddress((firstValidIndex) ? execAddress : 0); SetSectionCount((uint32_t)((firstValidIndex) ? imageHeader->GetPartitionHeaderList().size() : 0)); SetEncryptedPartitionLength((uint32_t)transferSize); SetUnencryptedPartitionLength((uint32_t)(partitionSize + 3)); SetTotalPartitionLength((uint32_t)partition->section->Length); uint32_t addr = 0; if (next_part_hdr != NULL) { addr = next_part_hdr->section->Address; } SetNextPartitionHeaderOffset(addr); SetLoadAddress(loadAddress, bi.options.IsVersalNetSeries()); SetPartitionWordOffset((uint32_t)partition->section->Address); SetPartitionAttributes(); SetChecksumOffset(); SetAuthCertificateOffset(); SetPartitionId(); if (!preencrypted) { SetPartitionSecureHdrIv(partitionSecHdrIv); SetPartitionKeySrc(partitionKeySrc, bi.bifOptions); SetPartitionGreyOrBlackIv(kekIvFile); } SetReserved(); SetChecksum(); } /******************************************************************************/ void VersalPartitionHeader::SetPartitionSecureHdrIv(uint8_t* iv) { if (iv == NULL) { memset(pHTable->partitionSecureHdrIv, 0, IV_LENGTH * WORD_SIZE_IN_BYTES); } else { memcpy(pHTable->partitionSecureHdrIv, iv, IV_LENGTH * WORD_SIZE_IN_BYTES); } } /******************************************************************************/ void VersalPartitionHeader::SetPartitionKeySrc(KeySource::Type keyType, BifOptions* bifOptions) { kekIvMust = false; switch (keyType) { case KeySource::EfuseRedKey: pHTable->partitionKeySource = EFUSE_RED_KEY; break; case KeySource::BbramRedKey: pHTable->partitionKeySource = BBRAM_RED_KEY; break; case KeySource::EfuseBlkKey: pHTable->partitionKeySource = EFUSE_BLK_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_blk_key'"); } kekIvMust = true; break; case KeySource::BbramBlkKey: pHTable->partitionKeySource = BBRAM_BLK_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_blk_key'"); } kekIvMust = true; break; case KeySource::BhBlkKey: pHTable->partitionKeySource = BH_BLACK_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_blk_key'"); } kekIvMust = true; break; case KeySource::EfuseGryKey: pHTable->partitionKeySource = EFUSE_GRY_KEY; kekIvFile = bifOptions->GetEfuseKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_kek_iv' is mandatory with 'keysrc=efuse_gry_key'"); } kekIvMust = true; break; case KeySource::BbramGryKey: pHTable->partitionKeySource = BBRAM_GRY_KEY; kekIvFile = bifOptions->GetBbramKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bbram_kek_iv' is mandatory with 'keysrc=bbram_gry_key'"); } kekIvMust = true; break; case KeySource::BhGryKey: pHTable->partitionKeySource = BH_GRY_KEY; kekIvFile = bifOptions->GetBHKekIVFile(); if (kekIvFile == "") { LOG_ERROR("'bh_kek_iv' is mandatory with 'keysrc=bh_gry_key'"); } kekIvMust = true; break; case KeySource::UserKey0: pHTable->partitionKeySource = USER_KEY0; break; case KeySource::UserKey1: pHTable->partitionKeySource = USER_KEY1; break; case KeySource::UserKey2: pHTable->partitionKeySource = USER_KEY2; break; case KeySource::UserKey3: pHTable->partitionKeySource = USER_KEY3; break; case KeySource::UserKey4: pHTable->partitionKeySource = USER_KEY4; break; case KeySource::UserKey5: pHTable->partitionKeySource = USER_KEY5; break; case KeySource::UserKey6: pHTable->partitionKeySource = USER_KEY6; break; case KeySource::UserKey7: pHTable->partitionKeySource = USER_KEY7; break; case KeySource::EfuseUserKey0: pHTable->partitionKeySource = EFUSE_USER_KEY0; break; case KeySource::EfuseUserBlkKey0: pHTable->partitionKeySource = EFUSE_USER_BLK_KEY0; kekIvFile = bifOptions->GetEfuseUserKek0IVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_user_kek0_iv' is mandatory with 'keysrc=efuse_user_blk_key0'"); } kekIvMust = true; break; case KeySource::EfuseUserGryKey0: pHTable->partitionKeySource = EFUSE_USER_GRY_KEY0; kekIvFile = bifOptions->GetEfuseUserKek0IVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_user_kek0_iv' is mandatory with 'keysrc=efuse_user_gry_key0'"); } kekIvMust = true; break; case KeySource::EfuseUserKey1: pHTable->partitionKeySource = EFUSE_USER_KEY1; break; case KeySource::EfuseUserBlkKey1: pHTable->partitionKeySource = EFUSE_USER_BLK_KEY1; kekIvFile = bifOptions->GetEfuseUserKek1IVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_user_kek1_iv' is mandatory with 'keysrc=efuse_user_blk_key1'"); } kekIvMust = true; break; case KeySource::EfuseUserGryKey1: pHTable->partitionKeySource = EFUSE_USER_GRY_KEY1; kekIvFile = bifOptions->GetEfuseUserKek1IVFile(); if (kekIvFile == "") { LOG_ERROR("'efuse_user_kek1_iv' is mandatory with 'keysrc=efuse_user_gry_key1'"); } kekIvMust = true; break; case KeySource::None: default: pHTable->partitionKeySource = 0; break; } } /******************************************************************************/ void VersalPartitionHeader::SetPartitionGreyOrBlackIv(std::string ivFile) { uint8_t* ivData = new uint8_t[IV_LENGTH * 4]; memset(ivData, 0, IV_LENGTH * 4); if (ivFile != "") { FileImport fileReader; if (!fileReader.LoadHexData(ivFile, ivData, IV_LENGTH * 4)) { LOG_ERROR("Invalid no. of data bytes for Black/Grey Key IV.\n Expected length for Grey/Black IV is 12 bytes"); } } else { if (kekIvMust) { LOG_ERROR("Black/Grey IV is mandatory in case of Black/Grey key sources\n Please use 'bh_kek_iv' to specify the IV in BIF file"); } } memcpy(&pHTable->partitionGreyOrBlackIV, ivData, IV_LENGTH * 4); delete[] ivData; } /******************************************************************************/ void VersalPartitionHeader::SetEncryptedPartitionLength(uint32_t len) { pHTable->encryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void VersalPartitionHeader::SetUnencryptedPartitionLength(uint32_t len) { pHTable->unencryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void VersalPartitionHeader::SetTotalPartitionLength(uint32_t len) { pHTable->totalPartitionLength = len / sizeof(uint32_t); for (std::list::iterator acs = ac.begin(); acs != ac.end(); acs++) { if (*acs && (*acs)->section) { pHTable->totalPartitionLength += (uint32_t)((*acs)->section->Length / sizeof(uint32_t)); } } } /******************************************************************************/ void VersalPartitionHeader::SetNextPartitionHeaderOffset(uint32_t addr) { pHTable->nextPartitionHeaderOffset = addr / sizeof(uint32_t); } /******************************************************************************/ void VersalPartitionHeader::SetExecAddress(uint64_t addr) { pHTable->destinationExecAddress = addr; } /******************************************************************************/ #define R52_0A_TCMA_BASE_ADDR 0xEBA00000 /* R52_0A TCMA base address */ #define R52_1A_TCMA_BASE_ADDR 0xEBA40000 /* R52_1A TCMA base address */ #define R52_0B_TCMA_BASE_ADDR 0xEBA80000 /* R52_0B TCMA base address */ #define R52_1B_TCMA_BASE_ADDR 0xEBAC0000 /* R52_1B TCMA base address */ #define R52_TCM_CLUSTER_OFFSET 0x00080000 /* R52_TCM TCM cluster offset */ #define R52_TCMA_LOAD_ADDRESS 0x0 /* R52 TCMA load address */ #define R52_TCM_TOTAL_LENGTH 0x30000 /* R52 TCMA total length */ uint64_t VersalPartitionHeader::GetR52LoadAddr(uint64_t loadAddr) { uint64_t address = loadAddr; if ((imageHeader->GetDestCpu() == DestinationCPU::R5_0) && ((address < (R52_TCMA_LOAD_ADDRESS + R52_TCM_TOTAL_LENGTH)))) { if (((address % R52_TCM_TOTAL_LENGTH) + GetEncryptedPartitionLength()) > R52_TCM_TOTAL_LENGTH) { //Status = XPlmi_UpdateStatus(XLOADER_ERR_TCM_ADDR_OUTOF_RANGE, 0); } address += R52_0A_TCMA_BASE_ADDR + (imageHeader->GetClusterNum() * R52_TCM_CLUSTER_OFFSET); } else if ((imageHeader->GetDestCpu() == DestinationCPU::R5_1) && ((address < (R52_TCMA_LOAD_ADDRESS + R52_TCM_TOTAL_LENGTH)))) { if (((address % R52_TCM_TOTAL_LENGTH) + GetEncryptedPartitionLength()) > R52_TCM_TOTAL_LENGTH) { //Status = XPlmi_UpdateStatus(XLOADER_ERR_TCM_ADDR_OUTOF_RANGE, 0); } address += R52_1A_TCMA_BASE_ADDR + (imageHeader->GetClusterNum() * R52_TCM_CLUSTER_OFFSET); } else { /* Do nothing */ } /* Update the load address */ return address; } /******************************************************************************/ void VersalPartitionHeader::SetLoadAddress(uint64_t addr, bool versalNetSeries) { if ((imageHeader->GetPartitionType() == PartitionType::CONFIG_DATA_OBJ) || (imageHeader->GetPartitionType() == PartitionType::CFI) || (imageHeader->GetPartitionType() == PartitionType::CFI_GSC) || (imageHeader->GetPartitionType() == PartitionType::CFI_GSC_UNMASK)) { addr = 0xFFFFFFFFFFFFFFFF; } if (versalNetSeries) { if((imageHeader->GetDestCpu() == DestinationCPU::R5_0) || (imageHeader->GetDestCpu() == DestinationCPU::R5_1)) addr = GetR52LoadAddr(addr); } pHTable->destinationLoadAddress = addr; } /******************************************************************************/ void VersalPartitionHeader::SetPartitionWordOffset(uint32_t addr) { if (presigned) { pHTable->partitionWordOffset = (addr+sizeof(AuthCertificate4096Sha3PaddingStructure)) / sizeof(uint32_t); } else { pHTable->partitionWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (pHTable->partitionWordOffset != 0)) { if (IsBootloader()) { pHTable->partitionWordOffset = 0; } else { pHTable->partitionWordOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } } /******************************************************************************/ void VersalPartitionHeader::SetPartitionAttributes(void) { if (authCertPresent == 0) { authCertPresent = (imageHeader->GetAuthenticationType() == Authentication::RSA) || (imageHeader->GetAuthenticationType() == Authentication::ECDSA); } destCpu = imageHeader->GetDestCpu(); exceptionLevel = imageHeader->GetExceptionLevel(); trustzone = imageHeader->GetTrustZone(); early_handoff = imageHeader->GetEarlyHandoff(); partitionType = imageHeader->GetPartitionType(); hivec = imageHeader->GetHivec(); ownerType = imageHeader->GetPartOwner(); authBlock = imageHeader->GetAuthBlock(); dpaCM = imageHeader->GetDpacm(); pufHdLoc = imageHeader->GetPufHdLocation(); cluster = imageHeader->GetClusterNum(); if (imageHeader->GetLockStepFlag() == true) { lockstep = Lockstep::LockstepEnable; } if (imageHeader->GetTcmBootFlag() == true) { tcmBoot = TcmBoot::TcmBootEnable; } if (hivec) { if(((execState == A53ExecState::AARCH64) && (partitionType == PartitionType::ELF)) || (partitionType != PartitionType::ELF)) { LOG_ERROR("BIF attribute 'hivec' is supported only for a72(32-bit) and r5 applications."); } } if (checksumType != Checksum::None) { if (imageHeader->GetChecksumContext()->Type() != Checksum::None) { LOG_ERROR("Cannot rechecksum a partition"); } } else { checksumType = imageHeader->GetChecksumContext()->Type(); } if (authBlock != 0) { int i = 0; while (authBlock != 1) { if (authBlock % 2 == 0) { authBlock = authBlock / 2; i++; } } authBlock = (i - 1); } if ((imageHeader->GetEncryptContext() != NULL) && (imageHeader->GetEncryptContext()->Type() == Encryption::AES)) { /* Encryption to be enabled in release mode based on preencrypted flag avilable, since Encrption Context will not be AES */ partitionEncrypted = 1; } else if (encryptFlag == 1) { partitionEncrypted = 1; } else { partitionEncrypted = 0; } uint8_t endian = 0; if (elfEndianess == Endianness::BigEndian) { endian = 1; } pHTable->partitionAttributes = (trustzone << vphtTrustzoneShift) | (exceptionLevel << vphtExceptionLevelShift) | (execState << vphtExecStateShift) | (destCpu << vphtDestCpuShift) | (checksumType << vphtChecksumTypeShift) | (pufHdLoc << vphtPufHDLocationShift) | (ownerType <dataSectionCount = cnt; } /******************************************************************************/ void VersalPartitionHeader::SetChecksumOffset(void) { if (pHTable->checksumWordOffset == 0) { if (checksumSection) { pHTable->checksumWordOffset = (uint32_t)(checksumSection->Address / sizeof(uint32_t)); // 0x20: A word pointer to the Partition Checksum data. } else { pHTable->checksumWordOffset = 0; } } else { if (slaveBootSplitMode) { pHTable->checksumWordOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } /******************************************************************************/ void VersalPartitionHeader::SetAuthCertificateOffset(void) { if (certificateRelativeByteOffset != 0) { /* For presigned images, partition addr + auth cert offset from start of partition */ pHTable->authCertificateOffset = (uint32_t)((partition->section->Address) / sizeof(uint32_t)); } else if (ac.size() != 0) { /* For images signed on the go, get the address from the AC section created */ AuthenticationCertificate* acs = ac.front(); if (acs && acs->section) { pHTable->authCertificateOffset = (uint32_t)(acs->section->Address / sizeof(uint32_t)); // 0x28 } } else if (imageHeader->GetAuthenticationType() == Authentication::RSA) { /* If the image is not yet signed, partition addr + partition length - cert size */ AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); AuthenticationContext* auth = (VersalAuthenticationContext*)new VersalAuthenticationContext(Authentication::RSA); pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + partition->section->Length - auth->GetCertificateSize()) / sizeof(uint32_t)); } else if (imageHeader->GetAuthenticationType() == Authentication::ECDSA) { AuthenticationContext::SetAuthenticationKeyLength(EC_P384_KEY_LENGTH); AuthenticationContext* auth = (VersalAuthenticationContext*)new VersalAuthenticationContext(Authentication::ECDSA); pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + partition->section->Length - auth->GetCertificateSize()) / sizeof(uint32_t)); } else { /* For unauthenticated cases */ pHTable->authCertificateOffset = 0; } if (slaveBootSplitMode && (pHTable->authCertificateOffset != 0)) { if (partition->section->isBootloader) { pHTable->authCertificateOffset = 0; } else { pHTable->authCertificateOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } /******************************************************************************/ void VersalPartitionHeader::SetReserved(void) { memset(&pHTable->reserved, 0x00, MAX_PHT_RESERVED_VERSAL * sizeof(uint32_t)); } /******************************************************************************/ void VersalPartitionHeader::SetPartitionId() { pHTable->puid = partitionUid; } /******************************************************************************/ void VersalPartitionHeader::SetChecksum(void) { pHTable->pHChecksum = ComputeWordChecksum(pHTable, sizeof(VersalPartitionHeaderTableStructure) - sizeof(uint32_t)); } /******************************************************************************/ void VersalPartitionHeader::RealignSectionDataPtr(void) { pHTable = (VersalPartitionHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t VersalPartitionHeader::GetPartitionHeaderSize(void) { return sizeof(VersalPartitionHeaderTableStructure); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetSectionCount(void) { return pHTable->dataSectionCount; } /******************************************************************************/ uint32_t VersalPartitionHeader::GetChecksum(void) { return pHTable->pHChecksum; } /******************************************************************************/ uint64_t VersalPartitionHeader::GetExecAddress(void) { return pHTable->destinationExecAddress; } /******************************************************************************/ uint64_t VersalPartitionHeader::GetLoadAddress(void) { return pHTable->destinationLoadAddress; } /******************************************************************************/ uint32_t VersalPartitionHeader::GetEncryptedPartitionLength(void) { return pHTable->encryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetUnencryptedPartitionLength(void) { return pHTable->unencryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetTotalPartitionLength(void) { return pHTable->totalPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetChecksumType(void) { return ((pHTable->partitionAttributes >> vphtChecksumTypeShift) & vphtChecksumTypeMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetOwnerType(void) { return ((pHTable->partitionAttributes >> vphtPartitionOwnerShift) & vphtPartitionOwnerMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetDestinationCpu(void) { return ((pHTable->partitionAttributes >> vphtDestCpuShift) & vphtDestCpuMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetDestinationCluster(void) { return ((pHTable->partitionAttributes >> vNetphtClusterShift) & vNetphtClusterMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetProcessorExecState(void) { return ((pHTable->partitionAttributes >> vphtExecStateShift) & vphtExecStateMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetElfEndianess(void) { if ((pHTable->partitionAttributes >> vphtEndiannessShift) & vphtEndiannessMask) { return Endianness::BigEndian; } else { return Endianness::LittleEndian; } } /******************************************************************************/ uint8_t VersalPartitionHeader::GetExceptionLevel(void) { return ((pHTable->partitionAttributes >> vphtExceptionLevelShift) & vphtExceptionLevelMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetTrustZone(void) { return ((pHTable->partitionAttributes >> vphtTrustzoneShift) & vphtTrustzoneMask); } /******************************************************************************/ uint8_t VersalPartitionHeader::GetHivec(void) { return ((pHTable->partitionAttributes >> vphtHivecShift) & vphtHivecMask); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetAuthCertificateOffset(void) { return (pHTable->authCertificateOffset * sizeof(uint32_t)); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetPartitionUid(void) { return pHTable->puid; } /******************************************************************************/ uint32_t VersalPartitionHeader::GetPartitionWordOffset(void) { return (pHTable->partitionWordOffset * sizeof(uint32_t)); } /******************************************************************************/ PartitionType::Type VersalPartitionHeader::GetPartitionType(void) { return (PartitionType::Type)((pHTable->partitionAttributes >> vphtPartitionTypeShift) & vphtPartitionTypeMask); } /******************************************************************************/ DpaCM::Type VersalPartitionHeader::GetDpaCMFlag(void) { return (DpaCM::Type)((pHTable->partitionAttributes >> vphtDpaCMShift) & vphtDpaCMMask); } /******************************************************************************/ PufHdLoc::Type VersalPartitionHeader::GetPufHdLocation(void) { return (PufHdLoc::Type)((pHTable->partitionAttributes >> vphtPufHDLocationShift) & vphtPufHDLocationMask); } /******************************************************************************/ Lockstep::Type VersalPartitionHeader::GetLockStepFlag (void) { return (Lockstep::Type)((pHTable->partitionAttributes >> vNetphtlockStepShift) & vNetphtlockStepMask); } /******************************************************************************/ uint64_t VersalPartitionHeader::GetLQspiExecAddrForXip(uint64_t execAddr) { //SH -Revisit these addresses needs to be modfied for versal if ((execAddr < LQSPI_BASE_ADDR_VERSAL) || (execAddr >(LQSPI_BASE_ADDR_VERSAL + LQSPI_SIZE_VERSAL))) { LOG_DEBUG(DEBUG_STAMP, "LQSPI Range: 0x%x-0x%x, Exec Addr: 0x%x", LQSPI_BASE_ADDR_VERSAL, LQSPI_BASE_ADDR_VERSAL + LQSPI_SIZE_VERSAL, execAddr); LOG_ERROR("Execution Address of FSBL is out of Linear QSPI range in XIP mode"); } return (execAddr & LQSPI_RANGE_MASK_VERSAL); } /******************************************************************************/ uint32_t VersalPartitionHeader::GetPartitionPadSize64bBoundary(Section* sec) { return ((64 - (sec->Length & 63)) & 63); } /******************************************************************************/ void VersalPartitionHeader::SetPartitionRevokeId(uint32_t id) { pHTable->partitionRevokeId = id; } /******************************************************************************/ KeySource::Type VersalPartitionHeader::GetPartitionKeySource(void) { return (KeySource::Type)pHTable->partitionKeySource; } /******************************************************************************/ uint8_t VersalPartitionHeader::GetEncryptFlag(void) { if (pHTable->partitionKeySource != KeySource::None) { return 1; } else { return 0; } } /******************************************************************************/ uint8_t VersalPartitionHeader::GetAuthCertFlag(void) { if (pHTable->authCertificateOffset != 0) { return 1; } else { return 0; } } /******************************************************************************/ TcmBoot::Type VersalPartitionHeader::GetTcmBootFlag(void) { return (TcmBoot::Type)((pHTable->partitionAttributes >> vNetphtTcmBootShift) & vNetphtTcmBootMask); } /******************************************************************************/ void VersalPartitionHeaderTable::Build(BootImage & bi, Binary & cache) { LOG_INFO("Building the Partition Header Table"); if (!bi.options.IsVersalNetSeries()) { if (getenv("BOOTGEN_SKIP_MAX_PARTITIONS_CHECK") == NULL) { if (bi.subSysImageList.size() > MAX_NUM_IMAGES_VERSAL) { LOG_ERROR("The maximum number of images supported for Versal is %d.\n No. of images found : %d", MAX_NUM_IMAGES_VERSAL, bi.subSysImageList.size()); } if (bi.partitionHeaderList.size() > MAX_NUM_PARTITIONS_VERSAL) { LOG_ERROR("The maximum number of partitions supported for Versal is %d.\n No. of partitions found : %d", MAX_NUM_PARTITIONS_VERSAL, bi.partitionHeaderList.size()); } } else { LOG_WARNING("The ENV BOOTGEN_SKIP_MAX_PARTITIONS_CHECK is set. Skipping check for maximum number of partitions/images."); } } for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { (*partHdr)->Build(bi, cache); } UpdateAtfHandoffParams(bi); if (bi.partitionHeaderList.size() > 0) { bi.partitionHeaderTable->firstSection = bi.partitionHeaderList.front()->section; } else { bi.partitionHeaderTable->firstSection = NULL; } if ((bi.bifOptions->aHwrot == true) && (bi.options.bifOptions->metaHdrAttributes.authenticate == Authentication::None)) { LOG_ERROR("Meta Header must be authenticated when 'a_hwrot' is enabled"); } if ((bi.bifOptions->sHwrot == true) && (bi.options.bifOptions->metaHdrAttributes.encrypt == Encryption::None)) { LOG_ERROR("Meta Header must be encrypted with 'keysrc=efuse_blk_key', when 's_hwrot' is enabled"); } if ((bi.bifOptions->sHwrot == true) && (bi.options.bifOptions->metaHdrAttributes.encrKeySource != KeySource::EfuseBlkKey)) { LOG_ERROR("Meta Header must be encrypted with 'keysrc=efuse_blk_key', when 's_hwrot' is enabled"); } if (bi.bifOptions->GetHeaderAC()) { LOG_INFO("Creating Header Authentication Certificate"); ConfigureMetaHdrAuthenticationContext(bi); bi.headerAC = new VersalAuthenticationCertificate(bi.metaHdrAuthCtx); bi.headerAC->Build(bi, cache, bi.imageHeaderTable->section, false, true); } bi.imageHeaderTable->SetTotalMetaHdrLength(bi.imageHeaderTable->metaHeaderLength); if (bi.options.bifOptions->GetHeaderEncyption()) { if (bi.bootloaderFound && !(bi.bootloaderAuthenticate) && !(bi.bootloaderEncrypt)) { //LOG_ERROR("Bootloader must be encrypted or atleast authenticated to encrypt the Meta Header"); } if (bi.options.bifOptions->metaHdrAttributes.encrKeySource == KeySource::None) { bi.imageHeaderTable->metaHdrKeySrc = bi.options.cmdEncryptOptions->encryptedKeySource; } if (bi.options.bifOptions->metaHdrAttributes.encrKeyFile == "") { bi.options.bifOptions->metaHdrAttributes.encrKeyFile = "meta_header.nky"; } std::vector encrBlocks = bi.options.bifOptions->metaHdrAttributes.encrBlocks; int32_t defaultEncrBlockSize = bi.options.bifOptions->metaHdrAttributes.defEncrBlockSize; Binary::Length_t encrBlocksSize = 0; Binary::Length_t encrOverhead = 0; Binary::Length_t secureChunkSize = bi.GetSecureChunkSize(true); bi.options.bifOptions->metaHdrAttributes.encrBlocks.clear(); /* Creating encryption blocks for 64KB from user specified blocks. Consider encryption overhead as well */ for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* Push all the user blocks till the sum of user specified blocks and overhead is less than 64KB. */ if ((encrBlocksSize + encrOverhead) < secureChunkSize) { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back((encrBlocks[itr])); } /* When the sum of user specified blocks and overhead reaches 64KB, push that block and break. */ else if ((encrBlocksSize + encrOverhead) == secureChunkSize) { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back((encrBlocks[itr])); break; } /* If the sum of user specified blocks and overhead exceeds 64KB, truncate that block, .push and break.*/ else { Binary::Length_t lastBlock = secureChunkSize - (encrBlocksSize - encrBlocks[itr] + encrOverhead); encrBlocksSize += (lastBlock - encrBlocks[itr]); bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back((lastBlock)); LOG_WARNING("The last encryption block size is truncated to %d to fit into the secure chunk of 32KB.", lastBlock); break; } } /* If the user specified blocks, does not make a chunk of 64KB, then calculate the rest and push. */ if (encrBlocksSize + encrOverhead < secureChunkSize) { /* If a default size(using (*)) is mentioned, */ if (defaultEncrBlockSize != 0) { encrBlocksSize += defaultEncrBlockSize; encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); /* then push the default size untill the sum of encr blocks and overhead is < or = 64KB.*/ while (encrBlocksSize + encrOverhead < secureChunkSize) { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(defaultEncrBlockSize); encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); encrBlocksSize += defaultEncrBlockSize; } Binary::Length_t lastBlock = defaultEncrBlockSize; /* When the sum of encr blocks and overhead goes beyond 64KB, truncate the default size and push.*/ if ((encrBlocksSize + encrOverhead) > secureChunkSize) { lastBlock = secureChunkSize - (encrBlocksSize + encrOverhead - defaultEncrBlockSize); encrBlocksSize += (lastBlock - defaultEncrBlockSize); LOG_WARNING("The last encryption block size is truncated to %d to fit into the secure chunk of 32KB.", lastBlock); } bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(lastBlock); } /* If a default size(using (*)) is not mentioned, then calculate the last block that makes sum of encr blocks and overhead = 64KB and push.*/ else { encrOverhead += (SECURE_HDR_SZ + AES_GCM_TAG_SZ); bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(secureChunkSize - (encrBlocksSize + encrOverhead)); } } Binary::Length_t lastBlock = 0; uint32_t totalencrBlocks = bi.options.bifOptions->metaHdrAttributes.encrBlocks.size(); uint32_t overhead = (totalencrBlocks) * (SECURE_HDR_SZ + AES_GCM_TAG_SZ); encrBlocks.clear(); encrBlocks = bi.options.bifOptions->metaHdrAttributes.encrBlocks; bi.options.bifOptions->metaHdrAttributes.encrBlocks.clear(); /* Due to encryption over head, the actual default size on which the partition needs to be Key rolled is always less than 64KB. So first calculate the default key roll data size by substracting the overhead. */ /* Then calculate the number of such blocks possible on a given partition. */ /* Note that the last block will always be based on the partition length.*/ std::vector secureChunkEncrBlocks; uint32_t actualSecureChunkSize = bi.GetSecureChunkSize(true) - overhead; uint32_t totalKeyRollencrBlocks = EncryptionContext::GetTotalEncryptionBlocks(bi.imageHeaderTable->metaHeaderLength, secureChunkEncrBlocks, actualSecureChunkSize, &lastBlock); secureChunkEncrBlocks.clear(); for (uint32_t itr = 0; itr < totalKeyRollencrBlocks; itr++) { if ((itr == totalKeyRollencrBlocks - 1) && (lastBlock != 0)) { secureChunkEncrBlocks.push_back(lastBlock); lastBlock = 0; } else { secureChunkEncrBlocks.push_back(actualSecureChunkSize); } } /* Now chunk each default key roll data size, based on user encryption blocks. Note that the last block will always be based on the partition length.*/ bi.options.bifOptions->GetEncryptionBlocksList().clear(); for (uint32_t itr1 = 0; itr1 < totalKeyRollencrBlocks; itr1++) { if ((itr1 == totalKeyRollencrBlocks - 1) && (secureChunkEncrBlocks[itr1] != actualSecureChunkSize)) { Binary::Length_t encrBlocksSize = 0; for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { encrBlocksSize += encrBlocks[itr]; if (secureChunkEncrBlocks[itr1] > encrBlocksSize) { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(encrBlocks[itr]); } else { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(secureChunkEncrBlocks[itr1] - (encrBlocksSize - encrBlocks[itr])); break; } } } else { for (uint32_t itr = 0; itr < encrBlocks.size(); itr++) { bi.options.bifOptions->metaHdrAttributes.encrBlocks.push_back(encrBlocks[itr]); } } } totalencrBlocks = bi.options.bifOptions->metaHdrAttributes.encrBlocks.size(); uint32_t totalBlocksOverhead = (totalencrBlocks + 1) * 64; bi.encryptedHeaders = new Section("EncryptedMetaHeader", bi.imageHeaderTable->metaHeaderLength + totalBlocksOverhead); cache.Sections.push_back(bi.encryptedHeaders); } else { for (std::list::iterator itr = bi.headers.begin(); itr != bi.headers.end(); itr++) { cache.Sections.push_back(*itr); } } } /******************************************************************************/ void VersalPartitionHeaderTable::ConfigureMetaHdrAuthenticationContext(BootImage & bi) { AuthenticationContext* biAuth = NULL; for (std::list::iterator image = bi.imageList.begin(); image != bi.imageList.end(); image++) { if (((*image)->IsBootloader()) && ((*image)->GetAuthenticationType() == Authentication::None)) { //LOG_ERROR("Bootloader must be authenticated to authenticate Meta Header."); } } biAuth = (AuthenticationContext*) new VersalAuthenticationContext(bi.options.bifOptions->metaHdrAttributes.authenticate); biAuth->hashType = bi.GetAuthHashAlgo(); if (bi.bifOptions->metaHdrAttributes.ppk != "") { biAuth->SetPPKeyFile(bi.bifOptions->metaHdrAttributes.ppk); } else if (bi.bifOptions->GetPPKFileName() != "") { biAuth->SetPPKeyFile(bi.bifOptions->GetPPKFileName()); } if (bi.bifOptions->metaHdrAttributes.psk != "") { biAuth->SetPSKeyFile(bi.bifOptions->metaHdrAttributes.psk); } else if (bi.bifOptions->GetPSKFileName() != "") { biAuth->SetPSKeyFile(bi.bifOptions->GetPSKFileName()); } if (bi.bifOptions->metaHdrAttributes.spk != "") { biAuth->SetSPKeyFile(bi.bifOptions->metaHdrAttributes.spk); } else if (bi.bifOptions->GetSPKFileName() != "") { biAuth->SetSPKeyFile(bi.bifOptions->GetSPKFileName()); } if (bi.bifOptions->metaHdrAttributes.ssk != "") { biAuth->SetSSKeyFile(bi.bifOptions->metaHdrAttributes.ssk); } else if (bi.bifOptions->GetSSKFileName() != "") { biAuth->SetSSKeyFile(bi.bifOptions->GetSSKFileName()); } if (bi.bifOptions->metaHdrAttributes.spkSignature != "") { biAuth->SetSPKSignatureFile(bi.bifOptions->metaHdrAttributes.spkSignature); } biAuth->spkIdentification = bi.bifOptions->metaHdrAttributes.revokeId; //biAuth->SetPresignFile(bi.bifOptions->GetHeaderSignatureFile()); if (bi.bifOptions->metaHdrAttributes.presign != "") { biAuth->SetPresignFile(bi.bifOptions->metaHdrAttributes.presign); } AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); if (bi.bifOptions->metaHdrAttributes.authenticate == Authentication::ECDSA) { AuthenticationContext::SetAuthenticationKeyLength(EC_P384_KEY_LENGTH); } ImageHeaderTable* iht = bi.imageHeaderTable; biAuth->ResizeIfNecessary(iht->section); for (std::list::iterator ih = bi.imageList.begin(); ih != bi.imageList.end(); ih++) { biAuth->ResizeIfNecessary((*ih)->section); } for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { biAuth->ResizeIfNecessary((*partHdr)->section); } /* Header table authentication */ bi.metaHdrAuthCtx = (AuthenticationContext*)new VersalAuthenticationContext(biAuth, bi.bifOptions->metaHdrAttributes.authenticate); if (bi.bifOptions->metaHdrAttributes.presign != "") { bi.metaHdrAuthCtx->SetPresignFile(bi.bifOptions->metaHdrAttributes.presign); } } /******************************************************************************/ void VersalPartitionHeaderTable::UpdateAtfHandoffParams(BootImage & bi) { memset(&atf_handoff_params, 0, sizeof(atf_handoff_params_struct)); atf_handoff_params.magic[0] = 'X'; atf_handoff_params.magic[1] = 'L'; atf_handoff_params.magic[2] = 'N'; atf_handoff_params.magic[3] = 'X'; atf_handoff_params.num_entries = 0; for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { DestinationCPU::Type core = (*partHdr)->imageHeader->GetDestCpu(); ExceptionLevel::Type exceptionLevel = (*partHdr)->imageHeader->GetExceptionLevel(); TrustZone::Type trustzone = (*partHdr)->imageHeader->GetTrustZone(); //if((core = a72 - 0 or a72 - 1) && ((EL = EL2 && trustzone = non - secure) || (EL = EL1 && trustzone = secure) || (EL = EL1 && trustzone = non - secure))) bool valid_core = ((core == DestinationCPU::A53_0) || (core == DestinationCPU::A53_1)); bool valid_entry1 = ((exceptionLevel == ExceptionLevel::EL2) && (trustzone == TrustZone::NonSecure)); bool valid_entry2 = (exceptionLevel == ExceptionLevel::EL1); if (valid_core && (valid_entry1 || valid_entry2)) { atf_handoff_params.handoff_partition[atf_handoff_params.num_entries].entry_point = (*partHdr)->execAddress; uint8_t execState = (*partHdr)->execState; uint8_t endian = ((*partHdr)->elfEndianess == Endianness::BigEndian) ? 1 : 0; uint8_t destCpu = (core == DestinationCPU::A53_0) ? 0 : 1; atf_handoff_params.handoff_partition[atf_handoff_params.num_entries].flags = (execState << atfHandoffExecStateShift) | (endian << atfHandoffEndiannessShift) | (trustzone << atfHandoffTrustzoneShift) | (exceptionLevel << atfHandoffExceptionLevelShift) | (destCpu << atfHandoffDestCpuShift); atf_handoff_params.num_entries++; } } for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { if ((*partHdr)->update_atf_handoff_params) { memcpy((*partHdr)->partition->section->Data + (*partHdr)->atf_handoff_params_offset, &atf_handoff_params, sizeof(atf_handoff_params_struct)); } } } /******************************************************************************/ void VersalPartitionHeaderTable::Link(BootImage & bi) { uint32_t numPart = 0; for (std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); ) { PartitionHeader* currentPartHdr = (*partHdr); partHdr++; numPart++; if (numPart == bi.partitionHeaderList.size()) { currentPartHdr->Link(bi, NULL); } else { currentPartHdr->Link(bi, (*partHdr)); } } if (bi.bifOptions->GetHeaderAC()) { bi.imageHeaderTable->SetTotalMetaHdrLength(bi.imageHeaderTable->metaHeaderLength + sizeof(AuthCertificate4096Sha3PaddingStructure)); bi.imageHeaderTable->SetChecksum(); } if (bi.options.bifOptions->GetHeaderEncyption()) { LOG_INFO("Encrypting the Meta Header"); EncryptionContext* encryptCtx = bi.imageHeaderTable->GetEncryptContext(); bi.imageHeaderTable->SetTotalMetaHdrLength(bi.encryptedHeaders->Length); if (bi.bifOptions->GetHeaderAC()) { bi.imageHeaderTable->SetTotalMetaHdrLength(bi.encryptedHeaders->Length + sizeof(AuthCertificate4096Sha3PaddingStructure)); } bi.imageHeaderTable->SetChecksum(); encryptCtx->Process(bi); bi.imageHeaderTable->metaHeaderLength = bi.imageHeaderTable->GetTotalMetaHdrLength(); } if (bi.bifOptions->GetHeaderAC()) { bi.headerAC->Link(bi, bi.imageHeaderTable->section); } bi.bifOptions->CheckForSameKeyandKeySrcPair(bi.aesKeyandKeySrc); } xilinx-bootgen-2024.2/partitionheadertable-versal.h000077500000000000000000000223211475706442400224260ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _PARTITIONHEADERTABLE_VERSAL_H_ #define _PARTITIONHEADERTABLE_VERSAL_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable.h" #include "imageheadertable-versal.h" #include "bootimage.h" #include "stringutils.h" #include "options.h" #include "logger.h" #include "encryptutils.h" #include #include /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define MAX_PHT_RESERVED_VERSAL 9 typedef enum { vphtTrustzoneShift = 0, vphtTrustzoneMask = 0x1, vphtExceptionLevelShift = 1, vphtExceptionLevelMask = 0x3, vphtExecStateShift = 3, vphtExecStateMask = 0x1, vNetphtlockStepShift = 4, vNetphtlockStepMask = 0x3, vNetphtClusterShift = 6, vNetphtClusterMask = 0x3, vphtDestCpuShift = 8, vphtDestCpuMask = 0xF, vphtChecksumTypeShift = 12, vphtChecksumTypeMask = 0x3, vphtPufHDLocationShift = 14, vphtPufHDLocationMask = 0x3, vphtPartitionOwnerShift = 16, vphtPartitionOwnerMask = 0x3, vphtEndiannessShift = 18, vphtEndiannessMask = 0x1, vNetphtTcmBootShift = 19, vNetphtTcmBootMask = 0x3, vphtHivecShift = 23, vphtHivecMask = 0x1, vphtPartitionTypeShift = 24, vphtPartitionTypeMask = 0x7, vphtDpaCMShift = 27, vphtDpaCMMask = 0x3, } VersalPHTAttributes; /* Keys Source */ #define USER_KEY0 0xC5C3A5A3 #define USER_KEY1 0xC3A5C5B3 #define USER_KEY2 0xC5C3A5C3 #define USER_KEY3 0xC3A5C5D3 #define USER_KEY4 0xC5C3A5E3 #define USER_KEY5 0xC3A5C5F3 #define USER_KEY6 0xC5C3A563 #define USER_KEY7 0xC3A5C573 #define EFUSE_USER_KEY0 0x5C3CA5A3 #define EFUSE_USER_BLK_KEY0 0x5C3CA5A5 #define EFUSE_USER_GRY_KEY0 0x5C3CA5A7 #define EFUSE_USER_KEY1 0xC3A5C5A3 #define EFUSE_USER_BLK_KEY1 0xC3A5C5A5 #define EFUSE_USER_GRY_KEY1 0xC3A5C5A7 #define SECURE_16K_CHUNK 0x4000 #define SECURE_32K_CHUNK 0x8000 /* 32 KB = 32*1024 B */ #define SECURE_64K_CHUNK 0x10000 /* 64 KB = 64*1024 B */ /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t encryptedPartitionLength; // 0x00 uint32_t unencryptedPartitionLength; // 0x04 uint32_t totalPartitionLength; // 0x08 uint32_t nextPartitionHeaderOffset; // 0x0C uint64_t destinationExecAddress; // 0x10 uint64_t destinationLoadAddress; // 0x18 uint32_t partitionWordOffset; // 0x20 uint32_t partitionAttributes; // 0x24 uint32_t dataSectionCount; // 0x28 uint32_t checksumWordOffset; // 0x2C uint32_t puid; // 0x30 uint32_t authCertificateOffset; // 0x34 uint32_t partitionSecureHdrIv[IV_LENGTH]; // 0x38 uint32_t partitionKeySource; // 0x44 uint32_t partitionGreyOrBlackIV[IV_LENGTH]; // 0x48 uint32_t partitionRevokeId; // 0x54 uint32_t reserved[MAX_PHT_RESERVED_VERSAL]; // 0x58 uint32_t pHChecksum; // 0x7C } VersalPartitionHeaderTableStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalPartitionHeader : public PartitionHeader { public: VersalPartitionHeader(ImageHeader* imageheader, int index0); ~VersalPartitionHeader(); void ReadHeader(std::ifstream& ifs); void ReadData(std::ifstream& ifs); void Build(BootImage & bi, Binary & cache); void Link(BootImage & bi, PartitionHeader* next_part_hdr); void RealignSectionDataPtr(void); bool IsFirstPartitionInImage() { return index == 0; } void SetPartitionSecureHdrIv(uint8_t * iv); void SetPartitionKeySrc(KeySource::Type, BifOptions*); void SetPartitionGreyOrBlackIv(std::string); void SetEncryptedPartitionLength(uint32_t len); void SetUnencryptedPartitionLength(uint32_t len); void SetTotalPartitionLength(uint32_t len); void SetLoadAddress(uint64_t addr, bool versalNetSeries); void SetExecAddress(uint64_t addr); uint64_t GetR52LoadAddr(uint64_t loadAddr); void SetPartitionWordOffset(uint32_t addr); void SetPartitionAttributes(void); void SetSectionCount(uint32_t cnt); void SetChecksumOffset(void); void SetImageHeaderOffset(uint32_t offset) {}; void SetAuthCertificateOffset(void); void SetPartitionId(void); void SetChecksum(void); void SetReserved(void); void SetNextPartitionHeaderOffset(uint32_t addr); void SetPartitionRevokeId(uint32_t id); KeySource::Type GetPartitionKeySource(void); uint8_t GetEncryptFlag(void); uint8_t GetAuthCertFlag(void); bool IsBootloader(void) { return isBootloader; } bool IsPmcdata(void) { return isPmcdata; } uint8_t GetChecksumType(void); uint8_t GetOwnerType(void); uint8_t GetDestinationCpu(void); uint8_t GetDestinationCluster(void); uint8_t GetProcessorExecState(void); uint8_t GetElfEndianess(void); uint8_t GetExceptionLevel(void); uint8_t GetTrustZone(void); uint8_t GetHivec(void); uint32_t GetPartitionHeaderSize(void); uint32_t GetChecksum(void); uint64_t GetExecAddress(void); uint64_t GetLoadAddress(void); uint32_t GetEncryptedPartitionLength(void); uint32_t GetUnencryptedPartitionLength(void); uint32_t GetTotalPartitionLength(void); uint32_t GetAuthCertificateOffset(void); uint32_t GetPartitionWordOffset(void); uint32_t GetPartitionPadSize64bBoundary(Section*); PartitionType::Type GetPartitionType(void); DpaCM::Type GetDpaCMFlag(void); PufHdLoc::Type GetPufHdLocation(void); Lockstep::Type GetLockStepFlag(void); uint32_t GetPartitionUid(void); uint64_t GetLQspiExecAddrForXip(uint64_t addr); uint32_t GetSectionCount(void); TcmBoot::Type GetTcmBootFlag(void); private: uint8_t partitionEncrypted; uint8_t slr; uint8_t cluster; Lockstep::Type lockstep; uint32_t partitionUid; KeySource::Type partitionKeySrc; bool kekIvMust; std::string kekIvFile; DpaCM::Type dpaCM; PufHdLoc::Type pufHdLoc; TcmBoot::Type tcmBoot; VersalPartitionHeaderTableStructure* pHTable; }; /******************************************************************************/ class VersalPartitionHeaderTable : public PartitionHeaderTable { public: void Build(BootImage& bi, Binary& cache); void ConfigureMetaHdrAuthenticationContext(BootImage& bi); void UpdateAtfHandoffParams(BootImage& bi); void SetPartitionHashinOptionalData(BootImage & bi); void Link(BootImage& bi); Section* firstSection; }; /******************************************************************************/ class VersalPartition : public Partition { public: VersalPartition(PartitionHeader* hdr, Section* section0); VersalPartition(PartitionHeader* hdr, const uint8_t* data, Binary::Length_t length); size_t GetTotalDataChunks(Binary::Length_t partitionSize, std::vector& dataChunks, bool encryptionFlag); size_t GetBootloaderTotalDataChunks(Binary::Length_t partitionSize, std::vector& dataChunks, bool encryptionFlag); void ChunkifyAndHash(Section * section, bool encryptionFlag); void Build(BootImage& bi, Binary& cache); void Link(BootImage& bi); private: PartitionHeader* header; uint64_t firstChunkSize; bool versalNetSeries; uint64_t secureChunkSize; }; #endif xilinx-bootgen-2024.2/partitionheadertable-zynq.cpp000077500000000000000000000317471475706442400225020ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable-zynq.h" #include "authentication-zynq.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqPartitionHeader::ZynqPartitionHeader(ImageHeader* imageheader, int index) : PartitionHeader(imageheader, index) { std::string name; if (imageHeader) { name = "PartitionHeader " + imageHeader->GetName() + StringUtils::Format(".%d", index); } else { name = "PartitionHeader Null"; } section = new Section(name, sizeof(ZynqPartitionHeaderTableStructure)); memset(section->Data, 0, section->Length); pHTable = (ZynqPartitionHeaderTableStructure*)section->Data; } /******************************************************************************/ ZynqPartitionHeader::~ZynqPartitionHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqPartitionHeader::ReadHeader(std::ifstream& ifs) { ifs.read((char*)pHTable, sizeof(ZynqPartitionHeaderTableStructure)); uint32_t checksum = ComputeWordChecksum(pHTable, sizeof(ZynqPartitionHeaderTableStructure) - sizeof(uint32_t)); if (checksum != GetChecksum()) { LOG_DEBUG(DEBUG_STAMP, "Calculated Checksum = 0x%8X, Imported Checksum = 0x%8X", checksum, GetChecksum()); LOG_ERROR("Partition Header Checksum failed for %s", section->Name.c_str()); } execAddress = GetExecAddress(); loadAddress = GetLoadAddress(); partitionSize = GetUnencryptedPartitionLength(); transferSize = GetEncryptedPartitionLength(); prealigned = true; headAlignment = GetHeadAlignment(); tailAlignment = GetTailAlignment(); authCertPresent = GetAuthCertFlag(); checksumType = GetChecksumType(); ownerType = GetOwnerType(); presigned = (authCertPresent != 0); if (presigned) { certificateRelativeByteOffset = (GetAuthCertificateOffset() - GetPartitionWordOffset()); } } /******************************************************************************/ void ZynqPartitionHeader::ReadData(std::ifstream& ifs) { uint32_t dataLen = GetTotalPartitionLength(); std::string partName = imageHeader->GetName() + StringUtils::Format(".%d", index); Section* dsection = new Section(partName, dataLen); LOG_INFO("TESTINFO: SecName-%s, SecAdd-0x%x", dsection->Name.c_str(), dsection->Address); ifs.seekg(GetPartitionWordOffset()); ifs.read((char*)dsection->Data, dsection->Length); partition = new Partition(this, dsection); static uint8_t encryptionHeader[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x00,0x00,0x00, 0x44,0x00,0x22,0x11,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x55,0x99,0xAA }; preencrypted = (memcmp(dsection->Data, encryptionHeader, sizeof(encryptionHeader)) == 0); } /******************************************************************************/ void ZynqPartitionHeader::SetEncryptedPartitionLength(uint32_t len) { pHTable->encryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void ZynqPartitionHeader::SetUnencryptedPartitionLength(uint32_t len) { pHTable->unencryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void ZynqPartitionHeader::SetTotalPartitionLength(uint32_t len) { pHTable->totalPartitionLength = len / sizeof(uint32_t); for (std::list::iterator acs = ac.begin(); acs != ac.end(); acs++) { if (*acs && (*acs)->section) { pHTable->totalPartitionLength += (uint32_t)((*acs)->section->Length / sizeof(uint32_t)); // additional size of AC } } } /******************************************************************************/ void ZynqPartitionHeader::SetLoadAddress(uint64_t addr, bool arch) { pHTable->destinationLoadAddress = (uint32_t)addr; } /******************************************************************************/ void ZynqPartitionHeader::SetExecAddress(uint64_t addr) { pHTable->destinationExecAddress = (uint32_t)addr; } /******************************************************************************/ void ZynqPartitionHeader::SetPartitionWordOffset(uint32_t addr) { pHTable->partitionWordOffset = addr / sizeof(uint32_t); } /******************************************************************************/ void ZynqPartitionHeader::SetPartitionAttributes(void) { if (authCertPresent == 0) { authCertPresent = imageHeader->GetAuthenticationType() == Authentication::RSA; } switch (imageHeader->GetDomain()) { case Domain::PL: destDevice = DestinationDevice::DEST_DEV_PL; break; case Domain::PS: destDevice = DestinationDevice::DEST_DEV_PS; break; default: LOG_ERROR("Destination domain %d not supported", imageHeader->GetDomain()); } if (checksumType != Checksum::None) { if (imageHeader->GetChecksumContext()->Type() != Checksum::None) { LOG_ERROR("Cannot rechecksum a partition"); } } else { checksumType = imageHeader->GetChecksumContext()->Type(); } ownerType = imageHeader->GetPartOwner(); pHTable->partitionAttributes = (headAlignment << PH_HEAD_ALIGN_SHIFT) | (tailAlignment << PH_TAIL_ALIGN_SHIFT) | (destDevice << PH_DEST_DEVICE_SHIFT) | (authCertPresent << PH_AC_FLAG_SHIFT) | (checksumType << PH_CHECKSUM_SHIFT) | (ownerType << PH_OWNER_SHIFT); } /******************************************************************************/ void ZynqPartitionHeader::SetSectionCount(uint32_t cnt) { pHTable->dataSectionCount = cnt; } /******************************************************************************/ void ZynqPartitionHeader::SetChecksumOffset(void) { if (pHTable->checksumWordOffset == 0) { if (checksumSection) { pHTable->checksumWordOffset = (uint32_t)(checksumSection->Address / sizeof(uint32_t)); } else { pHTable->checksumWordOffset = 0; } } } /******************************************************************************/ void ZynqPartitionHeader::SetImageHeaderOffset(uint32_t offset) { pHTable->imageHeaderWordOffset = offset / sizeof(uint32_t); } /******************************************************************************/ void ZynqPartitionHeader::SetAuthCertificateOffset(void) { if (certificateRelativeByteOffset != 0) { /* For presigned images, partition addr + auth cert offset from start of partition */ pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + certificateRelativeByteOffset) / sizeof(uint32_t)); } else if (ac.size() != 0) { /* For images signed on the go, get the address from the AC section created */ AuthenticationCertificate* acs = ac.front(); if (acs && acs->section) { pHTable->authCertificateOffset = (uint32_t)(acs->section->Address / sizeof(uint32_t)); } } else if (imageHeader->GetAuthenticationType() == Authentication::RSA) { /* If the image is not yet signed, partition addr + partition length - cert size */ AuthenticationContext::SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + partition->section->Length - sizeof(AuthCertificate2048Structure)) / sizeof(uint32_t)); } else { /* For unauthenticated cases */ pHTable->authCertificateOffset = 0; } } /******************************************************************************/ void ZynqPartitionHeader::SetReserved(void) { for (uint8_t i = 0; ireserved[i] = 0x0; } } /******************************************************************************/ void ZynqPartitionHeader::SetChecksum(void) { pHTable->pHChecksum = ComputeWordChecksum(pHTable, sizeof(ZynqPartitionHeaderTableStructure) - sizeof(uint32_t)); } /******************************************************************************/ void ZynqPartitionHeader::RealignSectionDataPtr(void) { pHTable = (ZynqPartitionHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetPartitionHeaderSize(void) { return sizeof(ZynqPartitionHeaderTableStructure); } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetChecksum(void) { return pHTable->pHChecksum; } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetExecAddress(void) { return pHTable->destinationExecAddress; } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetLoadAddress(void) { return pHTable->destinationLoadAddress; } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetEncryptedPartitionLength(void) { return pHTable->encryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetUnencryptedPartitionLength(void) { return pHTable->unencryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetTotalPartitionLength(void) { return pHTable->totalPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetAuthCertificateOffset(void) { return (pHTable->authCertificateOffset * sizeof(uint32_t)); } /******************************************************************************/ uint32_t ZynqPartitionHeader::GetPartitionWordOffset(void) { return (pHTable->partitionWordOffset * sizeof(uint32_t)); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetDestinationDevice(void) { return ((pHTable->partitionAttributes >> PH_DEST_DEVICE_SHIFT) & PH_DEST_DEVICE_MASK); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetHeadAlignment(void) { return ((pHTable->partitionAttributes >> PH_HEAD_ALIGN_SHIFT) & PH_HEAD_ALIGN_MASK); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetTailAlignment(void) { return ((pHTable->partitionAttributes >> PH_TAIL_ALIGN_SHIFT) & PH_TAIL_ALIGN_MASK); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetAuthCertFlag(void) { return ((pHTable->partitionAttributes >> PH_AC_FLAG_SHIFT) & PH_AC_FLAG_MASK); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetChecksumType(void) { return ((pHTable->partitionAttributes >> PH_CHECKSUM_SHIFT) & PH_CHECKSUM_MASK); } /******************************************************************************/ uint8_t ZynqPartitionHeader::GetOwnerType(void) { return ((pHTable->partitionAttributes >> PH_OWNER_SHIFT) & PH_OWNER_MASK); } /******************************************************************************/ void ZynqPartitionHeader::SetBitLoadAddress(bool load, uint32_t val) { if (load) { loadAddress = val; } else { loadAddress = 0; } } xilinx-bootgen-2024.2/partitionheadertable-zynq.h000077500000000000000000000113771475706442400221440ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _PARTITIONHEADERTABLE_ZYNQ_H_ #define _PARTITIONHEADERTABLE_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable.h" #include "imageheadertable-zynq.h" #include "checksum.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define PHT_RESERVED 4 #define PH_TAIL_ALIGN_SHIFT 0 #define PH_TAIL_ALIGN_MASK 0x3 #define PH_HEAD_ALIGN_SHIFT 2 #define PH_HEAD_ALIGN_MASK 0x3 #define PH_DEST_DEVICE_SHIFT 4 #define PH_DEST_DEVICE_MASK 0xF #define PH_CHECKSUM_SHIFT 12 #define PH_CHECKSUM_MASK 0x7 #define PH_AC_FLAG_SHIFT 15 #define PH_AC_FLAG_MASK 0x1 #define PH_OWNER_SHIFT 16 #define PH_OWNER_MASK 0x3 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t encryptedPartitionLength; // 0x00 uint32_t unencryptedPartitionLength; // 0x04 uint32_t totalPartitionLength; // 0x08 uint32_t destinationLoadAddress; // 0x0C uint32_t destinationExecAddress; // 0x10 uint32_t partitionWordOffset; // 0x14 uint32_t partitionAttributes; // 0x18 uint32_t dataSectionCount; // 0x1C uint32_t checksumWordOffset; // 0x20 uint32_t imageHeaderWordOffset; // 0x24 uint32_t authCertificateOffset; // 0x28 uint32_t reserved[PHT_RESERVED]; // 0x2C uint32_t pHChecksum; // 0x3C } ZynqPartitionHeaderTableStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ class ZynqPartitionHeader : public PartitionHeader { public: ZynqPartitionHeader(ImageHeader* imageheader, int index0); ~ZynqPartitionHeader(); void ReadHeader(std::ifstream& ifs); void ReadData(std::ifstream& ifs); void SetEncryptedPartitionLength(uint32_t len); void SetUnencryptedPartitionLength(uint32_t len); void SetTotalPartitionLength(uint32_t len); void SetLoadAddress(uint64_t addr, bool arch); void SetExecAddress(uint64_t addr); void SetPartitionWordOffset(uint32_t addr); void SetPartitionAttributes(void); void SetSectionCount(uint32_t cnt); void SetChecksumOffset(void); void SetImageHeaderOffset(uint32_t offset); void SetAuthCertificateOffset(void); void SetChecksum(void); void SetReserved(void); void SetBitLoadAddress(bool load, uint32_t val); void RealignSectionDataPtr(void); bool IsBootloader(void) { return isBootloader; } uint8_t GetDestinationDevice(void); uint8_t GetHeadAlignment(void); uint8_t GetTailAlignment(void); uint8_t GetAuthCertFlag(void); uint8_t GetChecksumType(void); uint8_t GetOwnerType(void); uint32_t GetPartitionHeaderSize(void); uint32_t GetChecksum(void); uint32_t GetExecAddress(void); uint32_t GetLoadAddress(void); uint32_t GetEncryptedPartitionLength(void); uint32_t GetUnencryptedPartitionLength(void); uint32_t GetTotalPartitionLength(void); uint32_t GetAuthCertificateOffset(void); uint32_t GetPartitionWordOffset(void); bool IsFirstPartitionInImage() { return index == 0; } private: ZynqPartitionHeaderTableStructure* pHTable; }; #endif xilinx-bootgen-2024.2/partitionheadertable-zynqmp.cpp000077500000000000000000000470151475706442400230320ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable-zynqmp.h" #include "authentication-zynqmp.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ ZynqMpPartitionHeader::ZynqMpPartitionHeader(ImageHeader* imageheader, int index) : partitionEncrypted(0) , PartitionHeader(imageheader, index) { std::string name; if (imageHeader) { name = "PartitionHeader " + imageHeader->GetName() + StringUtils::Format(".%d", index); partitionAesKeyFile = imageHeader->GetAesKeyFile(); generateAesKeyFile = imageHeader->GetAesKeyFileGeneration(); if (index != 0) { partitionAesKeyFile = StringUtils::RemoveExtension(imageHeader->GetAesKeyFile()) + StringUtils::Format(".%d", index) + ".nky"; std::ifstream keyFile(partitionAesKeyFile); bool exists = keyFile.good(); if (!generateAesKeyFile && !exists) { generateAesKeyFile = true; } } } else { name = "PartitionHeader Null"; } section = new Section(name, sizeof(ZynqMpPartitionHeaderTableStructure)); memset(section->Data, 0, section->Length); pHTable = (ZynqMpPartitionHeaderTableStructure*)section->Data; } /******************************************************************************/ ZynqMpPartitionHeader::~ZynqMpPartitionHeader() { if (section != NULL) { delete section; } } /******************************************************************************/ void ZynqMpPartitionHeader::ReadHeader(std::ifstream& ifs) { ifs.read((char*)pHTable, sizeof(ZynqMpPartitionHeaderTableStructure)); uint32_t checksum = ComputeWordChecksum(pHTable, sizeof(ZynqMpPartitionHeaderTableStructure) - sizeof(uint32_t)); if (checksum != GetChecksum()) { LOG_DEBUG(DEBUG_STAMP, "Calculated Checksum = 0x%8X, Imported Checksum = 0x%8X", checksum, GetChecksum()); LOG_ERROR("Partition Header Checksum failed for %s", section->Name.c_str()); } execAddress = GetExecAddress(); loadAddress = GetLoadAddress(); partitionSize = GetUnencryptedPartitionLength(); transferSize = GetEncryptedPartitionLength(); prealigned = true; headAlignment = GetHeadAlignment(); tailAlignment = GetTailAlignment(); authCertPresent = GetAuthCertFlag(); encryptFlag = GetEncryptFlag(); checksumType = GetChecksumType(); ownerType = GetOwnerType(); destCpu = GetDestinationCpu(); destDevice = GetDestinationDevice(); execState = GetProcessorExecState(); elfEndianess = GetElfEndianess(); exceptionLevel = GetExceptionLevel(); trustzone = GetTrustZone(); early_handoff = GetEarlyHandoff(); hivec = GetHivec(); authBlock = GetAuthblock(); presigned = (authCertPresent != 0); if (presigned) { certificateRelativeByteOffset = (GetAuthCertificateOffset() - GetPartitionWordOffset()); } } /******************************************************************************/ void ZynqMpPartitionHeader::ReadData(std::ifstream& ifs) { uint32_t data_len = GetTotalPartitionLength(); std::string part_name = imageHeader->GetName() + StringUtils::Format(".%d", index); Section* dsection = new Section(part_name, data_len); ifs.seekg(GetPartitionWordOffset()); ifs.read((char*)dsection->Data, dsection->Length); partition = new Partition(this, dsection); static uint8_t encryptionHeader[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x00,0x00,0x00, 0x44,0x00,0x22,0x11,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x55,0x99,0xAA }; preencrypted = (memcmp(dsection->Data, encryptionHeader, sizeof(encryptionHeader)) == 0); } /******************************************************************************/ void ZynqMpPartitionHeader::SetEncryptedPartitionLength(uint32_t len) { pHTable->encryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void ZynqMpPartitionHeader::SetUnencryptedPartitionLength(uint32_t len) { pHTable->unencryptedPartitionLength = len / sizeof(uint32_t); } /******************************************************************************/ void ZynqMpPartitionHeader::SetTotalPartitionLength(uint32_t len) { pHTable->totalPartitionLength = len / sizeof(uint32_t); for (std::list::iterator acs = ac.begin(); acs != ac.end(); acs++) { if (*acs && (*acs)->section) { pHTable->totalPartitionLength += (uint32_t)((*acs)->section->Length / sizeof(uint32_t)); // additional size of AC } } } /******************************************************************************/ void ZynqMpPartitionHeader::SetNextPartitionHeaderOffset(void) { static PartitionHeader* prev_part_hdr = NULL; if (prev_part_hdr != NULL) { ZynqMpPartitionHeaderTableStructure* prev_pht = (ZynqMpPartitionHeaderTableStructure*)prev_part_hdr->section->Data; prev_pht->nextPartitionHeaderOffset = (uint32_t)(section->Address / sizeof(uint32_t)); if (slaveBootSplitMode && (prev_pht->nextPartitionHeaderOffset != 0)) { prev_pht->nextPartitionHeaderOffset -= fullBhSize / sizeof(uint32_t); } prev_part_hdr->SetChecksum(); } prev_part_hdr = this; } /******************************************************************************/ void ZynqMpPartitionHeader::SetExecAddress(uint64_t addr) { pHTable->destinationExecAddress = addr; } /******************************************************************************/ void ZynqMpPartitionHeader::SetLoadAddress(uint64_t addr, bool arch) { pHTable->destinationLoadAddress = addr; } /******************************************************************************/ void ZynqMpPartitionHeader::SetPartitionWordOffset(uint32_t addr) { pHTable->partitionWordOffset = addr / sizeof(uint32_t); if (slaveBootSplitMode && (pHTable->partitionWordOffset != 0)) { if (IsBootloader()) { pHTable->partitionWordOffset = 0; } else { pHTable->partitionWordOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } /******************************************************************************/ void ZynqMpPartitionHeader::SetPartitionAttributes(void) { if (authCertPresent == 0) { authCertPresent = imageHeader->GetAuthenticationType() == Authentication::RSA; } destDevice = imageHeader->GetDestinationDevice(); destCpu = imageHeader->GetDestCpu(); exceptionLevel = imageHeader->GetExceptionLevel(); trustzone = imageHeader->GetTrustZone(); early_handoff = imageHeader->GetEarlyHandoff(); hivec = imageHeader->GetHivec(); if (hivec) { if ((destCpu == DestinationCPU::PMU) || (destDevice == DestinationDevice::DEST_DEV_PL) || (execState == A53ExecState::AARCH64)) { LOG_ERROR("BIF attribute 'hivec' is supported only for a53(32-bit) and r5 applications."); } } if (checksumType != Checksum::None) { if (imageHeader->GetChecksumContext()->Type() != Checksum::None) { LOG_ERROR("Cannot rechecksum a partition"); } } else { checksumType = imageHeader->GetChecksumContext()->Type(); } ownerType = imageHeader->GetPartOwner(); authBlock = imageHeader->GetAuthBlock(); if (authBlock != 0) { int i = 0; while (authBlock != 1) { if (authBlock % 2 == 0) { authBlock = authBlock / 2; i++; } } authBlock = (i - 1); } if ((imageHeader->GetEncryptContext() != NULL) && (imageHeader->GetEncryptContext()->Type() == Encryption::AES)) { partitionEncrypted = 1; } else if (encryptFlag == 1) { /* Encryption to be enabled in release mode based on preencrypted flag available, since Encrption Context will not be AES */ partitionEncrypted = 1; } else { partitionEncrypted = 0; } uint8_t endian = 0; if (elfEndianess == Endianness::LittleEndian) { endian = 0; } else if (elfEndianess == Endianness::BigEndian) { endian = 1; } pHTable->partitionAttributes = (trustzone << PH_TRUSTZONE_SHIFT_ZYNQMP) | (exceptionLevel << PH_EXCEPTION_LEVEL_SHIFT_ZYNQMP) | (execState << PH_EXEC_STATE_SHIFT_ZYNQMP) | (destDevice << PH_DEST_DEVICE_SHIFT_ZYNQMP) | (partitionEncrypted << PH_ENCRYPT_SHIFT_ZYNQMP) | (destCpu << PH_DEST_CPU_SHIFT_ZYNQMP) | (authCertPresent << PH_AC_FLAG_SHIFT_ZYNQMP) | (checksumType << PH_CHECKSUM_SHIFT_ZYNQMP) | (ownerType << PH_OWNER_SHIFT_ZYNQMP) | (endian << PH_ENDIAN_SHIFT_ZYNQMP) | (early_handoff << PH_EARLY_HANDOFF_SHIFT_ZYNQMP) | (authBlock << PH_AUTH_BLOCK_SHIFT_ZYNQMP) | (hivec << PH_HIVEC_SHIFT_ZYNQMP); } /******************************************************************************/ void ZynqMpPartitionHeader::SetSectionCount(uint32_t cnt) { pHTable->dataSectionCount = cnt; } /******************************************************************************/ void ZynqMpPartitionHeader::SetChecksumOffset(void) { if (pHTable->checksumWordOffset == 0) { if (checksumSection) { pHTable->checksumWordOffset = (uint32_t)(checksumSection->Address / sizeof(uint32_t)); // 0x20: A word pointer to the Partition Checksum data. } else { pHTable->checksumWordOffset = 0; } } else { if (slaveBootSplitMode) { pHTable->checksumWordOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } /******************************************************************************/ void ZynqMpPartitionHeader::SetImageHeaderOffset(uint32_t offset) { pHTable->imageHeaderWordOffset = offset / sizeof(uint32_t); if (slaveBootSplitMode && (pHTable->imageHeaderWordOffset != 0)) { pHTable->imageHeaderWordOffset -= fullBhSize / sizeof(uint32_t); } } /******************************************************************************/ void ZynqMpPartitionHeader::SetAuthCertificateOffset(void) { if (certificateRelativeByteOffset != 0) { /* For presigned images, partition addr + auth cert offset from start of partition */ pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + certificateRelativeByteOffset) / sizeof(uint32_t)); } else if (ac.size() != 0) { /* For images signed on the go, get the address from the AC section created */ AuthenticationCertificate* acs = ac.front(); if (acs && acs->section) { pHTable->authCertificateOffset = (uint32_t)(acs->section->Address / sizeof(uint32_t)); } } else if (imageHeader->GetAuthenticationType() == Authentication::RSA) { /* If the image is not yet signed, partition addr + partition length - cert size */ AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); pHTable->authCertificateOffset = (uint32_t)((partition->section->Address + partition->section->Length - sizeof(AuthCertificate4096Structure)) / sizeof(uint32_t)); } else { /* For unauthenticated cases */ pHTable->authCertificateOffset = 0; } if (slaveBootSplitMode && (pHTable->authCertificateOffset != 0)) { if (partition->section->isBootloader) { pHTable->authCertificateOffset = 0; } else { pHTable->authCertificateOffset -= (fullBhSize + allHdrSize + bootloaderSize) / sizeof(uint32_t); } } } /******************************************************************************/ void ZynqMpPartitionHeader::SetPartitionNumber(uint32_t partNum) { pHTable->partitionNumber = partNum; } /******************************************************************************/ void ZynqMpPartitionHeader::SetChecksum(void) { pHTable->pHChecksum = ComputeWordChecksum(pHTable, sizeof(ZynqMpPartitionHeaderTableStructure) - sizeof(uint32_t)); } /******************************************************************************/ void ZynqMpPartitionHeader::RealignSectionDataPtr(void) { pHTable = (ZynqMpPartitionHeaderTableStructure*)section->Data; } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetPartitionHeaderSize(void) { return sizeof(ZynqMpPartitionHeaderTableStructure); } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetChecksum(void) { return pHTable->pHChecksum; } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetPartitionNumber(void) { return pHTable->partitionNumber; } /******************************************************************************/ uint64_t ZynqMpPartitionHeader::GetExecAddress(void) { return pHTable->destinationExecAddress; } /******************************************************************************/ uint64_t ZynqMpPartitionHeader::GetLoadAddress(void) { return pHTable->destinationLoadAddress; } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetEncryptedPartitionLength(void) { return pHTable->encryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetUnencryptedPartitionLength(void) { return pHTable->unencryptedPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetTotalPartitionLength(void) { return pHTable->totalPartitionLength * sizeof(uint32_t); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetDestinationDevice(void) { return ((pHTable->partitionAttributes >> PH_DEST_DEVICE_SHIFT_ZYNQMP) & PH_DEST_DEVICE_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetEncryptFlag(void) { return ((pHTable->partitionAttributes >> PH_ENCRYPT_SHIFT_ZYNQMP) & PH_ENCRYPT_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetAuthCertFlag(void) { return ((pHTable->partitionAttributes >> PH_AC_FLAG_SHIFT_ZYNQMP) & PH_AC_FLAG_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetChecksumType(void) { return ((pHTable->partitionAttributes >> PH_CHECKSUM_SHIFT_ZYNQMP) & PH_CHECKSUM_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetOwnerType(void) { return ((pHTable->partitionAttributes >> PH_OWNER_SHIFT_ZYNQMP) & PH_OWNER_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetDestinationCpu(void) { return ((pHTable->partitionAttributes >> PH_DEST_CPU_SHIFT_ZYNQMP) & PH_DEST_CPU_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetProcessorExecState(void) { return ((pHTable->partitionAttributes >> PH_EXEC_STATE_SHIFT_ZYNQMP) & PH_EXEC_STATE_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetElfEndianess(void) { if ((pHTable->partitionAttributes >> PH_ENDIAN_SHIFT_ZYNQMP) & PH_ENDIAN_MASK_ZYNQMP) { return Endianness::BigEndian; } else { return Endianness::LittleEndian; } } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetExceptionLevel(void) { return ((pHTable->partitionAttributes >> PH_EXCEPTION_LEVEL_SHIFT_ZYNQMP) & PH_EXCEPTION_LEVEL_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetTrustZone(void) { return ((pHTable->partitionAttributes >> PH_TRUSTZONE_SHIFT_ZYNQMP) & PH_TRUSTZONE_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetEarlyHandoff(void) { return ((pHTable->partitionAttributes >> PH_EARLY_HANDOFF_SHIFT_ZYNQMP) & PH_EARLY_HANDOFF_MASK_ZYNQMP); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetHivec(void) { return ((pHTable->partitionAttributes >> PH_HIVEC_SHIFT_ZYNQMP) & PH_HIVEC_MASK_ZYNQMP); } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetAuthCertificateOffset(void) { return (pHTable->authCertificateOffset * sizeof(uint32_t)); } /******************************************************************************/ uint8_t ZynqMpPartitionHeader::GetAuthblock(void) { uint8_t block = ((pHTable->partitionAttributes >> PH_AUTH_BLOCK_SHIFT_ZYNQMP) & PH_AUTH_BLOCK_MASK_ZYNQMP); if (block != 0) { block = 1 << (block + 1); } return block; } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetPartitionWordOffset(void) { return (pHTable->partitionWordOffset * sizeof(uint32_t)); } /******************************************************************************/ uint32_t ZynqMpPartitionHeader::GetPartitionPadSize64bBoundary(Section* sec) { return ((64 - (sec->Length & 63)) & 63); } /******************************************************************************/ void ZynqMpPartitionHeader::SetBitLoadAddress(bool load, uint32_t val) { if (load) { loadAddress = val; } else { loadAddress = 0xFFFFFFFF; } } xilinx-bootgen-2024.2/partitionheadertable-zynqmp.h000077500000000000000000000141501475706442400224710ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _PARTITIONHEADERTABLE_ZYNQMP_H_ #define _PARTITIONHEADERTABLE_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "partitionheadertable.h" #include "imageheadertable-zynqmp.h" #include "encryption.h" #include "checksum.h" /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define PH_TRUSTZONE_SHIFT_ZYNQMP 0 #define PH_TRUSTZONE_MASK_ZYNQMP 0x1 #define PH_EXCEPTION_LEVEL_SHIFT_ZYNQMP 1 #define PH_EXCEPTION_LEVEL_MASK_ZYNQMP 0x3 #define PH_EXEC_STATE_SHIFT_ZYNQMP 3 #define PH_EXEC_STATE_MASK_ZYNQMP 0x1 #define PH_DEST_DEVICE_SHIFT_ZYNQMP 4 #define PH_DEST_DEVICE_MASK_ZYNQMP 0x7 #define PH_ENCRYPT_SHIFT_ZYNQMP 7 #define PH_ENCRYPT_MASK_ZYNQMP 0x1 #define PH_DEST_CPU_SHIFT_ZYNQMP 8 #define PH_DEST_CPU_MASK_ZYNQMP 0xF #define PH_CHECKSUM_SHIFT_ZYNQMP 12 #define PH_CHECKSUM_MASK_ZYNQMP 0x7 #define PH_AC_FLAG_SHIFT_ZYNQMP 15 #define PH_AC_FLAG_MASK_ZYNQMP 0x1 #define PH_OWNER_SHIFT_ZYNQMP 16 #define PH_OWNER_MASK_ZYNQMP 0x3 #define PH_ENDIAN_SHIFT_ZYNQMP 18 #define PH_ENDIAN_MASK_ZYNQMP 0x1 #define PH_EARLY_HANDOFF_SHIFT_ZYNQMP 19 #define PH_EARLY_HANDOFF_MASK_ZYNQMP 0x1 #define PH_AUTH_BLOCK_SHIFT_ZYNQMP 20 #define PH_AUTH_BLOCK_MASK_ZYNQMP 0x7 #define PH_HIVEC_SHIFT_ZYNQMP 23 #define PH_HIVEC_MASK_ZYNQMP 0x1 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t encryptedPartitionLength; // 0x00 uint32_t unencryptedPartitionLength; // 0x04 uint32_t totalPartitionLength; // 0x08 uint32_t nextPartitionHeaderOffset; // 0x0C uint64_t destinationExecAddress; // 0x10 uint64_t destinationLoadAddress; // 0x18 uint32_t partitionWordOffset; // 0x20 uint32_t partitionAttributes; // 0x24 uint32_t dataSectionCount; // 0x28 uint32_t checksumWordOffset; // 0x2C uint32_t imageHeaderWordOffset; // 0x30 uint32_t authCertificateOffset; // 0x34 uint32_t partitionNumber; // 0x38 uint32_t pHChecksum; // 0x3C } ZynqMpPartitionHeaderTableStructure; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpPartitionHeader : public PartitionHeader { public: ZynqMpPartitionHeader(ImageHeader* imageheader, int index0); ~ZynqMpPartitionHeader(); void ReadHeader(std::ifstream& ifs); void ReadData(std::ifstream& ifs); void RealignSectionDataPtr(void); void SetEncryptedPartitionLength(uint32_t len); void SetUnencryptedPartitionLength(uint32_t len); void SetTotalPartitionLength(uint32_t len); void SetLoadAddress(uint64_t addr, bool arch); void SetExecAddress(uint64_t addr); void SetPartitionWordOffset(uint32_t addr); void SetPartitionAttributes(void); void SetSectionCount(uint32_t cnt); void SetChecksumOffset(void); void SetImageHeaderOffset(uint32_t offset); void SetAuthCertificateOffset(void); void SetPartitionNumber(uint32_t partNum); void SetChecksum(void); void SetNextPartitionHeaderOffset(void); void SetBitLoadAddress(bool load, uint32_t val); bool IsBootloader(void) { return isBootloader; } uint8_t GetDestinationDevice(void); uint8_t GetEncryptFlag(void); uint8_t GetAuthCertFlag(void); uint8_t GetChecksumType(void); uint8_t GetOwnerType(void); uint8_t GetDestinationCpu(void); uint8_t GetProcessorExecState(void); uint8_t GetElfEndianess(void); uint8_t GetExceptionLevel(void); uint8_t GetTrustZone(void); uint8_t GetEarlyHandoff(void); uint8_t GetHivec(void); uint32_t GetPartitionHeaderSize(void); uint32_t GetChecksum(void); uint32_t GetPartitionNumber(void); uint64_t GetExecAddress(void); uint64_t GetLoadAddress(void); uint32_t GetEncryptedPartitionLength(void); uint32_t GetUnencryptedPartitionLength(void); uint32_t GetTotalPartitionLength(void); uint32_t GetAuthCertificateOffset(void); uint8_t GetAuthblock(void); uint32_t GetPartitionWordOffset(void); uint32_t GetPartitionPadSize64bBoundary(Section*); bool IsFirstPartitionInImage() { return index == 0; } private: uint8_t partitionEncrypted; ZynqMpPartitionHeaderTableStructure* pHTable; }; #endif xilinx-bootgen-2024.2/partitionheadertable.cpp000077500000000000000000000404631475706442400214760ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- ************************************************* H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootimage.h" #include "stringutils.h" #include #include #include "options.h" #include "partitionheadertable-zynq.h" #include "authentication-zynq.h" #include "authentication-zynqmp.h" #include "partitionheadertable-zynqmp.h" #include "partitionheadertable-versal.h" #include "logger.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void PartitionHeaderTable::Build(BootImage &bi, Binary& cache) { LOG_INFO("Building the Partition Header Table"); for(std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { (*partHdr)->Build(bi,cache); bi.partCount++; if ((*partHdr)->imageHeader->IsUserPartitionNumSet()) { (*partHdr)->partitionNum = ((*partHdr)->imageHeader->GetUserPartitionNum()) + (*partHdr)->index; } else { (*partHdr)->partitionNum = bi.partCount - 1; } } PartitionHeader* nullHeader = NULL; if (bi.options.archType == Arch::ZYNQMP) { nullHeader = new ZynqMpPartitionHeader(NULL, 0); } else { nullHeader = new ZynqPartitionHeader(NULL, 0); } if (nullHeader != NULL) { nullHeader->SetChecksum(); nullHeader->Build(bi, cache); bi.nullPartHeaderSection = nullHeader->section; uint8_t maxPartitions = bi.imageHeaderTable->GetMaxNumOfPartitions(); if (bi.options.DoPadHeaderTable()) { int paddingsize = maxPartitions - bi.partitionHeaderList.size(); if (paddingsize > 0) { nullHeader->section->Reserve = (1 + paddingsize) * 64; } } if (bi.partitionHeaderList.size() > 0) { firstSection = bi.partitionHeaderList.front()->section; } else { firstSection = nullHeader->section; } } if (bi.bifOptions->GetHeaderAC() && ! bi.options.GetLegacyFlag()) { LOG_INFO("Creating Header Authentication Certificate"); AuthenticationContext* biAuth = NULL; for (std::list::iterator image = bi.imageList.begin(); image != bi.imageList.end(); image++) { AuthenticationContext* imageAuth = (AuthenticationContext*)(*image)->GetAuthContext(); imageAuth->hashType = bi.GetAuthHashAlgo(); if (((*image)->IsBootloader()) && ((*image)->GetAuthenticationType() == Authentication::None)) { LOG_ERROR("Bootloader must be authenticated to authenticate rest of the partitions"); } if (!biAuth && (*image)->IsBootloader()) { if (bi.options.archType == Arch::ZYNQMP) { AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqMpAuthenticationContext(imageAuth); } else { AuthenticationContext::SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqAuthenticationContext(imageAuth); } biAuth->hashType = bi.GetAuthHashAlgo(); } else if (!biAuth && ((*image)->GetAuthenticationType() != Authentication::None)) { if (bi.options.archType == Arch::ZYNQMP) { AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqMpAuthenticationContext(imageAuth); } else { AuthenticationContext::SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqAuthenticationContext(imageAuth); } biAuth->hashType = bi.GetAuthHashAlgo(); } } if(!biAuth && bi.bifOptions->GetHeaderAC()) { if (bi.options.archType == Arch::ZYNQMP) { AuthenticationContext::SetAuthenticationKeyLength(RSA_4096_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqMpAuthenticationContext(bi.currentAuthCtx); } else { AuthenticationContext::SetAuthenticationKeyLength(RSA_2048_KEY_LENGTH); biAuth = (AuthenticationContext*) new ZynqAuthenticationContext(bi.currentAuthCtx); } biAuth->hashType = bi.GetAuthHashAlgo(); } if (bi.bifOptions->GetSPKFileName() != "") { biAuth->SetSPKeyFile(bi.bifOptions->GetSPKFileName()); biAuth->ParseSPKeyFile(bi.bifOptions->GetSPKFileName()); } if (bi.bifOptions->GetSSKFileName() != "") { biAuth->SetSSKeyFile(bi.bifOptions->GetSSKFileName()); biAuth->ParseSSKeyFile(bi.bifOptions->GetSSKFileName()); } if (bi.bifOptions->GetSPKSignFileName() != "") { biAuth->SetSPKSignatureFile(bi.bifOptions->GetSPKSignFileName()); } if (bi.bifOptions->GetBHSignFileName() != "") { biAuth->SetBHSignatureFile(bi.bifOptions->GetBHSignFileName()); } if (bi.bifOptions->GetPpkSelectionGlobal()) { biAuth->ppkSelect = bi.bifOptions->GetPpkSelection(); } if (bi.bifOptions->GetSpkSelectionGlobal()) { biAuth->spkSelect = bi.bifOptions->GetSpkSelection(); } if (bi.bifOptions->GetSpkIdGlobal()) { biAuth->spkIdentification = bi.bifOptions->GetSpkId(); } biAuth->SetPresignFile(bi.bifOptions->GetHeaderSignatureFile()); /* Resize sections to guarantee size is mod 64. */ ImageHeaderTable* iht = bi.imageHeaderTable; biAuth->ResizeIfNecessary(iht->section); for( std::list::iterator ih = bi.imageList.begin(); ih !=bi.imageList.end(); ih++) { biAuth->ResizeIfNecessary((*ih)->section); } for(std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { biAuth->ResizeIfNecessary((*partHdr)->section); } /* Header AC authentication */ if (bi.options.archType == Arch::ZYNQMP) { bi.headerAC = new RSA4096AuthenticationCertificate(biAuth); } else { bi.headerAC = new RSA2048AuthenticationCertificate(biAuth); } bi.headerAC->Build(bi, cache, iht->section, false, true); } else if (bi.options.DoPadHeaderTable()) { if (nullHeader != NULL) { nullHeader->section->Reserve += bi.currentAuthCtx->GetCertificateSize(); } } } /******************************************************************************/ void PartitionHeaderTable::BuildPartitions(BootImage &bi, Binary& cache) { for(std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { (*partHdr)->partition->Build(bi, cache); } } /******************************************************************************/ void PartitionHeaderTable::Link(BootImage &bi) { for(std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { (*partHdr)->Link(bi, NULL); (*partHdr)->SetNextPartitionHeaderOffset(); } if (bi.bifOptions->GetHeaderAC() && ! bi.options.GetLegacyFlag()) { bi.headerAC->Link(bi, bi.imageHeaderTable->section); } std::list::iterator partHdr = bi.partitionHeaderList.begin(); for (uint32_t currHdr = 0; currHdr < bi.partitionHeaderList.size(); currHdr++, partHdr++) { if ((*partHdr)->imageHeader->GetDomain() != Domain::PL) { uint8_t currCpu = (*partHdr)->GetDestinationCpu(); uint64_t currStrtAddr = (*partHdr)->GetLoadAddress(); uint64_t currEndAddr = currStrtAddr + (*partHdr)->GetPartitionSize(); if ((*partHdr)->imageHeader->IsBootloader()) { currEndAddr = currStrtAddr + (*partHdr)->imageHeader->GetTotalFsblFwSizeIh(); } bool currCpuR5 = (currCpu == DestinationCPU :: R5_0 || currCpu == DestinationCPU :: R5_1 || currCpu == DestinationCPU :: R5_lockstep); bool isCurrPartitionOnTcm = false; std::list::iterator nextPartHdr = bi.partitionHeaderList.begin(); std::advance(nextPartHdr, currHdr + 1); for (uint32_t nxtHdr = currHdr + 1; nxtHdr < bi.partitionHeaderList.size(); nxtHdr++) { if ((*nextPartHdr)->imageHeader->GetDomain() != Domain::PL) { uint8_t nxtCpu = (*nextPartHdr)->GetDestinationCpu(); uint64_t nxtStrtAddr = (*nextPartHdr)->GetLoadAddress(); uint64_t nxtEndAddr = nxtStrtAddr + (*nextPartHdr)->GetPartitionSize(); if ((*nextPartHdr)->imageHeader->IsBootloader()) { nxtEndAddr = nxtStrtAddr + (*nextPartHdr)->imageHeader->GetTotalFsblFwSizeIh(); } bool nxtCpuR5 = (nxtCpu == DestinationCPU :: R5_0 || nxtCpu == DestinationCPU :: R5_1 || nxtCpu == DestinationCPU :: R5_lockstep); bool isNxtPartitionOnTcm = false; if (currCpuR5 != nxtCpuR5) { isCurrPartitionOnTcm = IsTcmMemoryRange((currCpu == DestinationCPU :: R5_lockstep) ? true:false, currStrtAddr, currEndAddr); isNxtPartitionOnTcm = IsTcmMemoryRange((nxtCpu == DestinationCPU :: R5_lockstep) ? true:false, nxtStrtAddr, nxtEndAddr); if (isCurrPartitionOnTcm || isNxtPartitionOnTcm) { std::advance(nextPartHdr, 1); continue; } } if ((nxtEndAddr >= currStrtAddr) && (nxtStrtAddr < currEndAddr)) { LOG_WARNING("Partition %s range is overlapped with partition %s memory range", (*partHdr)->partition->section->Name.c_str(), (*nextPartHdr)->partition->section->Name.c_str()); LOG_TRACE("Current Partition %s Start Address is %X and End Address is %X ,Next Partition %s Start Address is %X and End Address %X",(*partHdr)->partition->section->Name.c_str(), currStrtAddr, currEndAddr, (*nextPartHdr)->partition->section->Name.c_str(),nxtStrtAddr, nxtEndAddr); } std::advance(nextPartHdr, 1); } } } } } /******************************************************************************/ void PartitionHeaderTable::LinkPartitions(BootImage &bi) { for(std::list::iterator partHdr = bi.partitionHeaderList.begin(); partHdr != bi.partitionHeaderList.end(); partHdr++) { (*partHdr)->partition->Link(bi); } } /******************************************************************************/ PartitionHeader::PartitionHeader(ImageHeader* imageheader, int index) : imageHeader(imageheader) , index(index) , partition(NULL) , checksumSection(NULL) , headAlignment(0) , tailAlignment(0) , authCertPresent(0) , encryptFlag(0) , checksumType(0) , destDevice(0) , ownerType(0) , prealigned(false) , certificateRelativeByteOffset(0) , preencrypted(false) , presigned(false) , loadAddress(0) , execAddress(0) , partitionSize(0) , transferSize(0) , firstValidIndex(false) , execState(A53ExecState::AARCH64) , trustzone(TrustZone::NonSecure) , exceptionLevel(ExceptionLevel::EL3) , early_handoff(false) , hivec(false) , partitionNum(0) , slaveBootSplitMode(false) , isBootloader(false) , destCpu(0) , allHdrSize(0) , bootloaderSize(0) , fullBhSize(0) , authBlock(0) , elfEndianess(Endianness::LittleEndian) , generateAesKeyFile(false) , partitionSecHdrIv(NULL) , firstChunkSize(0) , isPmcdata(false) , partitionType(PartitionType::RESERVED) , update_atf_handoff_params(false) , atf_handoff_params_offset(0) { if(imageheader != NULL) { isBootloader = imageHeader->IsBootloader(); } preservedBitstreamHdr.data = NULL; preservedBitstreamHdr.size = 0; } /******************************************************************************/ PartitionHeader::~PartitionHeader() { } /******************************************************************************/ void PartitionHeader::Build(BootImage& bi, Binary& cache) { if(section != NULL) { cache.Sections.push_back(section); } } /******************************************************************************/ void PartitionHeader::Link(BootImage &bi, PartitionHeader* next_part_hdr) { /* Realigning the data ptr is necessary because Section->Data ptr gets changed in the RSAAuthenticationContext::ResizeIfNecessary() function call */ slaveBootSplitMode = (bi.bifOptions->GetSplitMode() == SplitMode::SlaveMode) ? true : false; fullBhSize = bi.options.bootheaderSize; allHdrSize = bi.options.allHeaderSize; bootloaderSize = bi.options.bootloaderSize; isBootloader = partition->section->isBootloader; RealignSectionDataPtr(); SetEncryptedPartitionLength((uint32_t)transferSize); SetUnencryptedPartitionLength((uint32_t)(partitionSize+3)); SetTotalPartitionLength((uint32_t)partition->section->Length); SetLoadAddress(loadAddress, false); SetExecAddress((firstValidIndex) ? execAddress : 0); SetPartitionWordOffset((uint32_t)partition->section->Address); SetPartitionAttributes(); SetSectionCount((uint32_t)((firstValidIndex) ? imageHeader->GetPartitionHeaderList().size() : 0)); SetChecksumOffset(); SetImageHeaderOffset((uint32_t)imageHeader->section->Address); SetAuthCertificateOffset(); SetReserved(); SetPartitionNumber(partitionNum); SetChecksum(); } /****************************************************************************************************************/ bool PartitionHeaderTable::IsTcmMemoryRange(bool isR5LockStep, uint64_t strtAddr, uint64_t endAddr) { bool tcm_R5 = false; if (isR5LockStep) { tcm_R5 = ((strtAddr > R5_BTCM_START_ADDRESS) && (strtAddr < (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH * 4)) && (endAddr <= (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH * 4))); } else { bool Tcm = (strtAddr >= R5_TCM_START_ADDRESS) && (strtAddr < (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH)) && (endAddr <= (R5_TCM_START_ADDRESS + R5_TCM_BANK_LENGTH)); bool Btcm = ((strtAddr > R5_BTCM_START_ADDRESS) && (strtAddr < (R5_BTCM_START_ADDRESS + R5_TCM_BANK_LENGTH)) && (endAddr <= (R5_BTCM_START_ADDRESS + R5_TCM_BANK_LENGTH))); tcm_R5 = (Tcm || Btcm); } return tcm_R5; } xilinx-bootgen-2024.2/partitionheadertable.h000077500000000000000000000175541475706442400211500ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _PARTITIONHEADERTABLE_H_ #define _PARTITIONHEADERTABLE_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "bootheader.h" /* -------------------------------------------------------------------------------- ***************************************** C L A S S R E F E R E N C E S *** -------------------------------------------------------------------------------- */ class BaseThing; class Options; class BootImage; class Section; class PartitionHeader; class ImageHeader; class Partition; class ChecksumContext; class MD5ChecksumContext; /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ typedef struct { uint32_t* data; uint32_t size; } PreservedHeader; /*----------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class PartitionHeader : public BaseThing { public: PartitionHeader(ImageHeader* imageheader, int index); virtual ~PartitionHeader(); virtual void Build(BootImage& bi, Binary& cache); virtual void Link(BootImage& bi, PartitionHeader* next_part_hdr); virtual void ReadHeader(std::ifstream& ifs) = 0; virtual void ReadData(std::ifstream& ifs) = 0; virtual void RealignSectionDataPtr(void) {} virtual void SetEncryptedPartitionLength(uint32_t len) {} virtual void SetUnencryptedPartitionLength(uint32_t len) {} virtual void SetTotalPartitionLength(uint32_t len) {} virtual void SetLoadAddress(uint64_t addr, bool arch) {} virtual void SetExecAddress(uint64_t addr) {} virtual void SetPartitionWordOffset(uint32_t addr) {} virtual void SetPartitionAttributes(void) {} virtual void SetSectionCount(uint32_t cnt) {} virtual void SetChecksumOffset(void) {} virtual void SetImageHeaderOffset(uint32_t offset) {} virtual void SetAuthCertificateOffset(void) {} virtual void SetPartitionNumber(uint32_t partNum) {} virtual void SetChecksum(void) {} virtual void SetReserved(void) {} virtual void SetNextPartitionHeaderOffset(void) {} virtual void SetBitLoadAddress(bool load, uint32_t val) {} virtual void SetPartitionSize(Binary::Length_t) {} virtual bool IsFirstPartitionInImage(void) { return false; } virtual bool IsBootloader(void) { return false; } virtual uint32_t GetPartitionHeaderSize(void) { return 0; } virtual uint32_t GetPartitionNumber(void) { return 0; } virtual uint32_t GetChecksum(void) { return 0; }; virtual uint32_t GetAuthCertificateOffset(void) { return 0; }; virtual uint8_t GetAuthblock(void) { return 0; }; virtual uint32_t GetPartitionWordOffset(void) { return 0; }; virtual uint8_t GetDestinationDevice(void) { return 0; }; virtual uint8_t GetHeadAlignment(void) { return 0; }; virtual uint8_t GetTailAlignment(void) { return 0; }; virtual uint8_t GetEncryptFlag(void) { return 0; }; virtual uint8_t GetAuthCertFlag(void) { return 0; }; virtual uint8_t GetChecksumType(void) { return 0; }; virtual uint8_t GetOwnerType(void) { return 0; }; virtual uint8_t GetDestinationCpu(void) { return 0; }; virtual uint8_t GetProcessorExecState(void) { return 0; }; virtual uint8_t GetElfEndianess(void) { return 0; }; virtual uint8_t GetExceptionLevel(void) { return 0; }; virtual uint8_t GetTrustZone(void) { return 0; }; virtual uint8_t GetEarlyHandoff(void) { return 0; }; virtual uint8_t GetHivec(void) { return 0; }; virtual uint32_t GetPartitionPadSize64bBoundary(Section*) { return 0; }; virtual uint32_t GetEncryptedPartitionLength(void) { return 0; }; virtual PartitionType::Type GetPartitionType(void) { return PartitionType::RESERVED; } virtual uint32_t GetSectionCount(void) { return 0; } Binary::Address_t GetLoadAddress(void) { return loadAddress; } Binary::Address_t GetExecAddress(void) { return execAddress; } Binary::Length_t GetPartitionSize(void) { return partitionSize; } Binary::Length_t GetTransferSize(void) { return transferSize; } uint32_t GetCertificateRelativeByteOffset(void) { return certificateRelativeByteOffset; } uint8_t IsAuthCertPresent(void) { return authCertPresent; } uint32_t GetpartitionNum(void) { return partitionNum; } std::string GetPartitionAesKeyFile(void) { return partitionAesKeyFile; } bool GenerateAesKeyFlag(void) {return generateAesKeyFile; } ImageHeader* imageHeader; Partition* partition; std::list ac; Section* checksumSection; PreservedHeader preservedBitstreamHdr; int index; bool prealigned; bool preencrypted; bool presigned; bool firstValidIndex; uint8_t execState; uint8_t elfEndianess; uint32_t certificateRelativeByteOffset; uint8_t* partitionSecHdrIv; Binary::Address_t loadAddress; Binary::Address_t execAddress; Binary::Length_t partitionSize; Binary::Length_t transferSize; uint32_t partitionNum; std::string partitionAesKeyFile; bool generateAesKeyFile; // Attributes uint8_t headAlignment; uint8_t tailAlignment; uint8_t destDevice; uint8_t destCpu; uint8_t authCertPresent; uint8_t encryptFlag; uint8_t checksumType; uint8_t partitionType; uint8_t ownerType; uint8_t exceptionLevel; uint8_t trustzone; uint8_t early_handoff; uint8_t hivec; uint8_t authBlock; uint64_t firstChunkSize; uint64_t atf_handoff_params_offset; bool update_atf_handoff_params; protected: bool slaveBootSplitMode; uint32_t fullBhSize; uint32_t allHdrSize; uint32_t bootloaderSize; bool isBootloader; bool isPmcdata; }; /******************************************************************************/ class PartitionHeaderTable { public: PartitionHeaderTable() {} virtual ~PartitionHeaderTable() {} virtual void Build(BootImage& bi, Binary& cache); virtual void BuildPartitions(BootImage& bi, Binary& cache); virtual void Link(BootImage& bi); virtual void LinkPartitions(BootImage& bi); bool IsTcmMemoryRange(bool isR5LockStep, uint64_t strtAddr, uint64_t endAddr); Section* firstSection; }; /******************************************************************************/ class Partition : public BaseThing { public: Partition(PartitionHeader* hdr, Section* section0); Partition(PartitionHeader* hdr, const uint8_t* data, Binary::Length_t length); virtual ~Partition() {} virtual void Build(BootImage& bi, Binary& cache); virtual void Link(BootImage& bi); void ResizeIfNecessary(Section* section); private: PartitionHeader* header; }; #endif xilinx-bootgen-2024.2/position.hh000066400000000000000000000113111475706442400167500ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Positions for Bison parsers in C++ Copyright (C) 2002-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file ../bisonflex/position.hh ** Define the BIF::position class. */ #ifndef YY_YY_BISONFLEX_POSITION_HH_INCLUDED # define YY_YY_BISONFLEX_POSITION_HH_INCLUDED # include // std::max # include # include # ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULL nullptr # else # define YY_NULL 0 # endif # endif /* Line 36 of location.cc */ #line 24 "../s/bif.y" namespace BIF { /* Line 36 of location.cc */ #line 58 "../bisonflex/position.hh" /// Abstract a position. class position { public: /// Construct a position. explicit position (std::string* f = YY_NULL, unsigned int l = 1u, unsigned int c = 1u) : filename (f) , line (l) , column (c) { } /// Initialization. void initialize (std::string* fn = YY_NULL, unsigned int l = 1u, unsigned int c = 1u) { filename = fn; line = l; column = c; } /** \name Line and Column related manipulators ** \{ */ /// (line related) Advance to the COUNT next lines. void lines (int count = 1) { column = 1u; line += count; } /// (column related) Advance to the COUNT next columns. void columns (int count = 1) { column = std::max (1u, column + count); } /** \} */ /// File name to which this position refers. std::string* filename; /// Current line number. unsigned int line; /// Current column number. unsigned int column; }; /// Add and assign a position. inline position& operator+= (position& res, const int width) { res.columns (width); return res; } /// Add two position objects. inline const position operator+ (const position& begin, const int width) { position res = begin; return res += width; } /// Add and assign a position. inline position& operator-= (position& res, const int width) { return res += -width; } /// Add two position objects. inline const position operator- (const position& begin, const int width) { return begin + -width; } /// Compare two position objects. inline bool operator== (const position& pos1, const position& pos2) { return (pos1.line == pos2.line && pos1.column == pos2.column && (pos1.filename == pos2.filename || (pos1.filename && pos2.filename && *pos1.filename == *pos2.filename))); } /// Compare two position objects. inline bool operator!= (const position& pos1, const position& pos2) { return !(pos1 == pos2); } /** \brief Intercept output stream redirection. ** \param ostr the destination output stream ** \param pos a reference to the position to redirect */ template inline std::basic_ostream& operator<< (std::basic_ostream& ostr, const position& pos) { if (pos.filename) ostr << *pos.filename << ':'; return ostr << pos.line << '.' << pos.column; } /* Line 148 of location.cc */ #line 24 "../s/bif.y" } // BIF /* Line 148 of location.cc */ #line 174 "../bisonflex/position.hh" #endif /* !YY_YY_BISONFLEX_POSITION_HH_INCLUDED */ xilinx-bootgen-2024.2/postprocess.cpp000077500000000000000000000032501475706442400176610ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include "imageheadertable-versal.h" #include "partitionheadertable-versal.h" #include "bootimage-versal.h" #include "bootimage.h" extern "C" { #include "cdo-npi.h" }; bool VersalImageHeader::PostProcessCdo(const uint8_t* cdo_data, Binary::Length_t cdo_size) { void * new_data = NULL; size_t new_size = 0; if (cdocmd_post_process_cdo(cdo_data, cdo_size, &new_data, &new_size)) { LOG_ERROR("CDO post process error"); return false; } if (new_data == NULL) return false; SetPartitionType(PartitionType::CONFIG_DATA_OBJ); PartitionHeader* hdr = new VersalPartitionHeader(this, 0); hdr->firstValidIndex = true; hdr->execAddress = 0; hdr->loadAddress = 0xFFFFFFFFFFFFFFFF; hdr->partitionSize = hdr->transferSize = new_size; hdr->partition = new VersalPartition(hdr, (uint8_t*)new_data, new_size); partitionHeaderList.push_back(hdr); return true; } xilinx-bootgen-2024.2/readimage-versal.cpp000077500000000000000000001432161475706442400205140ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include "readimage-versal.h" #include "authentication-versal.h" #define SEPARATOR "--------------------------------------------------------------------------------" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ void VersalReadImage::Separator(void) { #ifdef SEPARATOR std::cout << SEPARATOR << std::endl; #else std::cout << std::endl; #endif } /******************************************************************************/ VersalReadImage::~VersalReadImage() { if (bH != NULL) { delete[] bH; } if (iH != NULL) { delete[] iH; } if (iHT != NULL) { delete[] iHT; } if (pHT != NULL) { delete[] pHT; } } /**********************************************************************************************/ void VersalReadImage::DisplayOptionalData() { //Return without displaying anything if optional data size in IHT is 0 if(iHT->optionalDataSize == 0){ LOG_INFO("Optional data does not exist"); return; } size_t result; uint32_t read_opData = 0; uint32_t opData_total_length = 0; uint32_t opData_length = 0; uint32_t opData_id = 0; uint32_t opData_hdr_length = sizeof(uint32_t); uint32_t opData_checksum_length = sizeof(uint32_t); bool smap_header_found = false; uint32_t offset; int cnt_opData = 0; //Opening PDI to read optional data FILE *binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } //Creating text file to dump optional data FILE* filePtr; std::string fName = StringUtils::FolderPath(binFilename); if (dumpPath != "") { fName = dumpPath; } fName = fName + "/" + "optional_data.txt"; filePtr = fopen(fName.c_str(), "wb"); if (!filePtr) { fclose(filePtr); LOG_ERROR("Cannot create file %s", fName.c_str()); } if (bH && ((bH->smapWords[0] == 0xDD000000) || (bH->smapWords[0] == 0x00DD0000) || (bH->smapWords[0] == 0x000000DD))) { smap_header_found = true; } if(bH) { offset = bH->imageHeaderByteOffset; } else { if(smap_header_found) { offset = sizeof(VersalSmapWidthTable); } else { offset = 0; } } offset += sizeof(VersalImageHeaderTableStructure); while(!feof(binFile)) { if(read_opData == (iHT->optionalDataSize * 4)) break; //Extracting optional data header if (!(fseek(binFile, offset, SEEK_SET))) { uint32_t* buffer = new uint32_t[opData_hdr_length]; size_t result = fread(buffer, 1, opData_hdr_length, binFile); if (result != opData_hdr_length) { LOG_ERROR("Error parsing Optional Data Header from PDI file"); } opData_total_length = (((*buffer) & 0xFFFF0000) >> 16) * 4; opData_id = (*buffer) & 0x0000FFFF; opData_length = opData_total_length - opData_hdr_length - opData_checksum_length; } else { LOG_ERROR("Error parsing Optional Data Header from PDI file"); } if(0x00 <= opData_id && opData_id <= 0x20){ read_opData += opData_total_length; offset += opData_total_length; continue; } if(opData_id == 0xFFFF){ break; } fprintf(filePtr, "Optional Data %d\n", ++cnt_opData); fprintf(filePtr, "Length %d\n", opData_length); fprintf(filePtr, "ID %d\n", opData_id); fprintf(filePtr, "Data\n"); char* opData_buffer = new char[opData_length]; result = fread(opData_buffer, 1, opData_length, binFile); if (result != opData_length) { LOG_ERROR("Error parsing Optional Data from PDI file"); } for(uint32_t i=0; i < opData_length; i++) { char c1 = (*opData_buffer); opData_buffer++; fprintf(filePtr, "%x", c1); } offset += opData_total_length; read_opData += opData_total_length; fprintf(filePtr, "\n\n"); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); fclose(binFile); } /**********************************************************************************************/ void VersalReadImage::ReadPartitions() { size_t result; uint64_t offset = 0; uint32_t cnt_index = 0; FILE *binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } std::list::iterator pHT = pHTs.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { uint32_t part_sec_index = 0; uint32_t part_sec_count = 0; uint32_t part_index = 0; for (cnt_index = 0; cnt_index < (*iH)->dataSectionCount; cnt_index++) { uint32_t length = (*pHT)->encryptedPartitionLength * 4; uint8_t* buffer = new uint8_t[length]; offset = (*pHT)->partitionWordOffset * 4; if ((*pHT)->dataSectionCount > 0) { part_sec_index = 0; part_sec_count = (*pHT)->dataSectionCount; } if (((*pHT)->dataSectionCount > 0) && (cnt_index != 0)) { part_index++; } if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(buffer, 1, length, binFile); if (result != length) { LOG_ERROR("Error parsing partitions from PDI file"); } if (dumpType == DumpOption::PARTITIONS) { if (bH && bH->sourceOffset == offset) { length = bH->totalPlmLength; } if((part_sec_count > 1) && ((*pHT)->dataSectionCount == 0)) { part_sec_index++; } DumpPartitions(buffer, length, (*iH)->imageName, part_index, part_sec_index); } else { /* Bootloader - compare address offset from BH and PHT */ if (bH && bH->sourceOffset == offset) { length = bH->totalPlmLength; } if ((dumpType == DumpOption::PLM) || (dumpType == DumpOption::BOOT_FILES)) { DumpPartitions(buffer, length, "plm", part_index, part_sec_index); if (dumpType == DumpOption::PLM) { delete[] buffer; fclose(binFile); return; } } } /* For extracting PMC DATA, Bootloader - compare address offset from BH and PHT */ if (bH && bH->sourceOffset == offset) { if (bH && bH->totalPmcCdoLength != 0) { if ((dumpType == DumpOption::PARTITIONS) || (dumpType == DumpOption::PMC_CDO) || (dumpType == DumpOption::BOOT_FILES)) { DumpPartitions(buffer + bH->plmLength, bH->totalPmcCdoLength, "pmc_cdo"); if ((dumpType == DumpOption::PMC_CDO) || (dumpType == DumpOption::BOOT_FILES)) { // if dump boot files, the return from here delete[] buffer; fclose(binFile); return; } } } if (bH && bH->totalPmcCdoLength == 0 && dumpType == DumpOption::PMC_CDO) { LOG_ERROR("PMC_CDO partition is not available in the PDI"); } } } else { LOG_ERROR("Error parsing Partition Headers from bin file"); } pHT++; delete[] buffer; } } fclose(binFile); } /******************************************************************************/ void VersalReadImage::ReadHeaderTableDetails() { size_t result; uint64_t offset = 0; uint32_t index = 0; bool smap_header_found = false; FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { //fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } // Boot Header Table Extraction bH = new VersalBootHeaderStructure; result = fread(bH, 1, sizeof(VersalBootHeaderStructure), binFile); if ((bH->smapWords[0] == 0xDD000000) || (bH->smapWords[0] == 0x00DD0000) || (bH->smapWords[0] == 0x000000DD)) { smap_header_found = true; } if (bH->widthDetectionWord != 0xAA995566) { delete bH; bH = NULL; } if ((dumpType == DumpOption::BH) || (dumpType == DumpOption::BOOT_FILES)) { if (bH == NULL) { LOG_ERROR("Boot Header not found"); } FILE* filePtr; std::string fName = binFilename; if (dumpPath != "") { fName = dumpPath + "/" + StringUtils::BaseName(binFilename); } fName = StringUtils::RemoveExtension(fName); fName += "_bh.bin"; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { /* First 16 bytes are not required by BootRoM/PLM, they should not be part of BH */ result = fwrite(&bH->widthDetectionWord, 1, size_t(sizeof(VersalBootHeaderStructure) - 16), filePtr); if (result != sizeof(VersalBootHeaderStructure) - 16) { LOG_ERROR("Error dumping Boot Header to a file"); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } } if (bH) { offset = bH->imageHeaderByteOffset; } else { if(smap_header_found) { offset = sizeof(VersalSmapWidthTable); } else { offset = 0; } } if (!(fseek(binFile, offset, SEEK_SET))) { iHT = new VersalImageHeaderTableStructure; result = fread(iHT, 1, sizeof(VersalImageHeaderTableStructure), binFile); if ((iHT->version != VERSION_v1_00_VERSAL) && (iHT->version != VERSION_v2_00_VERSAL) && (iHT->version != VERSION_v3_00_VERSAL) && (iHT->version != VERSION_v4_00_VERSAL)) { LOG_ERROR("Improper version (0x%.8x) read from Image Header Table of the PDI file.",iHT->version); } if (result != sizeof(VersalImageHeaderTableStructure)) { LOG_ERROR("Error parsing Image Header Table from PDI file"); } if (!((iHT->partitionTotalCount > 0) && (iHT->partitionTotalCount < 0xFF))) { LOG_ERROR("Number of partitions read from PDI is more than number of supported partititon count."); } } else { LOG_ERROR("Error parsing Image Header Table from PDI file"); } uint8_t* header_ac = NULL; if (iHT && iHT->headerAuthCertificateWordOffset != 0) { header_ac = new uint8_t[sizeof(AuthCertificateECDSAStructure)]; if (!(fseek(binFile, iHT->headerAuthCertificateWordOffset * 4, SEEK_SET))) { result = fread(header_ac, 1, sizeof(AuthCertificateECDSAStructure), binFile); if (result != sizeof(AuthCertificateECDSAStructure)) { LOG_ERROR("Error parsing Header Authentication Certificate from PDI file"); } } } aCs.push_back(header_ac); if (iHT->metaHdrKeySource == KeySource::None) { offset = iHT->firstImageHeaderWordOffset * 4; for (index = 0; index < iHT->imageTotalCount; index++) { iH = new VersalImageHeaderStructure; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(iH, 1, sizeof(VersalImageHeaderStructure), binFile); if (result != sizeof(VersalImageHeaderStructure)) { LOG_ERROR("Error parsing Image Headers from PDI file"); } iHs.push_back(iH); offset += sizeof(VersalImageHeaderStructure); } else { LOG_ERROR("Error parsing Image Headers from PDI file"); } } offset = (iHT->firstImageHeaderWordOffset * 4) + (sizeof(VersalImageHeaderStructure) * iHT->imageTotalCount); for (index = 0; index < iHT->partitionTotalCount; index++) { pHT = new VersalPartitionHeaderTableStructure; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(pHT, 1, sizeof(VersalPartitionHeaderTableStructure), binFile); if (result != sizeof(VersalPartitionHeaderTableStructure)) { LOG_ERROR("Error parsing Partition Headers from PDI file"); } pHTs.push_back(pHT); offset += sizeof(VersalPartitionHeaderTableStructure); } else { LOG_ERROR("Error parsing Partition Headers from PDI file"); } } for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++) { uint8_t* aC = NULL; offset = (*partitionHdr)->authCertificateOffset * 4; if (offset != 0) { aC = new uint8_t[sizeof(AuthCertificateECDSAStructure)]; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(aC, 1, sizeof(AuthCertificateECDSAStructure), binFile); if (result != sizeof(AuthCertificateECDSAStructure)) { LOG_ERROR("Error parsing Authentication Certificates from PDI file"); } } } aCs.push_back(aC); } } fclose(binFile); return; } /******************************************************************************/ void VersalReadImage::ReadBinaryFile(DumpOption::Type dump, std::string path) { if (StringUtils::GetExtension(binFilename) == ".mcs") { LOG_ERROR("The option '-read/-dump' is not supported on mcs format file : %s", binFilename.c_str()); } dumpType = dump; dumpPath = path; ReadHeaderTableDetails(); if (dumpType == DumpOption::PARTITIONS) { DisplayImageInfo(); } if (readType != ReadImageOption::NONE) { DisplayImageInfo(); DisplayHeaderTableDetails(readType); } ReadPartitions(); } /******************************************************************************/ uint32_t VersalReadImage::GetPdiId(void) { return iHT->pdiId; } /******************************************************************************/ uint32_t VersalReadImage::GetParentId(void) { return iHT->parentId; } /******************************************************************************/ uint8_t VersalReadImage::GetCreatorId(void) { return ((iHT->imageHeaderTableAttributes) >> 1) & 0xF; } /******************************************************************************/ void VersalReadImage::DisplayHeaderTableDetails(ReadImageOption::Type type) { switch (type) { case ReadImageOption::BH: DisplayBootHeader(); break; case ReadImageOption::IHT: DisplayImageHeaderTable(); DisplayOptionalData(); break; case ReadImageOption::IH: if (iHT->metaHdrKeySource != KeySource::None) { LOG_ERROR("Cannot read IH from an encrypted PDI."); } DisplayImageHeaders(); break; case ReadImageOption::PHT: if (iHT->metaHdrKeySource != KeySource::None) { LOG_ERROR("Cannot read PHT from an encrypted PDI."); } DisplayPartitionHeaderTable(); break; case ReadImageOption::AC: DisplayAuthenicationCertificates(); break; default: DisplayBootHeader(); DisplayImageHeaderTable(); DisplayOptionalData(); if (iHT->metaHdrKeySource == KeySource::None) { DisplayImageHeaders(); DisplayPartitionHeaderTable(); DisplayAuthenicationCertificates(); } else { Separator(); LOG_MSG("\n[INFO] : Cannot read further from an encrypted PDI."); } break; } Separator(); } /******************************************************************************/ void VersalReadImage::DisplayImageDetails(ReadImageOption::Type type, DumpOption::Type dump, std::string dump_dir) { readType = type; ReadBinaryFile(dump, dump_dir); if (dump != DumpOption::NONE) { if (iHT->metaHdrKeySource != KeySource::None) { switch (dump) { case DumpOption::BH: break; case DumpOption::PLM: LOG_ERROR("Cannot dump PLM from an encrypted PDI."); break; case DumpOption::PMC_CDO: LOG_ERROR("Cannot dump PMC_CDO from an encrypted PDI."); break; case DumpOption::PARTITIONS: LOG_ERROR("Cannot dump partitions from an encrypted PDI."); break; case DumpOption::BOOT_FILES: LOG_MSG("\n[INFO] : Cannot dump PLM/ PMC_CDO/ partitions from an encrypted PDI."); break; default: break; } } return; } } /******************************************************************************/ void VersalReadImage::DisplayBootHeader(void) { Separator(); if (bH == NULL) { std::cout << " NO BOOT HEADER" << std::endl; return; } std::cout << " BOOT HEADER" << std::endl; Separator(); /* SMAP Vectors are not part of Boot Header - So don't display */ //DisplaySmapVectors(); DisplayValue("width_detection (0x10) : ", bH->widthDetectionWord); DisplayValue("image_id (0x14) : ", bH->identificationWord); DisplayValue("encryption_keystore (0x18) : ", bH->encryptionKeySource); DisplayValue("plm_offset (0x1c) : ", bH->sourceOffset); DisplayValue("pmccdo_load_addr (0x20) : ", bH->pmcCdoLoadAddress); DisplayValue("pmccdo_length (0x24) : ", bH->pmcCdoLength); DisplayValue("pmccdo_total_length (0x28) : ", bH->totalPmcCdoLength); DisplayValue("plm_length (0x2c) : ", bH->plmLength); DisplayValue("plm_total_length (0x30) : ", bH->totalPlmLength); DisplayValue("attributes (0x34) : ", bH->bhAttributes); DisplayKey("grey/black_key (0x38) : ", bH->greyOrBlackKey); DisplayIV("grey/black_iv (0x58) : ", bH->greyOrBlackIV); DisplayIV("plm_sec_hdr_iv (0x64) : ", bH->plmSecureHdrIv); DisplayValue("puf_shutter (0x70) : ", bH->shutterValue); DisplayIV("pmccdo_sec_hdr_iv (0x74) : ", bH->pmcCdoSecureHdrIv); if (versalNetSeries) { DisplayValue("puf_ro_swap (0x80) : ", bH->pufRoSwapConfigVal); DisplayValue("revoke_id (0x84) : ", bH->revokeId); } DisplayValue("metahdr_offset (0xc4) : ", bH->imageHeaderByteOffset); DisplayKey("puf_data (0x928) : ", bH->puf); DisplayValue("checksum (0xf30) : ", bH->headerChecksum); std::cout << " attribute list - " << std::endl; DisplayBhAttributes(bH->bhAttributes); } /******************************************************************************/ void VersalReadImage::DumpPartitions(uint8_t* buffer, uint32_t length, std::string name, uint32_t id, uint32_t index) { FILE* filePtr; size_t result; std::string extension = ".bin"; std::string fName = StringUtils::FolderPath(binFilename); if (dumpPath != "") { fName = dumpPath; } fName = fName + "/" + name; if (dumpType == DumpOption::PARTITIONS) { fName += StringUtils::Format(".%x", id); fName += StringUtils::Format(".%x", index); } fName += extension; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { result = fwrite(buffer, 1, length, filePtr); if (result != length) { LOG_ERROR("Error dumping partition %s to a file", name.c_str()); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } return; } /******************************************************************************/ void VersalReadImage::DisplayImageHeaderTable(void) { #define ID_STRING(opt) (opt == FPDI) ? "FPDI" : "PPDI" Separator(); std::cout << " IMAGE HEADER TABLE" << std::endl; Separator(); DisplayValue("version (0x00) : ", iHT->version, "total_images (0x04) : ", iHT->imageTotalCount); DisplayValue("ih_offset (0x08) : ", iHT->firstImageHeaderWordOffset, "total_partitions (0x0c) : ", iHT->partitionTotalCount); DisplayValue("pht_offset (0x10) : ", iHT->firstPartitionHeaderWordOffset, "sec_boot_dev_addr (0x14) : ", iHT->secondaryBootDeviceAddress); DisplayValue("id_code (0x18) : ", iHT->idCode, "attributes (0x1c) : ", iHT->imageHeaderTableAttributes); DisplayValue("pdi_id (0x20) : ", iHT->pdiId, "parent_id (0x24) : ", iHT->parentId); DisplayAscii("id_string (0x28) : ", ID_STRING(iHT->identificationString)); DisplayValue("hdr_sizes (0x2C) : ", iHT->headerSizes, "mhdr_total_length (0x30) : ", iHT->totalMetaHdrLength); DisplayIV("mhdr_sec_hdr_iv (0x34) : ", iHT->metaHdrSecureHdrIv); DisplayValue("mhdr_encrkey_store (0x40) : ", iHT->metaHdrKeySource, "extended_id_code (0x44) : ", iHT->extendedIdCode); DisplayValue("hdr_ac (0x48) : ", iHT->headerAuthCertificateWordOffset); DisplayIV("grey/black_iv (0x4C) : ", iHT->metaHdrGreyOrBlackIV); DisplayValue("optional_data_size (0x58) : ", iHT->optionalDataSize, "checksum(0x7c) : ", iHT->ihtChecksum); std::cout << " attribute list - " << std::endl; DisplayIhtAttributes(iHT->imageHeaderTableAttributes); } /******************************************************************************/ void VersalReadImage::DisplayImageHeaders(void) { #define OWNER(opt) (((opt >> 3) & 7) ? "[plm]" : "[non-plm]") int index = 0; for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { index++; Separator(); std::cout << " IMAGE HEADER " << "(" << (*iH)->imageName << ")" << std::endl; Separator(); DisplayValue("pht_offset (0x00) : ", (*iH)->partitionHeaderWordOffset, "section_count (0x04) : ", (*iH)->dataSectionCount); DisplayValue("mHdr_revoke_id (0x08) : ", (*iH)->metaHdrRevokeId, "attributes (0x0c) : ", ((*iH)->imageAttributes)); DisplayAscii("name (0x10) : ", (*iH)->imageName); DisplayValue("id (0x18) : ", (*iH)->imageId, "unique_id (0x24) : ", (*iH)->uniqueId); DisplayValue("parent_unique_id (0x28) : ", (*iH)->parentUniqueId, "function_id (0x2c) : ", (*iH)->functionId); DisplayValue("memcpy_address_lo (0x30) : ", (*iH)->memcpyAddressLo, "memcpy_address_hi (0x34) : ", (*iH)->memcpyAddressHi); if (versalNetSeries) { DisplayValue("pcr_value (0x38) : ", (*iH)->pcrNumber, "pcr_mindex (0x3A) : ", (*iH)->pcrMeasurementIndex); } DisplayValue("checksum (0x3c) : ", (*iH)->ihChecksum); std::cout << " attribute list -" << std::endl; DisplayIhAttributes((*iH)->imageAttributes); } } /******************************************************************************/ void VersalReadImage::DisplayPartitionHeaderTable(void) { uint32_t cnt_index = 0; std::list::iterator pHT = pHTs.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { uint32_t part_sec_index = 0; uint32_t part_sec_count = 0; uint32_t part_index = 0; for (cnt_index = 0; cnt_index < (*iH)->dataSectionCount; cnt_index++) { if ((*pHT)->dataSectionCount > 0) { part_sec_index = 0; part_sec_count = (*pHT)->dataSectionCount; } if (((*pHT)->dataSectionCount > 0) && (cnt_index != 0)) { part_index++; } if((part_sec_count > 1) && ((*pHT)->dataSectionCount == 0)) { part_sec_index++; } Separator(); std::cout << " PARTITION HEADER TABLE " << "(" << (*iH)->imageName << "." << std::hex << part_index << "." << std::hex << part_sec_index << ")" << std::endl; Separator(); DisplayValue("encrypted_length (0x00) : ", (*pHT)->encryptedPartitionLength, "unencrypted_length (0x04) : ", (*pHT)->unencryptedPartitionLength); DisplayValue("total_length (0x08) : ", (*pHT)->totalPartitionLength, "next_pht (0x0c) : ", (*pHT)->nextPartitionHeaderOffset); DisplayValue("exec_addr_lo (0x10) : ", (uint32_t)(*pHT)->destinationExecAddress, "exec_addr_hi (0x14) : ", (uint32_t)((*pHT)->destinationExecAddress >> 32)); DisplayValue("load_addr_lo (0x18) : ", (uint32_t)(*pHT)->destinationLoadAddress, "load_addr_hi (0x1c) : ", (uint32_t)((*pHT)->destinationLoadAddress >> 32)); DisplayValue("partition_offset (0x20) : ", (*pHT)->partitionWordOffset, "attributes (0x24) : ", (*pHT)->partitionAttributes); DisplayValue("section_count (0x28) : ", (*pHT)->dataSectionCount, "checksum_offset (0x2c) : ", (*pHT)->checksumWordOffset); DisplayValue("id (0x30) : ", (*pHT)->puid, "ac_offset (0x34) : ", (*pHT)->authCertificateOffset); DisplayIV("sec_hdr_iv (0x38) : ", (*pHT)->partitionSecureHdrIv); DisplayValue("encryption_keystore (0x44) : ", (*pHT)->partitionKeySource); DisplayIV("grey/black_iv (0x48) : ", (*pHT)->partitionGreyOrBlackIV); DisplayValue("revoke_id (0x54) : ", (*pHT)->partitionRevokeId, "checksum (0x7c) : ", (*pHT)->pHChecksum); std::cout << " attribute list -" << std::endl; DisplayPhtAttributes((*pHT)->partitionAttributes); pHT++; } } } /******************************************************************************/ void VersalReadImage::DisplayAuthenicationCertificates(void) { uint32_t cnt_index = 0; Authentication::Type auth_type = Authentication::None; std::list::iterator aC = aCs.begin(); /* Header AC */ if ((*aC) != NULL) { Separator(); std::cout << " AUTHENTICATION CERTIFICATE " << "(Meta Header)" << std::endl; Separator(); if ((*(*aC) & 0xF3) == 0x02) { auth_type = Authentication::ECDSA; } else if ((*(*aC) & 0xF3) == 0x11) { auth_type = Authentication::RSA; } else if ((*(*aC) & 0xF3) == 0x22) { auth_type = Authentication::ECDSAp521; } DisplayACFields(*aC, auth_type); } aC++; /* Partition AC */ for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { for (cnt_index = 0; cnt_index < (*iH)->dataSectionCount; cnt_index++) { if ((*aC) != NULL) { Separator(); std::cout << " AUTHENTICATION CERTIFICATE " << "(" << (*iH)->imageName << "." << std::dec << cnt_index << ")" << std::endl; Separator(); if ((*(*aC) & 0xF3) == 0x02) { auth_type = Authentication::ECDSA; } else if ((*(*aC) & 0xF3) == 0x11) { auth_type = Authentication::RSA; } else if ((*(*aC) & 0xF3) == 0x22) { auth_type = Authentication::ECDSAp521; } DisplayACFields(*aC, auth_type); } aC++; } } } /******************************************************************************/ void VersalReadImage::DisplayACFields(uint8_t* aC, Authentication::Type auth_type) { if (auth_type == Authentication::RSA) { AuthCertificate4096Sha3PaddingStructure* auth_cert = (AuthCertificate4096Sha3PaddingStructure*)(aC); DisplayValue("auth_header (0x00) : ", auth_cert->acHeader); DisplayValue("revoke_id (0x04) : ", auth_cert->spkId); DisplayLongValues("udf (0x08) : ", (uint8_t*)auth_cert->acUdf, 56); DisplayLongValues("ppk_mod (0x40) : ", (uint8_t*)auth_cert->acPpk.N, 512); DisplayLongValues("ppk_mod_ext (0x240) : ", (uint8_t*)auth_cert->acPpk.N_extension, 512); DisplayLongValues("ppk_exponent (0x440) : ", (uint8_t*)auth_cert->acPpk.E, 4); DisplayLongValues("ppk_padding (0x444) : ", (uint8_t*)auth_cert->ppkSHA3Padding, 12); DisplayLongValues("spk_mod (0x450) : ", (uint8_t*)auth_cert->acSpk.N, 512); DisplayLongValues("spk_mod_ext (0x650) : ", (uint8_t*)auth_cert->acSpk.N_extension, 512); DisplayLongValues("spk_exponent (0x850) : ", (uint8_t*)auth_cert->acSpk.E, 4); DisplayLongValues("spk_padding (0x854) : ", (uint8_t*)auth_cert->spkSHA3Padding, 4); DisplayLongValues("spk_signature (0x860) : ", (uint8_t*)(&auth_cert->acSpkSignature), 512); DisplayLongValues("bh_signature (0xa60) : ", (uint8_t*)(&auth_cert->acHeaderSignature), 512); DisplayLongValues("part_signature (0xc60) : ", (uint8_t*)(&auth_cert->acPartitionSignature), 512); } else if(auth_type == Authentication::ECDSA) { AuthCertificateECDSAStructure* auth_cert = (AuthCertificateECDSAStructure*)(aC); DisplayValue("auth_header (0x00) : ", auth_cert->acHeader); DisplayValue("revoke_id (0x04) : ", auth_cert->spkId); DisplayLongValues("udf (0x08) : ", (uint8_t*)auth_cert->acUdf, 56); DisplayLongValues("ppk_x (0x40) : ", (uint8_t*)auth_cert->acPpk.x, 48); DisplayLongValues("ppk_y (0x70) : ", (uint8_t*)auth_cert->acPpk.y, 48); DisplayLongValues("ppk_padding (0x444) : ", (uint8_t*)auth_cert->ppkSHA3Padding, 12); DisplayLongValues("spk_x (0x450) : ", (uint8_t*)auth_cert->acSpk.x, 48); DisplayLongValues("spk_y (0x480) : ", (uint8_t*)auth_cert->acSpk.y, 48); DisplayLongValues("spk_padding (0x854) : ", (uint8_t*)auth_cert->spkSHA3Padding, 4); DisplayLongValues("spk_signature (r) (0x860) : ", (uint8_t*)(&auth_cert->acSpkSignature), 48); DisplayLongValues("(s) (0x890) : ", ((uint8_t*)(&auth_cert->acSpkSignature) + 48), 48); DisplayLongValues("bh_signature (r) (0xa60) : ", (uint8_t*)(&auth_cert->acHeaderSignature), 48); DisplayLongValues("(s) (0xa90) : ", ((uint8_t*)(&auth_cert->acHeaderSignature) + 48), 48); DisplayLongValues("part_signature (r) (0xc60) : ", (uint8_t*)(&auth_cert->acPartitionSignature), 48); DisplayLongValues("(s) (0xc90) : ", ((uint8_t*)(&auth_cert->acPartitionSignature) + 48), 48); } else { AuthCertificateECDSAp521Structure* auth_cert = (AuthCertificateECDSAp521Structure*)(aC); DisplayValue("auth_header (0x00) : ", auth_cert->acHeader); DisplayValue("revoke_id (0x04) : ", auth_cert->spkId); DisplayLongValues("udf (0x08) : ", (uint8_t*)auth_cert->acUdf, 56); DisplayLongValues("ppk_x (0x40) : ", (uint8_t*)auth_cert->acPpk.x, 66); DisplayLongValues("ppk_y (0x70) : ", (uint8_t*)auth_cert->acPpk.y, 66); DisplayLongValues("ppk_padding (0x444) : ", (uint8_t*)auth_cert->ppkSHA3Padding, 12); DisplayLongValues("spk_x (0x450) : ", (uint8_t*)auth_cert->acSpk.x, 66); DisplayLongValues("spk_y (0x480) : ", (uint8_t*)auth_cert->acSpk.y, 66); DisplayLongValues("spk_padding (0x854) : ", (uint8_t*)auth_cert->spkSHA3Padding, 4); DisplayLongValues("spk_signature (r) (0x860) : ", (uint8_t*)(&auth_cert->acSpkSignature), 66); DisplayLongValues("(s) (0x890) : ", ((uint8_t*)(&auth_cert->acSpkSignature) + 66), 66); DisplayLongValues("bh_signature (r) (0xa60) : ", (uint8_t*)(&auth_cert->acHeaderSignature), 66); DisplayLongValues("(s) (0xa90) : ", ((uint8_t*)(&auth_cert->acHeaderSignature) + 66), 66); DisplayLongValues("part_signature (r) (0xc60) : ", (uint8_t*)(&auth_cert->acPartitionSignature), 66); DisplayLongValues("(s) (0xc90) : ", ((uint8_t*)(&auth_cert->acPartitionSignature) + 66), 66); } } /******************************************************************************/ void VersalReadImage::DisplaySmapVectors(void) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << "smap_words (0x00) : "; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << bH->smapWords[0] << std::setw(8) << std::hex << bH->smapWords[1] << std::setw(8) << std::hex << bH->smapWords[2] << std::setw(8) << std::hex << bH->smapWords[3] << std::endl; } /******************************************************************************/ void VersalReadImage::DisplayImageInfo() { Separator(); std::cout << " BOOTIMAGE COMPONENTS" << std::endl; Separator(); uint32_t cnt_index = 0; std::list::iterator pHT = pHTs.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { uint32_t part_sec_index = 0; uint32_t part_sec_count = 0; uint32_t part_index = 0; if ((dumpType == DumpOption::PARTITIONS) || readType != ReadImageOption::NONE) { LOG_MSG("+---Image: %s [id:0x%x]",(*iH)->imageName, (*iH)->imageId); } for (cnt_index = 0; cnt_index < (*iH)->dataSectionCount; cnt_index++) { std::string partitionType = GetPartitionType((*pHT)->partitionAttributes); std::string partitionCore = GetPartitionCore((*pHT)->partitionAttributes); if ((*pHT)->dataSectionCount > 0) { part_sec_index = 0; part_sec_count = (*pHT)->dataSectionCount; } if (((*pHT)->dataSectionCount > 0) && (cnt_index != 0)) { part_index++; } if((part_sec_count > 1) && ((*pHT)->dataSectionCount == 0)) { part_sec_index++; } std::string fName = (*iH)->imageName; fName += StringUtils::Format(".%x", part_index); fName += StringUtils::Format(".%x", part_sec_index); LOG_MSG(" |__ %s [core: %s, type: %s]",fName.c_str(), partitionCore.c_str(), partitionType.c_str()); pHT++; } LOG_MSG(""); } } /******************************************************************************/ void VersalReadImage::DisplayBhAttributes(uint32_t value) { std::string val, val1; switch ((value >> PUF_HD_BIT_SHIFT) & PUF_HD_BIT_MASK) { case 3: val = "[bh]"; break; default: val = "[efuse]"; break; } val1 = val; switch ((value >> BH_PUF_MODE_BIT_SHIFT) & BH_PUF_MODE_BIT_MASK) { case 0: val = "[puf-12k]"; break; case 3: val = "[puf-4k]"; break; default: val = "[invalid]"; break; } DisplayAttributes("puf_hd_source ", val1, "puf_mode ", val); switch ((value >> BI_HASH_BIT_SHIFT) & BI_HASH_BIT_MASK) { case 3: val = "[sha-3]"; break; default: val = "[none]"; break; } val1 = val; switch ((value >> DPA_CM_BIT_SHIFT) & DPA_CM_BIT_MASK) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } DisplayAttributes("integrity ", val1, "dpa_cm ", val); if (!versalNetSeries) { switch ((value >> BH_RSA_BIT_SHIFT) & BH_RSA_BIT_MASK) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } DisplayAttributes("bh_auth ", val, "", ""); } if (versalNetSeries) { switch ((value >> BH_RSA_SINGED_BIT_SHIFT) & BH_RSA_SINGED_BIT_MASK) { case 3: val = "[yes]"; break; default: val = "[no]"; break; } val1 = val; switch ((value >> BH_DICE_BIT_SHIFT) & BH_DICE_BIT_MASK) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } DisplayAttributes("rsa_signed ", val1, "dice ", val); } } /*********************************************************************************/ void VersalReadImage::DisplayIhtAttributes(uint32_t value) { std::string val, val1; switch ((value >> vihtSiliconRevisionIdCodeCheckShift) & vihtSiliconRevisionIdCodeCheckMask) { case 1: val = "[true]"; break; default: val = "[false]"; break; } val1 = val; switch ((value >> vihtImageCreatorIdShift) & vihtImageCreatorIdMask) { case 1: val = "[wdi]"; break; case 2: val = "[sdk]"; break; default: val = "[rsvd]"; break; } DisplayAttributes("silicon_rev_id_code_check ", val1, "image_creator ", val); switch ((value >> vihtSecBootDeviceShift) & vihtSecBootDeviceMask) { case 0: val = "[same-dev]"; break; case 1: val = "[qspi32]"; break; case 2: val = "[qspi24]"; break; case 3: val = "[nand]"; break; case 4: val = "[sd0]"; break; case 5: val = "[sd1]"; break; case 6: val = "[sd-ls]"; break; case 7: val = "[mmc]"; break; case 8: val = "[usb]"; break; case 9: val = "[ethernet]"; break; case 10: val = "[pcie]"; break; case 11: val = "[sata]"; break; case 12: val = "[ospi]"; break; case 13: val = "[smap]"; break; case 14: val = "[sbi]"; break; case 15: val = "[sd0-raw]"; break; case 16: val = "[sd1-raw]"; break; case 17: val = "[sd-ls-raw]"; break; case 18: val = "[mmc-raw]"; break; case 19: val = "[mmc0]"; break; case 20: val = "[mmc0-raw]"; break; case 21: val = "[imagestore]"; break; default: val = "[n/a]"; break; } val1 = val; switch ((value >> vihtDpacmEnableShift) & vihtDpacmEnableMask) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } DisplayAttributes("boot_device ", val1, "dpacm ", val); switch ((value >> vihtPufHDLocationShift) & vihtPufHDLocationMask) { case 3: val = "[bh]"; break; default: val = "[efuse]"; break; } val1 = val; DisplayAttributes("puf_hd_source", val1, "", ""); switch ((value >> vihtIdCodeCheckShift) & vihtIdCodeCheckMask) { case 3: val = "[true]"; break; default: val = "[false]"; break; } val1 = val; DisplayAttributes("skip_id_code_check", val1, "", ""); } /************************************************************************************************/ void VersalReadImage::DisplayIhAttributes(uint32_t value) { std::string val, val1, val2, val3; switch ((value >> vihImageOwnerShift) & vihImageOwnerMask) { case 0: val = "[plm]"; break; case 1: val = "[non-plm]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> vihCopyToMemoryShift) & vihCopyToMemoryMask) { case 1: val = "[yes]"; break; default: val = "[no]"; break; } DisplayAttributes("owner ", val1, "memcpy ", val); switch ((value >> vihDelayLoadShift) & vihDelayLoadMask) { case 1: val = "[delay]"; break; default: val = "[now]"; break; } val1 = val; switch ((value >> vihDelayHandoffShift) & vihDelayHandoffMask) { case 1: val = "[delay]"; break; default: val = "[now]"; break; } DisplayAttributes("load ", val1, "handoff ", val); std::string powerDomains = ""; switch ((value >> vihLowPowerDomainShift) & vihLowPowerDomainMask) { case 1: powerDomains += "[lpd]"; break; default: break; } switch ((value >> vihFullPowerDomainShift) & vihFullPowerDomainMask) { case 1: powerDomains += "[fpd]"; break; default: break; } switch ((value >> vihSystemPowerDomainShift) & vihSystemPowerDomainMask) { case 1: powerDomains += "[spd]"; break; default: break; } val1 = val; switch ((value >> vihPLPowerDomainShift) & vihPLPowerDomainMask) { case 1: powerDomains += "[pld]"; break; default: break; } if (powerDomains == "") powerDomains = "[none]"; DisplayAttributes("dependentPowerDomains ", powerDomains, " ", ""); } /************************************************************************************************/ void VersalReadImage::DisplayPhtAttributes(uint32_t value) { uint32_t core = (value >> vphtDestCpuShift) & vphtDestCpuMask; uint32_t arch = (value >> vphtExecStateShift) & vphtExecStateMask; uint32_t is_a72 = (core == 1 || core == 2); bool is_armv8 = (arch == 0 && is_a72 == 1); bool is_armv7 = ((arch == 1 && is_a72 == 1) || core == 5 || core == 6 || core == 7); bool is_elf = (((value >> vphtPartitionTypeShift) & vphtPartitionTypeMask) == 1); std::string val, val1, val2, val3; switch ((value >> vphtTrustzoneShift) & vphtTrustzoneMask) { case 0: val = "[non-secure]"; break; case 1: val = "[secure]"; break; } if (!is_armv8) { val = "[n/a]"; } val1 = val; switch ((value >> vphtExceptionLevelShift) & vphtExceptionLevelMask) { case 0: val = "[el-0]"; break; case 1: val = "[el-1]"; break; case 2: val = "[el-2]"; break; case 3: val = "[el-3]"; break; } if (!is_armv8) { val = "[n/a]"; } DisplayAttributes("trustzone ", val1, "el ", val); switch ((value >> vphtExecStateShift) & vphtExecStateMask) { case 0: val = "[aarch-64]"; break; case 1: val = "[aarch-32]"; break; } if (!is_armv8) { val = "[n/a]"; } val1 = val; switch ((value >> vphtDestCpuShift) & vphtDestCpuMask) { case 0: val = "[none]"; break; case 1: if (versalNetSeries) val = "[a78-0]"; else val = "[a72-0]"; break; case 2: if (versalNetSeries) val = "[a78-1]"; else val = "[a72-1]"; break; if (versalNetSeries) { case 3: val = "[a78-2]"; break; case 4: val = "[a78-3]"; break; } case 5: val = "[r5-0]"; break; case 6: val = "[r5-1]"; break; case 7: val = "[r5-lockstep]"; break; case 8: val = "[psm]"; break; case 9: val = "[aie]"; break; default: val = "[invalid]"; break; } if (!is_elf) { val = "[n/a]"; } DisplayAttributes("exec_state ", val1, "core ", val); if (versalNetSeries) { switch ((value >> vNetphtlockStepShift) & vNetphtlockStepMask) { case 0: val = "[disabled]"; break; case 3: val = "[enabled]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> vNetphtClusterShift) & vNetphtClusterMask) { case 0: val = "[0]"; break; case 1: val = "[1]"; break; case 2: val = "[2]"; break; case 3: val = "[3]"; break; default: val = "[invalid]"; break; } DisplayAttributes("lockstep ", val1, "cluster", val); switch ((value >> vNetphtTcmBootShift) & vNetphtTcmBootMask) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } val1 = val; DisplayAttributes("tcmboot ", val1, " ", ""); } switch ((value >> vphtChecksumTypeShift) & vphtChecksumTypeMask) { case 0: val = "[none]"; break; case 3: val = "[sha-3]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> vphtPufHDLocationShift) & vphtPufHDLocationMask) { case 0: val = "[efuse]"; break; case 3: val = "[bh]"; break; default: val = "[invalid]"; break; } DisplayAttributes("checksum ", val1, "puf_hd_source", val); switch ((value >> vphtPartitionOwnerShift) & vphtPartitionOwnerMask) { case 0: val = "[plm]"; break; case 1: val = "[non-plm]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> vphtEndiannessShift) & vphtEndiannessMask) { case 0: val = "[little-endian]"; break; case 1: val = "[big-endian]"; break; } if (!is_elf) { val = "[n/a]"; } DisplayAttributes("owner ", val1, "endianness ", val); switch ((value >> vphtHivecShift) & vphtHivecMask) { case 0: val = "[false]"; break; case 1: val = "[true]"; break; } if (!is_armv7) { val = "[n/a]"; } val1 = val; switch ((value >> vphtPartitionTypeShift) & vphtPartitionTypeMask) { case 0: val = "[none]"; break; case 1: val = "[elf]"; break; case 2: val = "[cdo]"; break; case 3: val = "[cfi]"; break; case 4: val = "[raw]"; break; case 5: val = "[raw-elf]"; break; case 6: val = "[cfi-gsc-mask]"; break; case 7: val = "[cfi-gsc-unmask]"; break; default: val = "[invalid]"; break; } DisplayAttributes("hi-vec ", val1, "partition_type", val); switch ((value >> vphtDpaCMShift) & vphtDpaCMMask) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } val1 = val; DisplayAttributes("dpacm ", val1, " ", ""); } /*******************************************************************************************************/ std::string VersalReadImage::GetPartitionCore(uint32_t value) { std::string val; bool is_elf = (((value >> vphtPartitionTypeShift) & vphtPartitionTypeMask) == 1); switch ((value >> vphtDestCpuShift) & vphtDestCpuMask) { case 0: val = "none"; break; case 1: if (versalNetSeries) val = "a78-0"; else val = "a72-0"; break; case 2: if (versalNetSeries) val = "a78-1"; else val = "a72-1"; break; if (versalNetSeries) { case 3: val = "a78-2"; break; case 4: val = "a78-3"; break; } case 5: val = "r5-0"; break; case 6: val = "r5-1"; break; case 7: val = "r5-lockstep"; break; case 8: val = "psm"; break; case 9: val = "aie"; break; default: val = "invalid"; break; } if (!is_elf) { val = "n/a"; } return val; } /*******************************************************************************************************/ std::string VersalReadImage::GetPartitionType(uint32_t value) { std::string val; switch ((value >> vphtPartitionTypeShift) & vphtPartitionTypeMask) { case 0: val = "none"; break; case 1: val = "elf"; break; case 2: val = "cdo"; break; case 3: val = "cfi"; break; case 4: val = "raw"; break; case 5: val = "raw-elf"; break; case 6: val = "cfi-gsc-mask"; break; case 7: val = "cfi-gsc-unmask"; break; default: val = "invalid"; break; } return val; } xilinx-bootgen-2024.2/readimage-versal.h000077500000000000000000000104021475706442400201470ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _READIMAGE_VERSAL_H_ #define _READIMAGE_VERSAL_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "readimage.h" #include "bootheader-versal.h" #include "imageheadertable-versal.h" #include "partitionheadertable-versal.h" #include "authentication-versal.h" /* Forward Class References */ class BootGenOptions; class BootHeader; class ImageHeaderTable; class BootImage; class Partition; class ImageHeader; class ByteFile; /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class VersalReadImage :public ReadImage { public: VersalReadImage(std::string filename) : ReadImage(filename) { binFilename = filename; bH = NULL; iHT = NULL; iHs.clear(); pHTs.clear(); partitionBuffers.clear(); aCs.clear(); authenticationVerified = true; versalNetSeries = false; } ~VersalReadImage(); void ReadBinaryFile(DumpOption::Type dump=DumpOption::NONE, std::string path=""); void ReadHeaderTableDetails(); void ReadPartitions(); void DisplayOptionalData(); void DisplayImageDetails(ReadImageOption::Type type, DumpOption::Type dump, std::string path=""); void DisplayHeaderTableDetails(ReadImageOption::Type type); void DisplayBootHeader(void); void DisplayImageHeaderTable(void); void DisplayImageHeaders(void); void DisplayPartitionHeaderTable(void); void DisplayAuthenicationCertificates(void); void DisplayACFields(uint8_t* rsa_ac, Authentication::Type auth_type); void DisplayBhAttributes(uint32_t value); void DisplayIhtAttributes(uint32_t value); void DisplayIhAttributes(uint32_t value); void DisplayPhtAttributes(uint32_t value); void DisplaySmapVectors(void); void VerifyAuthentication(bool); void VerifyHeaderTableSignature(); void VerifySPKSignature(uint8_t* aC); void VerifyPartitionSignature(void); bool VerifySignature(bool nist, uint8_t * data, size_t dataLength, ACKey4096Sha3Padding * acKey, uint8_t* signature); bool VerifyECDSASignature(bool nist, uint8_t * data, size_t dataLength, ACKeyECDSA *eckey, uint8_t* signature); bool VerifyECDSAP521Signature(bool nist, uint8_t * data, size_t dataLength, ACKeyECDSAP521 *eckey, uint8_t* signature); void Separator(void); void DumpPartitions(uint8_t* buffer, uint32_t length, std::string name, uint32_t id = 0, uint32_t index = 0); void DisplayImageInfo(); uint32_t GetPdiId(void); uint32_t GetParentId(void); uint8_t GetCreatorId(void); std::string GetPartitionType(uint32_t); std::string GetPartitionCore(uint32_t); protected: std::string binFilename; VersalBootHeaderStructure* bH; VersalImageHeaderTableStructure* iHT; VersalImageHeaderStructure *iH; VersalPartitionHeaderTableStructure *pHT; std::list iHs; std::list pHTs; std::list aCs; std::list partitionBuffers; bool authenticationVerified; }; #endif xilinx-bootgen-2024.2/readimage-zynq.cpp000077500000000000000000000502351475706442400202170ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "readimage-zynq.h" /*******************************************************************************/ ZynqReadImage::~ZynqReadImage() { if (bH != NULL) { delete[] bH; } if (iH != NULL) { delete[] iH; } if (iHT != NULL) { delete[] iHT; } if (pHT != NULL) { delete[] pHT; } } /**********************************************************************************************/ void ZynqReadImage::ReadPartitions() { size_t result; uint64_t offset = 0; FILE *binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } std::list::iterator partitionName = pHTNames.begin(); for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++, partitionName++) { uint32_t bufferLength = ((*partitionHdr)->encryptedPartitionLength * 4); uint8_t* tempBuffer = new uint8_t[bufferLength]; memset(tempBuffer, 0, bufferLength); offset = (*partitionHdr)->partitionWordOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, bufferLength, binFile); if (result != bufferLength) { LOG_ERROR("Error reading partition for hash calculation"); } if (bH && bH->sourceOffset == offset) { bufferLength = bH->totalFsblLength; } if (dumpType == DumpOption::BOOT_FILES) { DumpPartitions(tempBuffer, bufferLength, *partitionName); } if (dumpType == DumpOption::PARTITIONS) { DumpPartitions(tempBuffer, bufferLength, *partitionName); } } else { LOG_ERROR("Error parsing Partitions from BootImage file %s",binFilename.c_str()); } } fclose(binFile); } /*******************************************************************************/ void ZynqReadImage::ReadBinaryFile(DumpOption::Type dump, std::string path) { if (StringUtils::GetExtension(binFilename) == ".mcs") { LOG_ERROR("The option '-read/-dump' is not supported on mcs format file : %s", binFilename.c_str()); } ReadPartitions(); } /*******************************************************************************/ void ZynqReadImage::ReadHeaderTableDetails() { size_t result; uint64_t offset = 0; uint32_t index = 0; if (StringUtils::GetExtension(binFilename) == ".mcs") { LOG_ERROR("The option '-read' is not supported on mcs format file : %s", binFilename.c_str()); } FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { LOG_ERROR("Cannot read file %s", binFilename.c_str()); } /* Boot Header Extraction */ bH = new ZynqBootHeaderStructure; result = fread(bH, 1, sizeof(ZynqBootHeaderStructure), binFile); if (result != sizeof(ZynqBootHeaderStructure)) { LOG_ERROR("Error reading Boot header"); } if ((bH->widthDetectionWord != WIDTH_DETECTION) && (bH->identificationWord != HEADER_ID_WORD)) { LOG_ERROR("Boot Header not found in %s", binFilename.c_str()); } if ((dumpType == DumpOption::BH) || (dumpType == DumpOption::BOOT_FILES)) { FILE* filePtr; std::string fName = binFilename; if (dumpPath != "") { fName = dumpPath + "/" + StringUtils::BaseName(binFilename); } fName = StringUtils::RemoveExtension(fName); fName += "_bh.bin"; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { result = fwrite(bH, 1, size_t(sizeof(ZynqBootHeaderStructure)), filePtr); if (result != sizeof(ZynqBootHeaderStructure)) { LOG_ERROR("Error dumping Boot Header to a file"); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } } /* Image Header Table Extraction */ offset = bH->imageHeaderByteOffset; if (!(fseek(binFile, offset, SEEK_SET))) { iHT = new ZynqImageHeaderTableStructure; result = fread(iHT, 1, sizeof(ZynqImageHeaderTableStructure), binFile); if (result != sizeof(ZynqImageHeaderTableStructure)) { LOG_ERROR("Error reading Image header table"); } if ((iHT->version != VERSION_ZYNQ_ZYNQMP)) { LOG_ERROR("Improper version (0x%.8x) read from Image Header Table of the boot image file.", iHT->version); } if (!((iHT->partitionTotalCount > 0) && (iHT->partitionTotalCount < 0xFF))) { LOG_ERROR("Number of partitions read is more than number of supported partititon count."); } } else { LOG_ERROR("Error parsing Image Header Table from bin file"); } char buffer[4]; char name[256]; /* Image Header Extraction */ offset = 4 * (iHT->firstImageHeaderWordOffset); do { iH = new ZynqImageHeaderStructure; memset(iH, 0, sizeof(ZynqImageHeaderStructure)); if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(iH, 1, 4 * sizeof(uint32_t), binFile); if (result != (4 * sizeof(uint32_t))) { LOG_ERROR("Error reading Image header"); } uint32_t i = 0; do { result = fread(buffer, 1, 4, binFile); if (result != 4) { LOG_ERROR("Error reading Image header"); } name[i + 0] = buffer[3]; name[i + 1] = buffer[2]; name[i + 2] = buffer[1]; name[i + 3] = buffer[0]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } iHNames.push_back(name); iHs.push_back(iH); } else { LOG_ERROR("Error parsing Image Headers from bin file"); } offset = 4 * (iH->nextImageHeaderWordOffset); } while (offset != 0); /* Partition Header Extraction */ offset = 4 * (iHT->firstPartitionHeaderWordOffset); for (index = 0; index < iHT->partitionTotalCount; index++) { pHT = new ZynqPartitionHeaderTableStructure; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(pHT, 1, sizeof(ZynqPartitionHeaderTableStructure), binFile); if (result != sizeof(ZynqPartitionHeaderTableStructure)) { LOG_ERROR("Error reading Partition header table"); } pHTs.push_back(pHT); } else { LOG_ERROR("Error parsing Partition Headers from bin file"); } offset += sizeof(ZynqPartitionHeaderTableStructure); } /* Insert Partition Names from Image Header based on Section Count */ std::list::iterator iHName = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, iHName++) { for (uint32_t sectionIndex = 0; sectionIndex < (*iH)->imageNameLength; sectionIndex++) { std::stringstream ss; ss << sectionIndex; pHTNames.push_back(*iHName + "." + ss.str()); } } /* Authentication Certificates Extraction */ uint8_t* header_ac = NULL; if (iHT->headerAuthCertificateWordOffset != 0) { header_ac = new uint8_t[sizeof(AuthCertificate2048Structure)]; if (!(fseek(binFile, 4 * (iHT->headerAuthCertificateWordOffset), SEEK_SET))) { result = fread(header_ac, 1, sizeof(AuthCertificate2048Structure), binFile); if (result != sizeof(AuthCertificate2048Structure)) { LOG_ERROR("Error reading header authentication certificate"); } } } aCs.push_back(header_ac); for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++) { uint8_t* aC = NULL; offset = (*partitionHdr)->authCertificateOffset * 4; if (offset != 0) { aC = new uint8_t[sizeof(AuthCertificate2048Structure)]; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(aC, 1, sizeof(AuthCertificate2048Structure), binFile); if (result != sizeof(AuthCertificate2048Structure)) { LOG_ERROR("Error reading partition authentication certificate"); } } } aCs.push_back(aC); } if (header_ac != NULL) { delete[] header_ac; } fclose(binFile); } /******************************************************************************/ void ZynqReadImage::DumpPartitions(uint8_t* buffer, uint32_t length, std::string name) { FILE* filePtr; size_t result; std::string extension = ".bin"; std::string fName = StringUtils::FolderPath(binFilename); if (dumpPath != "") { fName = dumpPath; } fName = fName + "/" + name; fName += extension; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { result = fwrite(buffer, 1, length, filePtr); if (result != length) { LOG_ERROR("Error dumping partition %s to a file", fName.c_str()); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } return; } /*******************************************************************************/ void ZynqReadImage::DisplayBootHeader(void) { Separator(); std::cout << " BOOT HEADER" << std::endl; Separator(); DisplayBootVectors(); DisplayValue("width_detection (0x20) : ", bH->widthDetectionWord); DisplayValue("image_id (0x24) : ", bH->identificationWord); DisplayValue("encryption_keystore (0x28) : ", bH->encryptionKeySource); DisplayValue("header_version (0x2c) : ", bH->headerVersion); DisplayValue("fsbl_sourceoffset (0x30) : ", bH->sourceOffset); DisplayValue("fsbl_length (0x34) : ", bH->fsblLength); DisplayValue("fsbl_load_address (0x38) : ", bH->fsblLoadAddress); DisplayValue("fsbl_exec_address (0x3C) : ", bH->fsblExecAddress); DisplayValue("fsbl_total_length (0x40) : ", bH->totalFsblLength); DisplayValue("qspi_config-word (0x44) : ", bH->qspiConfigWord); DisplayValue("checksum (0x48) : ", bH->headerChecksum); //DisplayValue("user_defined_feilds (0x4C) : ", bH->udf); DisplayValue("iht_offset (0x98) : ", bH->imageHeaderByteOffset); DisplayValue("pht_offset (0x9c) : ", bH->partitionHeaderByteOffset); } /*******************************************************************************/ void ZynqReadImage::DisplayImageHeaderTable(void) { Separator(); std::cout << " IMAGE HEADER TABLE" << std::endl; Separator(); DisplayValue("version (0x00) : ", iHT->version, "total_images (0x04) : ", iHT->partitionTotalCount); DisplayValue("pht_offset (0x08) : ", 4 * (iHT->firstPartitionHeaderWordOffset), "ih_offset (0x0c) : ", 4 * (iHT->firstImageHeaderWordOffset)); DisplayValue("hdr_ac_offset (0x10) : ", 4 * (iHT->headerAuthCertificateWordOffset)); } /*******************************************************************************/ void ZynqReadImage::DisplayImageHeaders(void) { uint32_t index = 0; std::list::iterator name = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, name++) { index++; Separator(); std::cout << " IMAGE HEADER " << "(" << *name << ")" << std::endl; Separator(); DisplayValue("next_ih(W) (0x00) : ", (*iH)->nextImageHeaderWordOffset); DisplayValue("next_pht(W) (0x04) : ", (*iH)->partitionHeaderWordOffset); DisplayValue("total_partitions (0x0c) : ", (*iH)->imageNameLength); DisplayAscii("name (0x10) : ", *name); } } /*******************************************************************************/ void ZynqReadImage::DisplayPartitionHeaderTable(void) { uint32_t cnt_index = 0; std::list::iterator pHT = pHTs.begin(); std::list::iterator name = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, name++) { for (cnt_index = 0; cnt_index < (*iH)->imageNameLength; cnt_index++) { Separator(); std::cout << " PARTITION HEADER TABLE " << "(" << *name << "." << std::dec << cnt_index << ")" << std::endl; Separator(); DisplayValue("encrypted_length (0x00) : ", (*pHT)->encryptedPartitionLength, "unencrypted_length (0x04) : ", (*pHT)->unencryptedPartitionLength); DisplayValue("total_length (0x08) : ", (*pHT)->totalPartitionLength, "load_addr (0x0c) : ", (*pHT)->destinationLoadAddress); DisplayValue("exec_addr (0x10) : ", (uint32_t)(*pHT)->destinationExecAddress, "partition_offset (0x14) : ", (*pHT)->partitionWordOffset); DisplayValue("attributes (0x18) : ", (*pHT)->partitionAttributes, "section_count (0x1C) : ", (*pHT)->dataSectionCount); DisplayValue("checksum_offset (0x20) : ", (*pHT)->checksumWordOffset, "iht_offset (0x24) : ", (*pHT)->imageHeaderWordOffset); DisplayValue("ac_offset (0x28) : ", (*pHT)->authCertificateOffset, "checksum (0x3c) : ", (*pHT)->pHChecksum); std::cout << " attribute list -" << std::endl; DisplayPhtAttributes((*pHT)->partitionAttributes); pHT++; } } } /*******************************************************************************/ void ZynqReadImage::DisplayAuthenicationCertificates(void) { uint32_t cnt_index = 0; Authentication::Type auth_type; std::list::iterator aC = aCs.begin(); /* Header AC */ if ((*aC) != NULL) { Separator(); std::cout << " AUTHENTICATION CERTIFICATE " << "(Headers)" << std::endl; Separator(); auth_type = (Authentication::Type) (*(*aC) & 3); DisplayACFields(*aC, auth_type); } aC++; /* Partition ACs */ std::list::iterator name = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, name++) { for (cnt_index = 0; cnt_index < (*iH)->imageNameLength; cnt_index++) { if ((*aC) != NULL) { Separator(); std::cout << " AUTHENTICATION CERTIFICATE " << "(" << *name << "." << std::dec << cnt_index << ")" << std::endl; Separator(); auth_type = (Authentication::Type) (*(*aC) & 3); DisplayACFields(*aC, auth_type); } aC++; } } } /*******************************************************************************/ void ZynqReadImage::DisplayACFields(uint8_t* aC, Authentication::Type auth_type) { if (auth_type == Authentication::RSA) { AuthCertificate2048Structure* auth_cert = (AuthCertificate2048Structure*)(aC); DisplayValue("auth_header (0x00) : ", auth_cert->acHeader); DisplayValue("ac_size (0x04) : ", auth_cert->acSize); DisplayLongValues("udf (0x08) : ", (uint8_t*)auth_cert->acUdf, UDF_DATA_SIZE); DisplayLongValues("ppk_mod (0x40) : ", (uint8_t*)auth_cert->acPpk.N, RSA_2048_KEY_LENGTH); DisplayLongValues("ppk_mod_ext (0x140) : ", (uint8_t*)auth_cert->acPpk.N_extension, RSA_2048_KEY_LENGTH); DisplayLongValues("ppk_exponent (0x240) : ", (uint8_t*)auth_cert->acPpk.E, 4); DisplayLongValues("ppk_padding (0x244) : ", (uint8_t*)auth_cert->acPpk.Padding, 60); DisplayLongValues("spk_mod (0x280) : ", (uint8_t*)auth_cert->acSpk.N, RSA_2048_KEY_LENGTH); DisplayLongValues("spk_mod_ext (0x380) : ", (uint8_t*)auth_cert->acSpk.N_extension, RSA_2048_KEY_LENGTH); DisplayLongValues("spk_exponent (0x480) : ", (uint8_t*)auth_cert->acSpk.E, 4); DisplayLongValues("spk_padding (0x484) : ", (uint8_t*)auth_cert->acSpk.Padding, 60); DisplayLongValues("spk_signature (0x4c0) : ", (uint8_t*)(&auth_cert->acSpkSignature), RSA_SIGN_LENGTH_ZYNQ); DisplayLongValues("part_signature (0x5c0) : ", (uint8_t*)(&auth_cert->acPartitionSignature), RSA_SIGN_LENGTH_ZYNQ); } } /*******************************************************************************/ void ZynqReadImage::DisplayBootVectors(void) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << "boot_vectors (0x00) : "; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << bH->bootVectors[0] << std::setw(8) << std::hex << bH->bootVectors[1] << std::setw(8) << std::hex << bH->bootVectors[2] << std::setw(8) << std::hex << bH->bootVectors[3] << bH->bootVectors[4] << std::setw(8) << std::hex << bH->bootVectors[5] << std::setw(8) << std::hex << bH->bootVectors[6] << std::setw(8) << std::hex << bH->bootVectors[7] << std::endl; } /*******************************************************************************/ void ZynqReadImage::DisplayPhtAttributes(uint32_t value) { std::string val, val1, val2, val3; switch ((value >> PH_TAIL_ALIGN_SHIFT) & PH_TAIL_ALIGN_MASK) { case 0: val = "[non-secure]"; break; case 1: val = "[secure]"; break; } val1 = val; switch ((value >> PH_HEAD_ALIGN_SHIFT) & PH_HEAD_ALIGN_MASK) { case 0: val = "[el-0]"; break; case 1: val = "[el-1]"; break; case 2: val = "[el-2]"; break; case 3: val = "[el-3]"; break; } DisplayAttributes("trustzone ", val1, "el ", val); switch ((value >> PH_DEST_DEVICE_SHIFT) & PH_DEST_DEVICE_MASK) { case 0: val = "[aarch-64]"; break; case 1: val = "[aarch-32]"; break; } val1 = val; switch ((value >> PH_CHECKSUM_SHIFT) & PH_CHECKSUM_MASK) { case 0: val = "[none]"; break; case 1: val = "[PS]"; break; case 2: val = "[PL]"; break; default: val = "[invalid]"; break; } DisplayAttributes("exec_state ", val1, "dest_device ", val); switch ((value >> PH_AC_FLAG_SHIFT) & PH_AC_FLAG_MASK) { case 0: val = "[no]"; break; case 1: val = "[yes]"; break; } val1 = val; switch ((value >> PH_OWNER_SHIFT) & PH_OWNER_MASK) { case 0: val = "[none]"; break; case 1: val = "[a53-0]"; break; case 2: val = "[a53-1]"; break; case 3: val = "[a53-2]"; break; case 4: val = "[a53-3]"; break; case 5: val = "[r5-0]"; break; case 6: val = "[r5-1]"; break; case 7: val = "[r5-lockstep]"; break; case 8: val = "[pmu]"; break; default: val = "[invalid]"; break; } DisplayAttributes("encryption ", val1, "core ", val); }xilinx-bootgen-2024.2/readimage-zynq.h000077500000000000000000000053221475706442400176610ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _READIMAGE_ZYNQ_H_ #define _READIMAGE_ZYNQ_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "readimage.h" #include "bootheader-zynq.h" #include "imageheadertable-zynq.h" #include "partitionheadertable-zynq.h" #include "authentication-zynq.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqReadImage : public ReadImage { public: ZynqReadImage(std::string filename) : ReadImage(filename) { bH = NULL; iHT = NULL; iH = NULL; pHT = NULL; iHs.clear(); pHTs.clear(); } ~ZynqReadImage(); void ReadBinaryFile(DumpOption::Type dump = DumpOption::NONE, std::string path = ""); void ReadHeaderTableDetails(); void ReadPartitions(); void DisplayBootHeader(void); void DisplayImageHeaderTable(void); void DisplayImageHeaders(void); void DisplayPartitionHeaderTable(void); void DisplayAuthenicationCertificates(void); void DisplayACFields(uint8_t* rsa_ac, Authentication::Type auth_type); void DisplayBhAttributes(uint32_t value); void DisplayPhtAttributes(uint32_t value); void DisplayBootVectors(void); void DumpPartitions(uint8_t* buffer, uint32_t length, std::string name); protected: ZynqBootHeaderStructure* bH; ZynqImageHeaderTableStructure* iHT; ZynqImageHeaderStructure* iH; ZynqPartitionHeaderTableStructure* pHT; std::list iHs; std::list pHTs; }; #endif xilinx-bootgen-2024.2/readimage-zynqmp.cpp000077500000000000000000000617701475706442400205620ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "readimage-zynqmp.h" #define BITSTREAM_AUTH_CHUNK_SIZE 0x800000 //8MB = 8*1024*1024 /*******************************************************************************/ ZynqMpReadImage::~ZynqMpReadImage() { if (bH != NULL) { delete[] bH; } if (iH != NULL) { delete[] iH; } if (iHT != NULL) { delete[] iHT; } if (pHT != NULL) { delete[] pHT; } } /**********************************************************************************************/ void ZynqMpReadImage::ReadPartitions() { size_t result; uint64_t offset = 0; FILE *binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } std::list::iterator partitionName = pHTNames.begin(); for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++, partitionName++) { uint32_t bufferLength = ((*partitionHdr)->encryptedPartitionLength * 4); uint8_t* tempBuffer = new uint8_t[bufferLength]; memset(tempBuffer, 0, bufferLength); offset = (*partitionHdr)->partitionWordOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, bufferLength, binFile); if (result != bufferLength) { LOG_ERROR("Error reading partition for hash calculation"); } if (bH && bH->sourceOffset == offset) { bufferLength = bH->totalFsblLength; } if (dumpType == DumpOption::BOOT_FILES) { DumpPartitions(tempBuffer, bufferLength, *partitionName); } if (dumpType == DumpOption::PARTITIONS) { DumpPartitions(tempBuffer, bufferLength, *partitionName); } } else { LOG_ERROR("Error parsing Partitions from BootImage file %s",binFilename.c_str()); } } fclose(binFile); } /*******************************************************************************/ void ZynqMpReadImage::ReadBinaryFile(DumpOption::Type dump, std::string path) { if (StringUtils::GetExtension(binFilename) == ".mcs") { LOG_ERROR("The option '-read/-dump' is not supported on mcs format file : %s", binFilename.c_str()); } ReadHeaderTableDetails(); ReadPartitions(); } /*******************************************************************************/ void ZynqMpReadImage::ReadHeaderTableDetails() { size_t result; uint64_t offset = 0; uint32_t index = 0; if (StringUtils::GetExtension(binFilename) == ".mcs") { LOG_ERROR("The option '-read' is not supported on mcs format file : %s", binFilename.c_str()); } FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); if (!binFile) { fclose(binFile); LOG_ERROR("Cannot read file %s", binFilename.c_str()); } /* Boot Header Extraction */ bH = new ZynqMpBootHeaderStructure; result = fread(bH, 1, sizeof(ZynqMpBootHeaderStructure), binFile); if (result != sizeof(ZynqMpBootHeaderStructure)) { LOG_ERROR("Error reading Boot header"); } if ((bH->widthDetectionWord != WIDTH_DETECTION) && (bH->identificationWord != HEADER_ID_WORD)) { LOG_ERROR("Boot Header not found in %s", binFilename.c_str()); } if ((dumpType == DumpOption::BH) || (dumpType == DumpOption::BOOT_FILES)) { FILE* filePtr; std::string fName = binFilename; if (dumpPath != "") { fName = dumpPath + "/" + StringUtils::BaseName(binFilename); } fName = StringUtils::RemoveExtension(fName); fName += "_bh.bin"; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { result = fwrite(bH, 1, size_t(sizeof(ZynqMpBootHeaderStructure)), filePtr); if (result != sizeof(ZynqMpBootHeaderStructure)) { LOG_ERROR("Error dumping Boot Header to a file"); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } } /* Image Header Table Extraction */ offset = bH->imageHeaderByteOffset; if (!(fseek(binFile, offset, SEEK_SET))) { iHT = new ZynqMpImageHeaderTableStructure; result = fread(iHT, 1, sizeof(ZynqMpImageHeaderTableStructure), binFile); if (result != sizeof(ZynqMpImageHeaderTableStructure)) { LOG_ERROR("Error reading Image header table"); } if ((iHT->version != VERSION_ZYNQ_ZYNQMP)) { LOG_ERROR("Improper version (0x%.8x) read from Image Header Table of the boot image file.", iHT->version); } if (!((iHT->partitionTotalCount > 0) && (iHT->partitionTotalCount < 0xFF))) { LOG_ERROR("Number of partitions read is more than number of supported partiiton count."); } } else { LOG_ERROR("Error parsing Image Header Table from bin file"); } char buffer[4]; char name[256]; /* Image Header Extraction */ offset = 4 * (iHT->firstImageHeaderWordOffset); do { iH = new ZynqMpImageHeaderStructure; memset(iH, 0, sizeof(ZynqMpImageHeaderStructure)); if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(iH, 1, 4 * sizeof(uint32_t), binFile); if (result != (4 * sizeof(uint32_t))) { LOG_ERROR("Error reading Image header"); } uint32_t i = 0; do { result = fread(buffer, 1, 4, binFile); if (result != 4) { LOG_ERROR("Error reading Image header"); } name[i + 0] = buffer[3]; name[i + 1] = buffer[2]; name[i + 2] = buffer[1]; name[i + 3] = buffer[0]; i += 4; } while (buffer[0] && buffer[1] && buffer[2] && buffer[3] && i= sizeof(name)) { LOG_DEBUG(DEBUG_STAMP, "Image header name too long"); LOG_ERROR("Failure parsing imported bootimage"); } iHNames.push_back(name); iHs.push_back(iH); } else { LOG_ERROR("Error parsing Image Headers from bin file"); } offset = 4 * (iH->nextImageHeaderWordOffset); } while (offset != 0); /* Partition Header Extraction */ offset = 4 * (iHT->firstPartitionHeaderWordOffset); for (index = 0; index < iHT->partitionTotalCount; index++) { pHT = new ZynqMpPartitionHeaderTableStructure; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(pHT, 1, sizeof(ZynqMpPartitionHeaderTableStructure), binFile); if (result != sizeof(ZynqMpPartitionHeaderTableStructure)) { LOG_ERROR("Error reading Partition header table"); } pHTs.push_back(pHT); } else { LOG_ERROR("Error parsing Partition Headers from bin file"); } offset += sizeof(ZynqMpPartitionHeaderTableStructure); } /* Insert Partition Names from Image Header based on Section Count */ std::list::iterator iHName = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, iHName++) { for (uint32_t sectionIndex = 0; sectionIndex < (*iH)->imageNameLength; sectionIndex++) { std::stringstream ss; ss << sectionIndex; pHTNames.push_back(*iHName + "." + ss.str()); } } /* Authentication Certificates Extraction */ uint8_t* header_ac = NULL; if (iHT->headerAuthCertificateWordOffset != 0) { header_ac = new uint8_t[sizeof(AuthCertificate4096Structure)]; if (!(fseek(binFile, 4 * (iHT->headerAuthCertificateWordOffset), SEEK_SET))) { result = fread(header_ac, 1, sizeof(AuthCertificate4096Structure), binFile); if (result != sizeof(AuthCertificate4096Structure)) { LOG_ERROR("Error reading header authentication certificate"); } } } aCs.push_back(header_ac); aCNames.push_back("Headers"); std::list::iterator pHTName = pHTNames.begin(); for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++, pHTName++) { uint8_t* aC = NULL; offset = (*partitionHdr)->authCertificateOffset * 4; if (offset != 0) { int acCount = 1; /* Check if the partition is a PL */ if (((((*partitionHdr)->partitionAttributes) >> PH_DEST_DEVICE_SHIFT_ZYNQMP) & PH_DEST_DEVICE_MASK_ZYNQMP) == 2) { acCount = ((*partitionHdr)->encryptedPartitionLength * 4) / BITSTREAM_AUTH_CHUNK_SIZE; if (((*partitionHdr)->encryptedPartitionLength * 4) % BITSTREAM_AUTH_CHUNK_SIZE != 0) { acCount += 1; } plAcCount = acCount; } for (int i = 0; i < acCount; i++) { aC = new uint8_t[sizeof(AuthCertificate4096Structure)]; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(aC, 1, sizeof(AuthCertificate4096Structure), binFile); if (result != sizeof(AuthCertificate4096Structure)) { LOG_ERROR("Error reading header authentication certificate"); } } offset += sizeof(AuthCertificate4096Structure); aCs.push_back(aC); aCNames.push_back(*pHTName); } } } fclose(binFile); } /******************************************************************************/ void ZynqMpReadImage::DumpPartitions(uint8_t* buffer, uint32_t length, std::string name) { FILE* filePtr; size_t result; std::string extension = ".bin"; std::string fName = StringUtils::FolderPath(binFilename); if (dumpPath != "") { fName = dumpPath; } fName = fName + "/" + name; fName += extension; filePtr = fopen(fName.c_str(), "wb"); if (filePtr != NULL) { result = fwrite(buffer, 1, length, filePtr); if (result != length) { LOG_ERROR("Error dumping partition %s to a file", fName.c_str()); } fclose(filePtr); LOG_INFO("%s generated successfully", StringUtils::BaseName(fName).c_str()); } return; } /*******************************************************************************/ void ZynqMpReadImage::DisplayBootHeader(void) { Separator(); std::cout << " BOOT HEADER" << std::endl; Separator(); DisplayBootVectors(); DisplayValue("width_detection (0x20) : ", bH->widthDetectionWord); DisplayValue("image_id (0x24) : ", bH->identificationWord); DisplayValue("encryption_keystore (0x28) : ", bH->encryptionKeySource); DisplayValue("fsbl_exec_address (0x2c) : ", bH->fsblExecAddress); DisplayValue("fsbl_sourceoffset (0x30) : ", bH->sourceOffset); DisplayValue("pmufw_length (0x34) : ", bH->pmuFwLength); DisplayValue("pmufw_total_length (0x38) : ", bH->totalPmuFwLength); DisplayValue("fsbl_length (0x3c) : ", bH->fsblLength); DisplayValue("fsbl_total_length (0x40) : ", bH->totalFsblLength); DisplayValue("attributes (0x44) : ", bH->fsblAttributes); DisplayValue("checksum (0x48) : ", bH->headerChecksum); DisplayKey("grey/black_key (0x4c) : ", bH->greyOrBlackKey); DisplayValue("puf_shutter (0x6c) : ", bH->shutterValue); //DisplayValue("user_defined_feilds (0x70) : ", bH->udf); DisplayValue("iht_offset (0x98) : ", bH->imageHeaderByteOffset); DisplayValue("pht_offset (0x9c) : ", bH->partitionHeaderByteOffset); DisplayIV("fsbl_sec_hdr_iv (0xa0) : ", bH->secureHdrIv); DisplayIV("grey/black_iv (0xac) : ", bH->greyOrBlackIV); std::cout << " attribute list - " << std::endl; DisplayBhAttributes(bH->fsblAttributes); } /*******************************************************************************/ void ZynqMpReadImage::DisplayImageHeaderTable(void) { #define BOOT_DEVICE(opt) (opt ? ((opt==7) ? "[pcie]" : "[invalid]") : "[same-dev]") Separator(); std::cout << " IMAGE HEADER TABLE" << std::endl; Separator(); DisplayValue("version (0x00) : ", iHT->version, "total_images (0x04) : ", iHT->partitionTotalCount); DisplayValue("pht_offset (0x08) : ", 4 * (iHT->firstPartitionHeaderWordOffset), "ih_offset (0x0c) : ", 4 * (iHT->firstImageHeaderWordOffset)); DisplayValue("hdr_ac_offset (0x10) : ", 4 * (iHT->headerAuthCertificateWordOffset), "boot_device (0x14) : ", BOOT_DEVICE(iHT->bootDevice)); DisplayValue("checksum (0x3c) : ", iHT->ihtChecksum); } /*******************************************************************************/ void ZynqMpReadImage::DisplayImageHeaders(void) { #define OWNER(opt) (((opt >> 3) & 7) ? "[efsbl]" : "[non-efsbl]") uint32_t index = 0; std::list::iterator name = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, name++) { index++; Separator(); std::cout << " IMAGE HEADER " << "(" << *name << ")" << std::endl; Separator(); DisplayValue("next_ih(W) (0x00) : ", (*iH)->nextImageHeaderWordOffset); DisplayValue("next_pht(W) (0x04) : ", (*iH)->partitionHeaderWordOffset); DisplayValue("total_partitions (0x0c) : ", (*iH)->imageNameLength); DisplayAscii("name (0x10) : ", *name); } } /*******************************************************************************/ void ZynqMpReadImage::DisplayPartitionHeaderTable(void) { uint32_t cnt_index = 0; std::list::iterator pHT = pHTs.begin(); std::list::iterator name = iHNames.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++, name++) { for (cnt_index = 0; cnt_index < (*iH)->imageNameLength; cnt_index++) { Separator(); std::cout << " PARTITION HEADER TABLE " << "(" << *name << "." << std::dec << cnt_index << ")" << std::endl; Separator(); DisplayValue("encrypted_length (0x00) : ", (*pHT)->encryptedPartitionLength, "unencrypted_length (0x04) : ", (*pHT)->unencryptedPartitionLength); DisplayValue("total_length (0x08) : ", (*pHT)->totalPartitionLength, "next_pht(W) (0x0c) : ", (*pHT)->nextPartitionHeaderOffset); DisplayValue("exec_addr_lo (0x10) : ", (uint32_t)(*pHT)->destinationExecAddress, "exec_addr_hi (0x14) : ", (uint32_t)((*pHT)->destinationExecAddress >> 32)); DisplayValue("load_addr_lo (0x18) : ", (uint32_t)(*pHT)->destinationLoadAddress, "load_addr_hi (0x1c) : ", (uint32_t)((*pHT)->destinationLoadAddress >> 32)); DisplayValue("partition_offset (0x20) : ", (*pHT)->partitionWordOffset, "attributes (0x24) : ", (*pHT)->partitionAttributes); DisplayValue("section_count (0x28) : ", (*pHT)->dataSectionCount, "checksum_offset (0x2c) : ", (*pHT)->checksumWordOffset); DisplayValue("iht_offset (0x30) : ", (*pHT)->imageHeaderWordOffset, "ac_offset (0x34) : ", (*pHT)->authCertificateOffset); DisplayValue("partition_num (0x38) : ", (*pHT)->partitionNumber, "checksum (0x3c) : ", (*pHT)->pHChecksum); std::cout << " attribute list -" << std::endl; DisplayPhtAttributes((*pHT)->partitionAttributes); pHT++; } } } /*******************************************************************************/ void ZynqMpReadImage::DisplayAuthenicationCertificates(void) { Authentication::Type auth_type; std::list::iterator aCName = aCNames.begin(); for (std::list::iterator aC = aCs.begin(); aC != aCs.end(); aC++, aCName++) { if ((*aC) != NULL) { Separator(); std::cout << " AUTHENTICATION CERTIFICATE " << "(" << *aCName << ")" << std::endl; Separator(); auth_type = (Authentication::Type) (*(*aC) & 3); DisplayACFields(*aC, auth_type); } } } /*******************************************************************************/ void ZynqMpReadImage::DisplayACFields(uint8_t* aC, Authentication::Type auth_type) { if (auth_type == Authentication::RSA) { AuthCertificate4096Structure* auth_cert = (AuthCertificate4096Structure*)(aC); DisplayValue("auth_header (0x00) : ", auth_cert->acHeader); DisplayValue("spk_id (0x04) : ", auth_cert->spkId); DisplayLongValues("udf (0x08) : ", (uint8_t*)auth_cert->acUdf, UDF_DATA_SIZE); DisplayLongValues("ppk_mod (0x40) : ", (uint8_t*)auth_cert->acPpk.N, RSA_4096_KEY_LENGTH); DisplayLongValues("ppk_mod_ext (0x240) : ", (uint8_t*)auth_cert->acPpk.N_extension, RSA_4096_KEY_LENGTH); DisplayLongValues("ppk_exponent (0x440) : ", (uint8_t*)auth_cert->acPpk.E, 4); DisplayLongValues("ppk_padding (0x444) : ", (uint8_t*)auth_cert->acPpk.Padding, 60); DisplayLongValues("spk_mod (0x480) : ", (uint8_t*)auth_cert->acSpk.N, RSA_4096_KEY_LENGTH); DisplayLongValues("spk_mod_ext (0x680) : ", (uint8_t*)auth_cert->acSpk.N_extension, RSA_4096_KEY_LENGTH); DisplayLongValues("spk_exponent (0x880) : ", (uint8_t*)auth_cert->acSpk.E, 4); DisplayLongValues("spk_padding (0x884) : ", (uint8_t*)auth_cert->acSpk.Padding, 60); DisplayLongValues("spk_signature (0x8c0) : ", (uint8_t*)(&auth_cert->acSpkSignature), RSA_SIGN_LENGTH_ZYNQMP); DisplayLongValues("bh_signature (0xac0) : ", (uint8_t*)(&auth_cert->acBhSignature), RSA_SIGN_LENGTH_ZYNQMP); DisplayLongValues("part_signature (0xcc0) : ", (uint8_t*)(&auth_cert->acPartitionSignature), RSA_SIGN_LENGTH_ZYNQMP); } } /*******************************************************************************/ void ZynqMpReadImage::DisplayBootVectors(void) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << "boot_vectors (0x00) : "; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << bH->bootVectors[0] << std::setw(8) << std::hex << bH->bootVectors[1] << std::setw(8) << std::hex << bH->bootVectors[2] << std::setw(8) << std::hex << bH->bootVectors[3] << bH->bootVectors[4] << std::setw(8) << std::hex << bH->bootVectors[5] << std::setw(8) << std::hex << bH->bootVectors[6] << std::setw(8) << std::hex << bH->bootVectors[7] << std::endl; } /*******************************************************************************/ void ZynqMpReadImage::DisplayBhAttributes(uint32_t value) { std::string val, val1; switch ((value >> AUTH_ONLY_BIT_SHIFT) & OPT_KEY_BIT_MASK) { case 3: val = "[true]"; break; default: val = "[false]"; break; } switch ((value >> AUTH_ONLY_BIT_SHIFT) & AUTH_ONLY_BIT_MASK) { case 3: val = "[true]"; break; default: val = "[false]"; break; } val1 = val; switch ((value >> PUF_HD_BIT_SHIFT) & PUF_HD_BIT_MASK) { case 3: val = "[bh]"; break; default: val = "[efuse]"; break; } DisplayAttributes("auth_only ", val1, "puf_hd_source ", val); switch ((value >> BI_HASH_BIT_SHIFT) & BI_HASH_BIT_MASK) { case 3: val = "[sha-3]"; break; default: val = "[none]"; break; } val1 = val; switch ((value >> CORE_BIT_SHIFT) & CORE_BIT_MASK) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } DisplayAttributes("checksum ", val1, "core ", val); switch ((value >> AUTH_HASH_BIT_SHIFT) & AUTH_HASH_BIT_MASK) { case 2: val = "[puf-12k]"; break; case 3: val = "[puf-4k]"; break; default: val = "[invalid]"; break; } switch ((value >> BH_RSA_BIT_SHIFT) & BH_RSA_BIT_MASK) { case 3: val = "[enabled]"; break; default: val = "[disabled]"; break; } val1 = val; DisplayAttributes("bh_auth ", val1, "puf_mode ", val); } /*******************************************************************************/ void ZynqMpReadImage::DisplayPhtAttributes(uint32_t value) { std::string val, val1, val2, val3; switch ((value >> PH_TRUSTZONE_SHIFT_ZYNQMP) & PH_TRUSTZONE_MASK_ZYNQMP) { case 0: val = "[non-secure]"; break; case 1: val = "[secure]"; break; } val1 = val; switch ((value >> PH_EXCEPTION_LEVEL_SHIFT_ZYNQMP) & PH_EXCEPTION_LEVEL_MASK_ZYNQMP) { case 0: val = "[el-0]"; break; case 1: val = "[el-1]"; break; case 2: val = "[el-2]"; break; case 3: val = "[el-3]"; break; } DisplayAttributes("trustzone ", val1, "el ", val); switch ((value >> PH_EXEC_STATE_SHIFT_ZYNQMP) & PH_EXEC_STATE_MASK_ZYNQMP) { case 0: val = "[aarch-64]"; break; case 1: val = "[aarch-32]"; break; } val1 = val; switch ((value >> PH_DEST_DEVICE_SHIFT_ZYNQMP) & PH_DEST_DEVICE_MASK_ZYNQMP) { case 0: val = "[none]"; break; case 1: val = "[PS]"; break; case 2: val = "[PL]"; break; default: val = "[invalid]"; break; } DisplayAttributes("exec_state ", val1, "dest_device ", val); switch ((value >> PH_ENCRYPT_SHIFT_ZYNQMP) & PH_ENCRYPT_MASK_ZYNQMP) { case 0: val = "[no]"; break; case 1: val = "[yes]"; break; } val1 = val; switch ((value >> PH_DEST_CPU_SHIFT_ZYNQMP) & PH_DEST_CPU_MASK_ZYNQMP) { case 0: val = "[none]"; break; case 1: val = "[a53-0]"; break; case 2: val = "[a53-1]"; break; case 3: val = "[a53-2]"; break; case 4: val = "[a53-3]"; break; case 5: val = "[r5-0]"; break; case 6: val = "[r5-1]"; break; case 7: val = "[r5-lockstep]"; break; case 8: val = "[pmu]"; break; default: val = "[invalid]"; break; } DisplayAttributes("encryption ", val1, "core ", val); switch ((value >> PH_CHECKSUM_SHIFT_ZYNQMP) & PH_CHECKSUM_MASK_ZYNQMP) { case 0: val = "[none]"; break; case 3: val = "[sha-3]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> PH_AC_FLAG_SHIFT_ZYNQMP) & PH_AC_FLAG_MASK_ZYNQMP) { case 0: val = "[none]"; break; case 1: val = "[rsa]"; break; default: val = "[invalid]"; break; } DisplayAttributes("checksum ", val1, "authentication ", val); switch ((value >> PH_OWNER_SHIFT_ZYNQMP) & PH_OWNER_MASK_ZYNQMP) { case 0: val = "[efsbl]"; break; case 1: val = "[non-efsbl]"; break; default: val = "[invalid]"; break; } val1 = val; switch ((value >> PH_ENDIAN_SHIFT_ZYNQMP) & PH_ENDIAN_MASK_ZYNQMP) { case 0: val = "[little-endian]"; break; case 1: val = "[big-endian]"; break; } DisplayAttributes("owner ", val1, "endianness ", val); switch ((value >> PH_EARLY_HANDOFF_SHIFT_ZYNQMP) & PH_EARLY_HANDOFF_MASK_ZYNQMP) { case 0: val = "[no]"; break; case 1: val = "[yes]"; break; } val1 = val; switch ((value >> PH_AUTH_BLOCK_SHIFT_ZYNQMP) & PH_AUTH_BLOCK_MASK_ZYNQMP) { case 0: val = "[none]"; break; case 1: val = "[4kb]"; break; case 2: val = "[8kb]"; break; case 3: val = "[16kb]"; break; case 4: val = "[32kb]"; break; case 5: val = "[64kb]"; break; default: val = "[invalid]"; break; } DisplayAttributes("early_handoff ", val, "auth_blocks ", val); switch ((value >> PH_HIVEC_SHIFT_ZYNQMP) & PH_HIVEC_MASK_ZYNQMP) { case 0: val = "[false]"; break; case 1: val = "[true]"; break; } std::string empty = ""; DisplayAttributes("hi-vec ", val, empty, empty); }xilinx-bootgen-2024.2/readimage-zynqmp.h000077500000000000000000000063051475706442400202200ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _READIMAGE_ZYNQMP_H_ #define _READIMAGE_ZYNQMP_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "readimage.h" #include "bootheader-zynqmp.h" #include "imageheadertable-zynqmp.h" #include "partitionheadertable-zynqmp.h" #include "authentication-zynqmp.h" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ZynqMpReadImage : public ReadImage { public: ZynqMpReadImage(std::string filename) : ReadImage(filename) { bH = NULL; iHT = NULL; iH = NULL; pHT = NULL; iHs.clear(); pHTs.clear(); authenticationVerified = true; plAcCount = 0; } ~ZynqMpReadImage(); void ReadBinaryFile(DumpOption::Type dump = DumpOption::NONE, std::string path = ""); void ReadHeaderTableDetails(); void ReadPartitions(); void DisplayBootHeader(void); void DisplayImageHeaderTable(void); void DisplayImageHeaders(void); void DisplayPartitionHeaderTable(void); void DisplayAuthenicationCertificates(void); void DisplayACFields(uint8_t* rsa_ac, Authentication::Type auth_type); void DisplayBhAttributes(uint32_t value); void DisplayPhtAttributes(uint32_t value); void DisplayBootVectors(void); void DumpPartitions(uint8_t* buffer, uint32_t length, std::string name); void VerifyAuthentication(bool); void VerifyHeaderTableSignature(); void VerifySPKSignature(AuthCertificate4096Structure * auth_cert); void VerifyPartitionSignature(void); bool VerifySignature(bool nist, uint8_t * data, size_t dataLength, ACKey4096 * acKey, uint8_t * signature); protected: ZynqMpBootHeaderStructure* bH; ZynqMpImageHeaderTableStructure* iHT; ZynqMpImageHeaderStructure* iH; ZynqMpPartitionHeaderTableStructure* pHT; std::list iHs; std::list pHTs; bool authenticationVerified; int plAcCount; }; #endif xilinx-bootgen-2024.2/readimage.cpp000077500000000000000000000153231475706442400172170ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include "readimage.h" /*******************************************************************************/ void ReadImage::Separator() { #ifdef SEPARATOR std::cout << SEPARATOR << std::endl; #else std::cout << std::endl; #endif } /*******************************************************************************/ void ReadImage::DisplayImageDetails(ReadImageOption::Type type, DumpOption::Type dump, std::string path) { readType = type; dumpType = dump; dumpPath = path; ReadHeaderTableDetails(); if (readType != ReadImageOption::NONE) { switch (type) { case ReadImageOption::BH: DisplayBootHeader(); break; case ReadImageOption::IHT: DisplayImageHeaderTable(); break; case ReadImageOption::IH: DisplayImageHeaders(); break; case ReadImageOption::PHT: DisplayPartitionHeaderTable(); break; case ReadImageOption::AC: DisplayAuthenicationCertificates(); break; default: DisplayBootHeader(); DisplayImageHeaderTable(); DisplayImageHeaders(); DisplayPartitionHeaderTable(); DisplayAuthenicationCertificates(); break; } Separator(); } ReadBinaryFile(dump, path); } /*******************************************************************************/ void ReadImage::DisplayIV(std::string name, uint32_t* ptr) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << ptr[0] << std::setw(8) << std::hex << ptr[1] << std::setw(8) << std::hex << ptr[2] << std::endl; } /******************************************************************************/ void ReadImage::DisplayKey(std::string name, uint32_t* ptr) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << ptr[0] << std::setw(8) << std::hex << ptr[1] << std::setw(8) << std::hex << ptr[2] << std::setw(8) << std::hex << ptr[3] << std::setw(8) << std::hex << ptr[4] << std::setw(8) << std::hex << ptr[5] << std::endl; std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << " "; std::cout << std::setfill('0') << std::setw(8) << std::hex << ptr[6] << std::setw(8) << std::hex << ptr[7] << std::endl; } /*******************************************************************************/ void ReadImage::DisplayValue(std::string name1, uint32_t value1, std::string name2, uint32_t value2) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name1; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << value1; std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << name2; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << value2; std::cout << std::endl; } /*******************************************************************************/ void ReadImage::DisplayValue(std::string name1, uint32_t value1, std::string name2, std::string value2) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name1; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << value1; std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << name2; std::cout << std::left << value2; std::cout << std::endl; } /*******************************************************************************/ void ReadImage::DisplayValue(std::string name1, uint32_t value1) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name1; std::cout << std::setfill('0') << "0x" << std::setw(8) << std::hex << value1; std::cout << std::endl; } /*******************************************************************************/ void ReadImage::DisplayLongValues(std::string name, uint8_t* ptr, uint32_t num_bytes) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name; uint32_t index = 0; for (uint32_t count = 0; count < num_bytes; count++) { index++; uint32_t temp = ptr[count]; //std::cout << std::setfill('0') << std::setw(2) << std::hex << ptr[count]; std::cout << std::hex << std::setfill('0') << std::setw(2) << temp; if ((index % 24 == 0) && (index < num_bytes)) { std::cout << std::endl; std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << " "; } } std::cout << std::endl; } /*******************************************************************************/ void ReadImage::DisplayAscii(std::string name1, std::string value1) { std::cout << std::setw(30); std::cout << std::setfill(' '); std::cout << std::right << name1; std::cout << value1; std::cout << std::endl; } /******************************************************************************/ void ReadImage::DisplayAttributes(std::string name1, std::string value1, std::string name2, std::string value2) { std::cout << std::setw(25); std::cout << std::setfill(' '); std::cout << std::right << name1; std::cout << std::setw(12); std::cout << std::left << value1; if (name2 != "") { std::cout << std::setw(15); std::cout << std::right << name2; std::cout << std::setw(15); std::cout << std::left << value2; } std::cout << std::endl; } xilinx-bootgen-2024.2/readimage.h000077500000000000000000000075721475706442400166730ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _READIMAGE_H_ #define _READIMAGE_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include #include "authentication.h" #include "bootgenenum.h" #include "encryption.h" #include "binary.h" #include "baseclass.h" #include "bootgenexception.h" #include "logger.h" #include "authkeys.h" /* Forward Class References */ class BootGenOptions; class BootHeader; class ImageHeaderTable; class BootImage; class Partition; class ImageHeader; class ByteFile; #define SEPARATOR "--------------------------------------------------------------------------------" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class ReadImage { public: ReadImage(std::string filename) { binFilename = filename; iHNames.clear(); pHTNames.clear(); aCs.clear(); readType = ReadImageOption::NONE; dumpType = DumpOption::NONE; } virtual ~ReadImage() { } virtual void ReadBinaryFile(DumpOption::Type dump = DumpOption::NONE, std::string path = "") = 0; virtual void ReadHeaderTableDetails() = 0; virtual void DumpPartitions() {}; virtual void ReadPartitions(void) = 0; virtual void DisplayImageDetails(ReadImageOption::Type type, DumpOption::Type dump, std::string path=""); virtual void DisplayBootHeader(void) = 0; virtual void DisplayImageHeaderTable(void) = 0; virtual void DisplayImageHeaders(void) = 0; virtual void DisplayPartitionHeaderTable(void) = 0; virtual void DisplayAuthenicationCertificates(void) = 0; virtual void DisplayACFields(uint8_t* rsa_ac, Authentication::Type auth_type) = 0; void DisplayValue(std::string name1, uint32_t value1); void DisplayValue(std::string name1, uint32_t value1, std::string name2, uint32_t value2); void DisplayValue(std::string name1, uint32_t value1, std::string name2, std::string value2); void DisplayLongValues(std::string name1, uint8_t* value, uint32_t num_bytes); void DisplayAscii(std::string name1, std::string value1); void DisplayIV(std::string name, uint32_t* ptr); void DisplayKey(std::string name, uint32_t* ptr); void DisplayAttributes(std::string name1, std::string value1, std::string name2, std::string value2); virtual void DisplayBootVectors(void) {}; virtual void VerifyAuthentication(bool) {}; void Separator(); bool versalNetSeries; protected: std::string binFilename; std::list iHNames; std::list pHTNames; std::list aCNames; std::list aCs; RSA* rsa; std::string dumpPath; DumpOption::Type dumpType; ReadImageOption::Type readType; }; #endif xilinx-bootgen-2024.2/regdefs.h000077500000000000000000000155501475706442400163670ustar00rootroot00000000000000/* ####################################################################### # Copyright (c) 2022 AMD, Inc. All rights reserved. # # This document contains proprietary information which is # protected by copyright. All rights are reserved. No part of # this document may be photocopied, reproduced or translated to # another program language without prior written consent of # AMD Inc., San Jose, CA. 95124 # # AMD, Inc. # AMD IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A # COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS # ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR # STANDARD, AMD IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION # IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE # FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. # AMD EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO # THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO # ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE # FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS FOR A PARTICULAR PURPOSE. # ####################################################################### */ #include "bootheader.h" #define MAX_REG_GROUPS 202 RegisterInitAddressRange VersalAddressRanges[] = { { 0xffa80000, 0x00000200 }, { 0xffa90000, 0x00000200 }, { 0xffaa0000, 0x00000200 }, { 0xffab0000, 0x00000200 }, { 0xffac0000, 0x00000200 }, { 0xffad0000, 0x00000200 }, { 0xffae0000, 0x00000200 }, { 0xffaf0000, 0x00000200 }, { 0xf11e0000, 0x00000220 }, { 0xf9040000, 0x00001000 }, { 0xf9060000, 0x00001000 }, { 0xf9050000, 0x0000010c }, { 0xf9000000, 0x0000fffc }, { 0xf9010000, 0x00000058 }, { 0xf9020000, 0x0000fffc }, { 0xf9030000, 0x00000040 }, { 0xf9080000, 0x0000fffc }, { 0xf90a0000, 0x0000fffc }, { 0xf9090000, 0x0000c080 }, { 0xf90b0000, 0x0000c080 }, { 0xff9c0000, 0x00000110 }, { 0xf11f0000, 0x0000004c }, { 0xff060000, 0x0000418c }, { 0xff070000, 0x0000418c }, { 0xf12d0000, 0x00000250 }, { 0xf12e4000, 0x00000250 }, { 0xf12e6000, 0x00000250 }, { 0xf12e8000, 0x00000250 }, { 0xf12ea000, 0x00000250 }, { 0xf12ec000, 0x00000250 }, { 0xf12d2000, 0x00000250 }, { 0xf12d4000, 0x00000250 }, { 0xf12d6000, 0x00000250 }, { 0xf12d8000, 0x00000250 }, { 0xf12da000, 0x00000250 }, { 0xf12dc000, 0x00000250 }, { 0xf12de000, 0x00000250 }, { 0xf12e0000, 0x00000250 }, { 0xf12e2000, 0x00000250 }, { 0xf12ee000, 0x00000250 }, { 0xf12b0000, 0x0000011c }, { 0xfcf30000, 0x000000e4 }, { 0xfc000000, 0x00968e48 }, { 0xfca00000, 0x00000328 }, { 0xfcb00000, 0x0000207c }, { 0xfcd00000, 0x000061e0 }, { 0xfcff0000, 0x0000000c }, { 0xfca10000, 0x000003e8 }, { 0xfca20000, 0x00000430 }, { 0xfd1a0000, 0x00000318 }, { 0xff5e0000, 0x00000370 }, { 0xf1260000, 0x000005cc }, { 0xf0d10000, 0x00000ffc }, { 0xf0d00000, 0x00000ffc }, { 0xf0d30000, 0x00000ffc }, { 0xf0d20000, 0x00000ffc }, { 0xf0d50000, 0x00000ffc }, { 0xf0d40000, 0x00000ffc }, { 0xf0d70000, 0x00000ffc }, { 0xf0d60000, 0x00000ffc }, { 0xf0ca0000, 0x00000ffc }, { 0xf0c60000, 0x00000ffc }, { 0xf0c30000, 0x00000ffc }, { 0xf0c20000, 0x00000ffc }, { 0xf0fa0000, 0x00000ffc }, { 0xf0fd0000, 0x00000ffc }, { 0xf0f40000, 0x00000ffc }, { 0xf0f50000, 0x00000ffc }, { 0xf0f60000, 0x00000ffc }, { 0xf0f70000, 0x00000ffc }, { 0xf0f20000, 0x00000ffc }, { 0xf0f00000, 0x00000ffc }, { 0xf0bb0000, 0x00000ffc }, { 0xf0bc0000, 0x00000ffc }, { 0xf0bd0000, 0x00000ffc }, { 0xf0b30000, 0x00000ffc }, { 0xf0b50000, 0x00000ffc }, { 0xf0b20000, 0x00000ffc }, { 0xf0b10000, 0x00000ffc }, { 0xf0b40000, 0x00000ffc }, { 0xf0b00000, 0x00000ffc }, { 0xf0b70000, 0x00000ffc }, { 0xf0b60000, 0x00000ffc }, { 0xf09d0000, 0x00000ffc }, { 0xf0920000, 0x00000ffc }, { 0xf0910000, 0x00000ffc }, { 0xf0900000, 0x00000ffc }, { 0xf0990000, 0x00000ffc }, { 0xf08d0000, 0x00000ffc }, { 0xf0810000, 0x00000ffc }, { 0xf0800000, 0x00000ffc }, { 0xf0a10000, 0x00000ffc }, { 0xf0a00000, 0x00000ffc }, { 0xf0a30000, 0x00000ffc }, { 0xf0a50000, 0x00000ffc }, { 0xf0a40000, 0x00000ffc }, { 0xf0a70000, 0x00000ffc }, { 0xf1200000, 0x00000058 }, { 0xf1250000, 0x00000bfc }, { 0xf1240000, 0x00000060 }, { 0xfd360000, 0x00000f0c }, { 0xfd380000, 0x00000f0c }, { 0xfd5c0000, 0x00000094 }, { 0xfd5e0000, 0x00000040 }, { 0xfd700000, 0x000025fc }, { 0xfd000000, 0x00090118 }, { 0xfd390000, 0x00000284 }, { 0xfd610000, 0x00005000 }, { 0xfd690000, 0x00000ff8 }, { 0xfd5f0000, 0x00000060 }, { 0xfd800000, 0x0003ffb8 }, { 0xfd4d0000, 0x00002fd0 }, { 0xff0c0000, 0x00000b80 }, { 0xff0d0000, 0x00000b80 }, { 0xfe5f0000, 0x0000013c }, { 0xfcb40000, 0x00130000 }, { 0xfd370000, 0x0000009c }, { 0xfe600000, 0x001f0000 }, { 0xf1330000, 0x00240000 }, { 0xffc9f000, 0x000002fc }, { 0xff130000, 0x00000004 }, { 0xff140000, 0x00000020 }, { 0xff300000, 0x000a001c }, { 0xff9b0000, 0x00000f0c }, { 0xfe400000, 0x00001dfc }, { 0xfe000000, 0x0000017c }, { 0xff0a0000, 0x0000007c }, { 0xff080000, 0x00000728 }, { 0xff410000, 0x0000a040 }, { 0xff510000, 0x00000080 }, { 0xff990000, 0x00001640 }, { 0xff960000, 0x00000ff8 }, { 0xff980000, 0x00000284 }, { 0xf1010000, 0x00001ffc }, { 0xfca50000, 0x00000e9c }, { 0xfca60000, 0x00000e9c }, { 0xfca70000, 0x00000e08 }, { 0xfcfb0000, 0x00001db8 }, { 0xfcfc0000, 0x00001db8 }, { 0xf9000000, 0x00001ffc }, { 0xf1160000, 0x00020254 }, { 0xf11c0000, 0x00000ff8 }, { 0xf11d0000, 0x00000ff8 }, { 0xf1110000, 0x00040034 }, { 0xf1020000, 0x00000324 }, { 0xf1000000, 0x00000030 }, { 0xf1080000, 0x0000027c }, { 0xf1070000, 0x0000006c }, { 0xf1060000, 0x00000828 }, { 0xf1320000, 0x000019fc }, { 0xf1100000, 0x00000ff8 }, { 0xf1270000, 0x0002060c }, { 0xf11a0000, 0x00010034 }, { 0xf12f0000, 0x00000284 }, { 0xf1310000, 0x00001640 }, { 0xf1300000, 0x00001640 }, { 0xf0080000, 0x00000078 }, { 0xf0110000, 0x00005980 }, { 0xf0081000, 0x00000380 }, { 0xf0083000, 0x00000008 }, { 0xf0082000, 0x00000028 }, { 0xf0100000, 0x00000010 }, { 0xf0280000, 0x00000078 }, { 0xf0310000, 0x00005980 }, { 0xf0282000, 0x00000380 }, { 0xf0281000, 0x00000380 }, { 0xf0284000, 0x00000008 }, { 0xf0283000, 0x00000028 }, { 0xf0300000, 0x00000010 }, { 0xffc90000, 0x0000304c }, { 0xffc80000, 0x00000078 }, { 0xffc88000, 0x00000804 }, { 0xffcf0000, 0x00005980 }, { 0xffcb0000, 0x00000380 }, { 0xffca0000, 0x00000380 }, { 0xffcd0000, 0x00000008 }, { 0xffcc0000, 0x00000028 }, { 0xffce0000, 0x00000010 }, { 0xff0b0000, 0x000002e4 }, { 0xff020000, 0x00000030 }, { 0xff030000, 0x00000030 }, { 0xf0050000, 0x000003c4 }, { 0xf1030000, 0x00000828 }, { 0xff9a0000, 0x00000228 }, { 0xf12a0000, 0x00000050 }, { 0xf1040000, 0x0000f0fc }, { 0xf1050000, 0x0000f0fc }, { 0xf1210000, 0x00000050 }, { 0xf1220000, 0x0000030c }, { 0xff040000, 0x000000fc }, { 0xff050000, 0x000000fc }, { 0xf1230000, 0x000000f0 }, { 0xff0e0000, 0x00000080 }, { 0xff0f0000, 0x00000080 }, { 0xff100000, 0x00000080 }, { 0xff110000, 0x00000080 }, { 0xff000000, 0x00000ffc }, { 0xff010000, 0x00000ffc }, { 0xff9d0000, 0x00000070 }, { 0xfe200000, 0x0000cc28 }, { 0xff120000, 0x00002fd0 }, { 0xe1000000, 0x00006028 }, { 0x00000000, 0x00000000 }};xilinx-bootgen-2024.2/reginit.cpp000077500000000000000000000073711475706442400167460ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include "bootimage.h" #include "reginitscanner.h" #include "options.h" #include "bifoptions.h" #include "regdefs.h" /* ------------------------------------------------------------------------------- ***************************************************** F U N C T I O N S *** ------------------------------------------------------------------------------- */ /*****************************************************************************/ void RegisterTable::Build(Options& options, RegisterInitTable* regtab0) { regtab = regtab0; filename = options.bifOptions->GetRegInitFileName(); if (filename != "") { LOG_INFO("Started RE parsing : %s", filename.c_str()); RE::FlexScanner scanner; RE::BisonParser parser(scanner,options,*this); scanner.filename = filename; std::ifstream s(filename.c_str()); if (!s) { LOG_ERROR("Cannot read file - %s", filename.c_str()); } scanner.switch_streams(&s); parser.parse(); fileParseEnd = true; LOG_INFO("Done RE parsing : %s. Added %d regiter pairs", filename.c_str(), count); } if(invalidAddr.size() != 0) { for (size_t itr = 0; itr < invalidAddr.size(); itr++) { LOG_MSG("\t 0x%x", invalidAddr[itr]); } LOG_ERROR("Given ini file has the above invalid Addresses : %s", filename.c_str()); } /* Fill the remainder of the area with NOPs. */ while(count < MAX_REGISTER_INITS) { Add(options, INVALID_REGISTER_ADDRESS, 0); } } /******************************************************************************/ void RegisterTable::Add(Options& options, uint32_t address, uint32_t value) { if (count >= MAX_REGISTER_INITS) { LOG_ERROR("Too many register init pairs in %s", filename.c_str()); } if (options.archType == Arch::VERSAL && !options.IsVersalNetSeries()) { if (fileParseEnd != true) { bool isvalidAddress = false; for (int j = 0; j < MAX_REG_GROUPS; j++) { if ((address <= (VersalAddressRanges[j].baseaddr + VersalAddressRanges[j].size)) && (address >= (VersalAddressRanges[j].baseaddr))) { isvalidAddress = true; break; } } if (!isvalidAddress) { invalidAddr.push_back(address); } } } if (address != 0xFFFFFFFF) { LOG_INFO("\t address [0x%8x], value = 0x%x", address, value); } regtab->registerInitialization[count ].address = address; regtab->registerInitialization[count ].value = value; count++; } xilinx-bootgen-2024.2/reginit.l000077500000000000000000000056221475706442400164140ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the register initialization file */ /* Run the regedit.y file first through bison to generate the regidit.tab.hpp file, which is included herein */ /* Then run this file through flex to generate the reginit.yy.c source code */ %{ #include #include "reginitscanner.h" #include "reginit.tab.hpp" typedef RE::BisonParser::token tok; #include %} %option nodefault yyclass="FlexScanner" noyywrap c++ noyywrap nounput batch debug /* \.bitset\. return tok::BITSET; \.bitclear\. return tok::BITCLEAR; \.boot\. return tok::BOOT; \.user\. return tok::USER; */ %{ # define YY_USER_ACTION yylloc->columns (yyleng); %} %% %{ yylloc->step (); %} "/*" { comment(); } \/\/.*?\n /* ignore */; [0-9]+ yylval->number=atoi(yytext); return tok::DECVALUE; 0[xX][0-9a-fA-F]+ yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; \.set\. return tok::SET; \.or\. return tok::OR; \.xor\. return tok::XOR; \.and\. return tok::AND; \+ return tok::PLUS; \- return tok::MINUS; \<\< return tok::LSHIFT; \>\> return tok::RSHIFT; \* return tok::MULT; \/ return tok::DIVIDE; \% return tok::MODULO; \~ return tok::NEGATION; \& return tok::AND; \| return tok::OR; \^ return tok::XOR; \( return tok::LPAREN; \) return tok::RPAREN; \= return tok::EQUAL; ; return tok::SEMICOLON; [ \t]+ yylloc->step (); [\n]+ yylloc->lines (yyleng); yylloc->step (); . std::cerr << "WARNING: bad character '" << yytext << " at " << *yylloc << std::endl; %% void RE::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/reginit.tab.cpp000066400000000000000000000772301475706442400175110ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton implementation for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* First part of user declarations. */ /* Line 279 of lalr1.cc */ #line 53 "../../s/reginit.y" #include #include "reginitscanner.h" #include "options.h" #include "parsing.h" /* Line 279 of lalr1.cc */ #line 45 "reginit.tab.cpp" #include "reginit.tab.hpp" /* User implementation prologue. */ /* Line 285 of lalr1.cc */ #line 53 "reginit.tab.cpp" /* Unqualified %code blocks. */ /* Line 286 of lalr1.cc */ #line 49 "../../s/reginit.y" static int yylex(RE::BisonParser::semantic_type * yylval, RE::BisonParser::location_type* loc, RE::FlexScanner &scanner); /* Line 286 of lalr1.cc */ #line 62 "reginit.tab.cpp" # ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULL nullptr # else # define YY_NULL 0 # endif # endif #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* FIXME: INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ # ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (N) \ { \ (Current).begin = YYRHSLOC (Rhs, 1).begin; \ (Current).end = YYRHSLOC (Rhs, N).end; \ } \ else \ { \ (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ } \ while (/*CONSTCOND*/ false) # endif /* Suppress unused-variable warnings by "using" E. */ #define YYUSE(e) ((void) (e)) /* Enable debugging if requested. */ #if YYDEBUG /* A pseudo ostream that takes yydebug_ into account. */ # define YYCDEBUG if (yydebug_) (*yycdebug_) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug_) \ { \ *yycdebug_ << Title << ' '; \ yy_symbol_print_ ((Type), (Value), (Location)); \ *yycdebug_ << std::endl; \ } \ } while (false) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug_) \ yy_reduce_print_ (Rule); \ } while (false) # define YY_STACK_PRINT() \ do { \ if (yydebug_) \ yystack_print_ (); \ } while (false) #else /* !YYDEBUG */ # define YYCDEBUG if (false) std::cerr # define YY_SYMBOL_PRINT(Title, Type, Value, Location) YYUSE(Type) # define YY_REDUCE_PRINT(Rule) static_cast(0) # define YY_STACK_PRINT() static_cast(0) #endif /* !YYDEBUG */ #define yyerrok (yyerrstatus_ = 0) #define yyclearin (yychar = yyempty_) #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus_) /* Line 353 of lalr1.cc */ #line 24 "../../s/reginit.y" namespace RE { /* Line 353 of lalr1.cc */ #line 158 "reginit.tab.cpp" /// Build a parser object. BisonParser::BisonParser (RE::FlexScanner& scanner_yyarg, Options& options_yyarg, RegisterTable& regtab_yyarg) : #if YYDEBUG yydebug_ (false), yycdebug_ (&std::cerr), #endif scanner (scanner_yyarg), options (options_yyarg), regtab (regtab_yyarg) { } BisonParser::~BisonParser () { } #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ inline void BisonParser::yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yyvaluep); std::ostream& yyo = debug_stream (); std::ostream& yyoutput = yyo; YYUSE (yyoutput); switch (yytype) { default: break; } } void BisonParser::yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm") << ' ' << yytname_[yytype] << " (" << *yylocationp << ": "; yy_symbol_value_print_ (yytype, yyvaluep, yylocationp); *yycdebug_ << ')'; } #endif void BisonParser::yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yymsg); YYUSE (yyvaluep); if (yymsg) YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } void BisonParser::yypop_ (unsigned int n) { yystate_stack_.pop (n); yysemantic_stack_.pop (n); yylocation_stack_.pop (n); } #if YYDEBUG std::ostream& BisonParser::debug_stream () const { return *yycdebug_; } void BisonParser::set_debug_stream (std::ostream& o) { yycdebug_ = &o; } BisonParser::debug_level_type BisonParser::debug_level () const { return yydebug_; } void BisonParser::set_debug_level (debug_level_type l) { yydebug_ = l; } #endif inline bool BisonParser::yy_pact_value_is_default_ (int yyvalue) { return yyvalue == yypact_ninf_; } inline bool BisonParser::yy_table_value_is_error_ (int yyvalue) { return yyvalue == yytable_ninf_; } int BisonParser::parse () { /// Lookahead and lookahead in internal form. int yychar = yyempty_; int yytoken = 0; // State. int yyn; int yylen = 0; int yystate = 0; // Error handling. int yynerrs_ = 0; int yyerrstatus_ = 0; /// Semantic value of the lookahead. static semantic_type yyval_default; semantic_type yylval = yyval_default; /// Location of the lookahead. location_type yylloc; /// The locations where the error started and ended. location_type yyerror_range[3]; /// $$. semantic_type yyval; /// @$. location_type yyloc; int yyresult; // FIXME: This shoud be completely indented. It is not yet to // avoid gratuitous conflicts when merging into the master branch. try { YYCDEBUG << "Starting parse" << std::endl; /* User initialization code. */ /* Line 545 of lalr1.cc */ #line 32 "../../s/reginit.y" { // Initialize the initial location. yylloc.begin.filename = yylloc.end.filename = &scanner.filename; } /* Line 545 of lalr1.cc */ #line 323 "reginit.tab.cpp" /* Initialize the stacks. The initial state will be pushed in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ yystate_stack_ = state_stack_type (0); yysemantic_stack_ = semantic_stack_type (0); yylocation_stack_ = location_stack_type (0); yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* New state. */ yynewstate: yystate_stack_.push (yystate); YYCDEBUG << "Entering state " << yystate << std::endl; /* Accept? */ if (yystate == yyfinal_) goto yyacceptlab; goto yybackup; /* Backup. */ yybackup: /* Try to take a decision without lookahead. */ yyn = yypact_[yystate]; if (yy_pact_value_is_default_ (yyn)) goto yydefault; /* Read a lookahead token. */ if (yychar == yyempty_) { YYCDEBUG << "Reading a token: "; yychar = yylex (&yylval, &yylloc, scanner); } /* Convert token to internal form. */ if (yychar <= yyeof_) { yychar = yytoken = yyeof_; YYCDEBUG << "Now at end of input." << std::endl; } else { yytoken = yytranslate_ (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) goto yydefault; /* Reduce or error. */ yyn = yytable_[yyn]; if (yyn <= 0) { if (yy_table_value_is_error_ (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted. */ yychar = yyempty_; yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus_) --yyerrstatus_; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact_[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: yylen = yyr2_[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. */ if (yylen) yyval = yysemantic_stack_[yylen - 1]; else yyval = yysemantic_stack_[0]; // Compute the default @$. { BIF::slice slice (yylocation_stack_, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen); } // Perform the reduction. YY_REDUCE_PRINT (yyn); switch (yyn) { case 5: /* Line 670 of lalr1.cc */ #line 91 "../../s/reginit.y" { regtab.Add(options,(yysemantic_stack_[(5) - (2)].number),(yysemantic_stack_[(5) - (4)].number)); } break; case 8: /* Line 670 of lalr1.cc */ #line 95 "../../s/reginit.y" { (yyval.number) = (yysemantic_stack_[(3) - (2)].number); } break; case 10: /* Line 670 of lalr1.cc */ #line 99 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(2) - (2)].number); *options.debugstr << (yyval.number) << " + " << (yysemantic_stack_[(2) - (2)].number) << std::endl;} break; case 11: /* Line 670 of lalr1.cc */ #line 100 "../../s/reginit.y" {(yyval.number) = ~(yysemantic_stack_[(2) - (2)].number); *options.debugstr << (yyval.number) << " ~ " << (yysemantic_stack_[(2) - (2)].number) << std::endl;} break; case 13: /* Line 670 of lalr1.cc */ #line 105 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) * (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " + " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 14: /* Line 670 of lalr1.cc */ #line 106 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) / (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " / " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 15: /* Line 670 of lalr1.cc */ #line 107 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) % (yysemantic_stack_[(3) - (3)].number); *options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " % " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 17: /* Line 670 of lalr1.cc */ #line 112 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) + (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " + " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 18: /* Line 670 of lalr1.cc */ #line 113 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) - (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " - " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 20: /* Line 670 of lalr1.cc */ #line 118 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) << (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " << " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 21: /* Line 670 of lalr1.cc */ #line 119 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) >> (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " >> " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 23: /* Line 670 of lalr1.cc */ #line 124 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) & (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " & " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 25: /* Line 670 of lalr1.cc */ #line 129 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) ^ (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " ^ " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; case 27: /* Line 670 of lalr1.cc */ #line 134 "../../s/reginit.y" {(yyval.number) = (yysemantic_stack_[(3) - (1)].number) | (yysemantic_stack_[(3) - (3)].number);*options.debugstr << (yyval.number) << " = " << (yysemantic_stack_[(3) - (1)].number) << " | " << (yysemantic_stack_[(3) - (3)].number) << std::endl;} break; /* Line 670 of lalr1.cc */ #line 527 "reginit.tab.cpp" default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc); yypop_ (yylen); yylen = 0; YY_STACK_PRINT (); yysemantic_stack_.push (yyval); yylocation_stack_.push (yyloc); /* Shift the result of the reduction. */ yyn = yyr1_[yyn]; yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0]; if (0 <= yystate && yystate <= yylast_ && yycheck_[yystate] == yystate_stack_[0]) yystate = yytable_[yystate]; else yystate = yydefgoto_[yyn - yyntokens_]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus_) { ++yynerrs_; if (yychar == yyempty_) yytoken = yyempty_; error (yylloc, yysyntax_error_ (yystate, yytoken)); } yyerror_range[1] = yylloc; if (yyerrstatus_ == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= yyeof_) { /* Return failure if at end of input. */ if (yychar == yyeof_) YYABORT; } else { yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); yychar = yyempty_; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (false) goto yyerrorlab; yyerror_range[1] = yylocation_stack_[yylen - 1]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ yypop_ (yylen); yylen = 0; yystate = yystate_stack_[0]; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus_ = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact_[yystate]; if (!yy_pact_value_is_default_ (yyn)) { yyn += yyterror_; if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_) { yyn = yytable_[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yystate_stack_.height () == 1) YYABORT; yyerror_range[1] = yylocation_stack_[0]; yydestruct_ ("Error: popping", yystos_[yystate], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); yystate = yystate_stack_[0]; YY_STACK_PRINT (); } yyerror_range[2] = yylloc; // Using YYLLOC is tempting, but would change the location of // the lookahead. YYLOC is available though. YYLLOC_DEFAULT (yyloc, yyerror_range, 2); yysemantic_stack_.push (yylval); yylocation_stack_.push (yyloc); /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos_[yyn], &yysemantic_stack_[0], &yylocation_stack_[0]); yystate = yyn; goto yynewstate; /* Accept. */ yyacceptlab: yyresult = 0; goto yyreturn; /* Abort. */ yyabortlab: yyresult = 1; goto yyreturn; yyreturn: if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ yypop_ (yylen); while (1 < yystate_stack_.height ()) { yydestruct_ ("Cleanup: popping", yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } return yyresult; } catch (...) { YYCDEBUG << "Exception caught: cleaning lookahead and stack" << std::endl; // Do not try to display the values of the reclaimed symbols, // as their printer might throw an exception. if (yychar != yyempty_) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yytranslate_ (yychar); yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc); } while (1 < yystate_stack_.height ()) { yydestruct_ (YY_NULL, yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } throw; } } // Generate an error message. std::string BisonParser::yysyntax_error_ (int, int) { return YY_("syntax error"); } /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ const signed char BisonParser::yypact_ninf_ = -19; const signed char BisonParser::yypact_[] = { -19, 15, 20, -19, 12, -19, 12, 12, 12, -19, -19, -19, -19, 3, -6, 1, 19, 23, -1, -19, -19, 5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -19, -19, -19, -19, 3, 3, -6, -6, 1, 19, 23, 2, -19 }; /* YYDEFACT[S] -- default reduction number in state S. Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ const unsigned char BisonParser::yydefact_[] = { 3, 0, 2, 1, 0, 4, 0, 0, 0, 7, 6, 9, 12, 16, 19, 22, 24, 26, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 13, 14, 15, 17, 18, 20, 21, 23, 25, 27, 0, 5 }; /* YYPGOTO[NTERM-NUM]. */ const signed char BisonParser::yypgoto_[] = { -19, -19, -19, -19, -19, -5, -18, 6, 0, 7, 4, -8 }; /* YYDEFGOTO[NTERM-NUM]. */ const signed char BisonParser::yydefgoto_[] = { -1, 1, 2, 5, 11, 12, 13, 14, 15, 16, 17, 18 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF_, syntax error. */ const signed char BisonParser::yytable_ninf_ = -1; const unsigned char BisonParser::yytable_[] = { 21, 19, 20, 31, 25, 26, 31, 37, 38, 31, 22, 23, 24, 27, 28, 3, 32, 34, 35, 36, 45, 33, 6, 4, 44, 29, 7, 8, 30, 41, 0, 9, 10, 39, 40, 43, 0, 42 }; /* YYCHECK. */ const signed char BisonParser::yycheck_[] = { 8, 6, 7, 4, 10, 11, 4, 25, 26, 4, 7, 8, 9, 12, 13, 0, 17, 22, 23, 24, 18, 16, 10, 3, 32, 6, 14, 15, 5, 29, -1, 19, 20, 27, 28, 31, -1, 30 }; /* STOS_[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ const unsigned char BisonParser::yystos_[] = { 0, 22, 23, 0, 3, 24, 10, 14, 15, 19, 20, 25, 26, 27, 28, 29, 30, 31, 32, 26, 26, 32, 7, 8, 9, 10, 11, 12, 13, 6, 5, 4, 17, 16, 26, 26, 26, 27, 27, 28, 28, 29, 30, 31, 32, 18 }; #if YYDEBUG /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding to YYLEX-NUM. */ const unsigned short int BisonParser::yytoken_number_[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ const unsigned char BisonParser::yyr1_[] = { 0, 21, 22, 23, 23, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 31, 31, 32, 32 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ const unsigned char BisonParser::yyr2_[] = { 0, 2, 1, 0, 2, 5, 1, 1, 3, 1, 2, 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3 }; #if YYDEBUG /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at \a yyntokens_, nonterminals. */ const char* const BisonParser::yytname_[] = { "$end", "error", "$undefined", "SET", "OR", "XOR", "AND", "MULT", "DIVIDE", "MODULO", "PLUS", "MINUS", "LSHIFT", "RSHIFT", "NEGATION", "LPAREN", "RPAREN", "EQUAL", "SEMICOLON", "DECVALUE", "HEXVALUE", "$accept", "top", "statements", "statement", "number", "unary_expression", "multiplicative_expression", "additive_expression", "shift_expression", "and_expression", "xor_expression", "expression", YY_NULL }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ const BisonParser::rhs_number_type BisonParser::yyrhs_[] = { 22, 0, -1, 23, -1, -1, 23, 24, -1, 3, 32, 17, 32, 18, -1, 20, -1, 19, -1, 15, 32, 16, -1, 25, -1, 10, 26, -1, 14, 26, -1, 26, -1, 27, 7, 26, -1, 27, 8, 26, -1, 27, 9, 26, -1, 27, -1, 28, 10, 27, -1, 28, 11, 27, -1, 28, -1, 29, 12, 28, -1, 29, 13, 28, -1, 29, -1, 30, 6, 29, -1, 30, -1, 31, 5, 30, -1, 31, -1, 32, 4, 31, -1 }; /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ const unsigned char BisonParser::yyprhs_[] = { 0, 0, 3, 5, 6, 9, 15, 17, 19, 23, 25, 28, 31, 33, 37, 41, 45, 47, 51, 55, 57, 61, 65, 67, 71, 73, 77, 79 }; /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ const unsigned char BisonParser::yyrline_[] = { 0, 87, 87, 89, 89, 91, 93, 94, 95, 98, 99, 100, 104, 105, 106, 107, 111, 112, 113, 117, 118, 119, 123, 124, 128, 129, 133, 134 }; // Print the state stack on the debug stream. void BisonParser::yystack_print_ () { *yycdebug_ << "Stack now"; for (state_stack_type::const_iterator i = yystate_stack_.begin (); i != yystate_stack_.end (); ++i) *yycdebug_ << ' ' << *i; *yycdebug_ << std::endl; } // Report on the debug stream that the rule \a yyrule is going to be reduced. void BisonParser::yy_reduce_print_ (int yyrule) { unsigned int yylno = yyrline_[yyrule]; int yynrhs = yyr2_[yyrule]; /* Print the symbols being reduced, and their result. */ *yycdebug_ << "Reducing stack by rule " << yyrule - 1 << " (line " << yylno << "):" << std::endl; /* The symbols being reduced. */ for (int yyi = 0; yyi < yynrhs; yyi++) YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", yyrhs_[yyprhs_[yyrule] + yyi], &(yysemantic_stack_[(yynrhs) - (yyi + 1)]), &(yylocation_stack_[(yynrhs) - (yyi + 1)])); } #endif // YYDEBUG /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ BisonParser::token_number_type BisonParser::yytranslate_ (int t) { static const token_number_type translate_table[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; if ((unsigned int) t <= yyuser_token_number_max_) return translate_table[t]; else return yyundef_token_; } const int BisonParser::yyeof_ = 0; const int BisonParser::yylast_ = 37; const int BisonParser::yynnts_ = 12; const int BisonParser::yyempty_ = -2; const int BisonParser::yyfinal_ = 3; const int BisonParser::yyterror_ = 1; const int BisonParser::yyerrcode_ = 256; const int BisonParser::yyntokens_ = 21; const unsigned int BisonParser::yyuser_token_number_max_ = 275; const BisonParser::token_number_type BisonParser::yyundef_token_ = 2; /* Line 1141 of lalr1.cc */ #line 24 "../../s/reginit.y" } // RE /* Line 1141 of lalr1.cc */ #line 981 "reginit.tab.cpp" /* Line 1142 of lalr1.cc */ #line 138 "../../s/reginit.y" void RE::BisonParser::error(const RE::BisonParser::location_type &loc, const std::string &msg) { Parsing::Error(loc,msg); } static int yylex(RE::BisonParser::semantic_type * yylval, RE::BisonParser::location_type* loc, RE::FlexScanner &scanner) { return scanner.yylex(yylval, loc); } xilinx-bootgen-2024.2/reginit.tab.hpp000066400000000000000000000216771475706442400175220ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Skeleton interface for Bison LALR(1) parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file reginit.tab.hpp ** Define the RE::parser class. */ /* C++ LALR(1) parser skeleton written by Akim Demaille. */ #ifndef YY_YY_REGINIT_TAB_HPP_INCLUDED # define YY_YY_REGINIT_TAB_HPP_INCLUDED /* "%code requires" blocks. */ /* Line 33 of lalr1.cc */ #line 39 "../../s/reginit.y" namespace RE { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "location.hh" /* Line 33 of lalr1.cc */ #line 58 "reginit.tab.hpp" #include #include #include "stack.hh" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Line 33 of lalr1.cc */ #line 24 "../../s/reginit.y" namespace RE { /* Line 33 of lalr1.cc */ #line 75 "reginit.tab.hpp" /// A Bison parser. class BisonParser { public: /// Symbol semantic values. #ifndef YYSTYPE union semantic_type { /* Line 33 of lalr1.cc */ #line 64 "../../s/reginit.y" unsigned long number; /* Line 33 of lalr1.cc */ #line 92 "reginit.tab.hpp" }; #else typedef YYSTYPE semantic_type; #endif /// Symbol locations. typedef BIF::location location_type; /// Tokens. struct token { /* Tokens. */ enum yytokentype { SET = 258, OR = 259, XOR = 260, AND = 261, MULT = 262, DIVIDE = 263, MODULO = 264, PLUS = 265, MINUS = 266, LSHIFT = 267, RSHIFT = 268, NEGATION = 269, LPAREN = 270, RPAREN = 271, EQUAL = 272, SEMICOLON = 273, DECVALUE = 274, HEXVALUE = 275 }; }; /// Token type. typedef token::yytokentype token_type; /// Build a parser object. BisonParser (RE::FlexScanner& scanner_yyarg, Options& options_yyarg, RegisterTable& regtab_yyarg); virtual ~BisonParser (); /// Parse. /// \returns 0 iff parsing succeeded. virtual int parse (); #if YYDEBUG /// The current debugging stream. std::ostream& debug_stream () const; /// Set the current debugging stream. void set_debug_stream (std::ostream &); /// Type for debugging levels. typedef int debug_level_type; /// The current debugging level. debug_level_type debug_level () const; /// Set the current debugging level. void set_debug_level (debug_level_type l); #endif private: /// Report a syntax error. /// \param loc where the syntax error is found. /// \param msg a description of the syntax error. virtual void error (const location_type& loc, const std::string& msg); /// Generate an error message. /// \param state the state where the error occurred. /// \param tok the lookahead token. virtual std::string yysyntax_error_ (int yystate, int tok); #if YYDEBUG /// \brief Report a symbol value on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); /// \brief Report a symbol on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); #endif /// State numbers. typedef int state_type; /// State stack type. typedef BIF::stack state_stack_type; /// Semantic value stack type. typedef BIF::stack semantic_stack_type; /// location stack type. typedef BIF::stack location_stack_type; /// The state stack. state_stack_type yystate_stack_; /// The semantic value stack. semantic_stack_type yysemantic_stack_; /// The location stack. location_stack_type yylocation_stack_; /// Whether the given \c yypact_ value indicates a defaulted state. /// \param yyvalue the value to check static bool yy_pact_value_is_default_ (int yyvalue); /// Whether the given \c yytable_ value indicates a syntax error. /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); /// Internal symbol numbers. typedef unsigned char token_number_type; /* Tables. */ /// For a state, the index in \a yytable_ of its portion. static const signed char yypact_[]; static const signed char yypact_ninf_; /// For a state, default reduction number. /// Unless\a yytable_ specifies something else to do. /// Zero means the default is an error. static const unsigned char yydefact_[]; static const signed char yypgoto_[]; static const signed char yydefgoto_[]; /// What to do in a state. /// \a yytable_[yypact_[s]]: what to do in state \a s. /// - if positive, shift that token. /// - if negative, reduce the rule which number is the opposite. /// - if zero, do what YYDEFACT says. static const unsigned char yytable_[]; static const signed char yytable_ninf_; static const signed char yycheck_[]; /// For a state, its accessing symbol. static const unsigned char yystos_[]; /// For a rule, its LHS. static const unsigned char yyr1_[]; /// For a rule, its RHS length. static const unsigned char yyr2_[]; #if YYDEBUG /// For a symbol, its name in clear. static const char* const yytname_[]; /// A type to store symbol numbers and -1. typedef signed char rhs_number_type; /// A `-1'-separated list of the rules' RHS. static const rhs_number_type yyrhs_[]; /// For each rule, the index of the first RHS symbol in \a yyrhs_. static const unsigned char yyprhs_[]; /// For each rule, its source line number. static const unsigned char yyrline_[]; /// For each scanner token number, its symbol number. static const unsigned short int yytoken_number_[]; /// Report on the debug stream that the rule \a r is going to be reduced. virtual void yy_reduce_print_ (int r); /// Print the state stack on the debug stream. virtual void yystack_print_ (); /* Debugging. */ int yydebug_; std::ostream* yycdebug_; #endif /// Convert a scanner token number \a t to a symbol number. token_number_type yytranslate_ (int t); /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// If null, do not display the symbol, just free it. /// \param yytype The symbol type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. inline void yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp); /// Pop \a n symbols the three stacks. inline void yypop_ (unsigned int n = 1); /* Constants. */ static const int yyeof_; /* LAST_ -- Last index in TABLE_. */ static const int yylast_; static const int yynnts_; static const int yyempty_; static const int yyfinal_; static const int yyterror_; static const int yyerrcode_; static const int yyntokens_; static const unsigned int yyuser_token_number_max_; static const token_number_type yyundef_token_; /* User arguments. */ RE::FlexScanner& scanner; Options& options; RegisterTable& regtab; }; /* Line 33 of lalr1.cc */ #line 24 "../../s/reginit.y" } // RE /* Line 33 of lalr1.cc */ #line 299 "reginit.tab.hpp" #endif /* !YY_YY_REGINIT_TAB_HPP_INCLUDED */ xilinx-bootgen-2024.2/reginit.y000077500000000000000000000110651475706442400164270ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* register init grammar * Use bison to process this file into reginit.tab.cpp */ %require "2.4.1" %skeleton "lalr1.cc" %defines %define namespace "RE" %define parser_class_name "BisonParser" %parse-param { RE::FlexScanner& scanner } %parse-param { Options& options} %parse-param { RegisterTable& regtab} %lex-param { RE::FlexScanner& scanner } %locations %initial-action { // Initialize the initial location. @$.begin.filename = @$.end.filename = &scanner.filename; }; %define api.location.type "BIF::location" %code requires { namespace RE { class BisonScanner; class FlexScanner; class Parser; } #include "bootimage.h" #include "location.hh" } %code { static int yylex(RE::BisonParser::semantic_type * yylval, RE::BisonParser::location_type* loc, RE::FlexScanner &scanner); } %{ #include #include "reginitscanner.h" #include "options.h" #include "parsing.h" %} %start top %union { unsigned long number; } %token SET OR XOR AND MULT DIVIDE MODULO PLUS MINUS LSHIFT RSHIFT %left SET OR XOR AND MULT DIVIDE MODULO PLUS MINUS LSHIFT RSHIFT %token NEGATION %right NEGATION %token LPAREN RPAREN EQUAL SEMICOLON %right LPAREN %left RPAREN %left EQUAL %token DECVALUE HEXVALUE %type expression number multiplicative_expression unary_expression additive_expression shift_expression %type and_expression xor_expression %% top : statements ; statements : /* empty */ | statements statement ; statement : SET expression EQUAL expression SEMICOLON { regtab.Add(options,$2,$4); } ; number : HEXVALUE | DECVALUE | LPAREN expression RPAREN { $$ = $2; }; unary_expression : number | PLUS unary_expression {$$ = $2; *options.debugstr << $$ << " + " << $2 << std::endl;} | NEGATION unary_expression {$$ = ~$2; *options.debugstr << $$ << " ~ " << $2 << std::endl;} ; multiplicative_expression : unary_expression | multiplicative_expression MULT unary_expression {$$ = $1 * $3; *options.debugstr << $$ << " = " << $1 << " + " << $3 << std::endl;} | multiplicative_expression DIVIDE unary_expression {$$ = $1 / $3; *options.debugstr << $$ << " = " << $1 << " / " << $3 << std::endl;} | multiplicative_expression MODULO unary_expression {$$ = $1 % $3; *options.debugstr << $$ << " = " << $1 << " % " << $3 << std::endl;} ; additive_expression : multiplicative_expression | additive_expression PLUS multiplicative_expression {$$ = $1 + $3;*options.debugstr << $$ << " = " << $1 << " + " << $3 << std::endl;} | additive_expression MINUS multiplicative_expression {$$ = $1 - $3;*options.debugstr << $$ << " = " << $1 << " - " << $3 << std::endl;} ; shift_expression : additive_expression | shift_expression LSHIFT additive_expression {$$ = $1 << $3;*options.debugstr << $$ << " = " << $1 << " << " << $3 << std::endl;} | shift_expression RSHIFT additive_expression {$$ = $1 >> $3;*options.debugstr << $$ << " = " << $1 << " >> " << $3 << std::endl;} ; and_expression : shift_expression | and_expression AND shift_expression {$$ = $1 & $3;*options.debugstr << $$ << " = " << $1 << " & " << $3 << std::endl;} ; xor_expression : and_expression | xor_expression XOR and_expression {$$ = $1 ^ $3;*options.debugstr << $$ << " = " << $1 << " ^ " << $3 << std::endl;} ; expression : xor_expression | expression OR xor_expression {$$ = $1 | $3;*options.debugstr << $$ << " = " << $1 << " | " << $3 << std::endl;} ; %% void RE::BisonParser::error(const RE::BisonParser::location_type &loc, const std::string &msg) { Parsing::Error(loc,msg); } static int yylex(RE::BisonParser::semantic_type * yylval, RE::BisonParser::location_type* loc, RE::FlexScanner &scanner) { return scanner.yylex(yylval, loc); } xilinx-bootgen-2024.2/reginit.yy.cpp000066400000000000000000001442001475706442400173740ustar00rootroot00000000000000#line 2 "../bisonflex/reginit.yy.cpp" #line 4 "../bisonflex/reginit.yy.cpp" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ /* %not-for-header */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ /* %ok-for-header */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* %if-c++-only */ /* The c++ scanner is a mess. The FlexLexer.h header file relies on the * following macro. This is required in order to pass the c++-multiple-scanners * test in the regression suite. We get reports that it breaks inheritance. * We will address this in a future release of flex, or omit the C++ scanner * altogether. */ #define yyFlexLexer reginitFlexLexer /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ /* %if-c-only */ /* %endif */ /* %if-tables-serialization */ /* %endif */ /* end standard C headers. */ /* %if-c-or-c++ */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ /* %endif */ /* %if-c++-only */ /* begin standard C++ headers. */ #include #include #include #include /* end standard C++ headers. */ /* %endif */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* %not-for-header */ /* Returned upon end-of-file. */ #define YY_NULL 0 /* %ok-for-header */ /* %not-for-header */ /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* %ok-for-header */ /* %if-reentrant */ /* %endif */ /* %if-not-reentrant */ /* %endif */ /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif /* %if-not-reentrant */ extern int yyleng; /* %endif */ /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ /* %endif */ #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { /* %if-c-only */ /* %endif */ /* %if-c++-only */ std::istream* yy_input_file; /* %endif */ char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %if-not-reentrant */ /* %endif */ /* %ok-for-header */ /* %endif */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* %if-c-only Standard (non-C++) definition */ /* %if-not-reentrant */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ /* %endif */ void *reginitalloc (yy_size_t ); void *reginitrealloc (void *,yy_size_t ); void reginitfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ /* Begin user sect3 */ #define YY_SKIP_YYWRAP #define FLEX_DEBUG typedef unsigned char YY_CHAR; #define yytext_ptr yytext #include "FlexLexer.h" int yyFlexLexer::yywrap() { return 1; } int yyFlexLexer::yylex() { LexerError( "yyFlexLexer::yylex invoked but %option yyclass used" ); return 0; } #define YY_DECL int FlexScanner::yylex() /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ #define YY_NUM_RULES 27 #define YY_END_OF_BUFFER 28 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[52] = { 0, 0, 0, 28, 26, 24, 25, 15, 17, 20, 21, 13, 9, 10, 26, 14, 3, 3, 23, 26, 22, 26, 19, 18, 16, 24, 25, 0, 0, 0, 0, 1, 0, 3, 0, 11, 12, 0, 0, 0, 0, 0, 2, 4, 0, 6, 0, 0, 8, 5, 7, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 4, 5, 1, 6, 7, 8, 9, 1, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 1, 15, 16, 17, 18, 1, 1, 19, 19, 19, 19, 19, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 1, 1, 1, 1, 1, 21, 1, 1, 22, 19, 19, 23, 24, 19, 1, 1, 1, 1, 1, 1, 1, 25, 26, 1, 1, 27, 28, 29, 1, 1, 1, 30, 1, 1, 1, 31, 1, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[33] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int16_t yy_base[54] = { 0, 0, 0, 69, 70, 66, 64, 70, 70, 70, 70, 70, 70, 70, 11, 26, 22, 30, 70, 50, 70, 47, 70, 70, 70, 62, 60, 37, 34, 36, 33, 70, 55, 32, 0, 70, 70, 34, 45, 26, 24, 47, 70, 0, 38, 70, 37, 36, 70, 70, 70, 70, 52, 38 } ; static yyconst flex_int16_t yy_def[54] = { 0, 51, 1, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 51, 53, 51, 51, 51, 51, 51, 51, 52, 51, 53, 51, 51, 51, 51, 51, 51, 51, 0, 51, 51 } ; static yyconst flex_int16_t yy_nxt[103] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 23, 24, 27, 31, 33, 33, 28, 32, 29, 43, 30, 34, 33, 33, 33, 33, 50, 49, 48, 42, 47, 34, 41, 41, 46, 45, 44, 42, 40, 39, 38, 37, 26, 25, 36, 35, 26, 25, 51, 3, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51 } ; static yyconst flex_int16_t yy_chk[103] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 15, 16, 16, 14, 15, 14, 53, 14, 16, 17, 17, 33, 33, 47, 46, 44, 41, 40, 16, 52, 52, 39, 38, 37, 32, 30, 29, 28, 27, 26, 25, 21, 19, 6, 5, 3, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51 } ; static yyconst flex_int16_t yy_rule_linenum[27] = { 0, 50, 51, 54, 55, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81 } ; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "../s/reginit.l" /****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* This is the lexer/flexer input file, that tokenizes the register initialization file */ /* Run the regedit.y file first through bison to generate the regidit.tab.hpp file, which is included herein */ /* Then run this file through flex to generate the reginit.yy.c source code */ #line 23 "../s/reginit.l" #include #include "reginitscanner.h" #include "reginit.tab.hpp" typedef RE::BisonParser::token tok; #include /* \.bitset\. return tok::BITSET; \.bitclear\. return tok::BITCLEAR; \.boot\. return tok::BOOT; \.user\. return tok::USER; */ #line 41 "../s/reginit.l" # define YY_USER_ACTION yylloc->columns (yyleng); #line 569 "../bisonflex/reginit.yy.cpp" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ #include /* %endif */ #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* %if-c-only Reentrant structure and macros (non-C++). */ /* %if-reentrant */ /* %if-c-only */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif End reentrant structures and macros. */ /* %if-bison-bridge */ /* %endif */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ /* %ok-for-header */ /* %endif */ #endif /* %if-c-only */ /* %endif */ /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define ECHO LexerOutput( yytext, yyleng ) /* %endif */ #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ /* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ \ /* %if-c++-only C++ definition \ */\ if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); /* %endif */ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR /* %if-c-only */ /* %endif */ /* %if-c++-only */ #define YY_FATAL_ERROR(msg) LexerError( msg ) /* %endif */ #endif /* %if-tables-serialization structures and prototypes */ /* %not-for-header */ /* %ok-for-header */ /* %not-for-header */ /* %tables-yydmap generated elements */ /* %endif */ /* end tables serialization structures and prototypes */ /* %ok-for-header */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 /* %if-c-only Standard (non-C++) definition */ /* %endif */ /* %if-c++-only C++ definition */ #define YY_DECL int yyFlexLexer::yylex() /* %endif */ #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif /* %% [6.0] YY_RULE_SETUP definition goes here */ #define YY_RULE_SETUP \ YY_USER_ACTION /* %not-for-header */ /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; /* %% [7.0] user's declarations go here */ #line 44 "../s/reginit.l" yylloc->step (); #line 733 "../bisonflex/reginit.yy.cpp" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyin = & std::cin; /* %endif */ if ( ! yyout ) /* %if-c-only */ /* %endif */ /* %if-c++-only */ yyout = & std::cout; /* %endif */ if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { /* %% [8.0] yymore()-related code goes here */ yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; /* %% [9.0] code to set up and find next match goes here */ yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 52 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 51 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: /* %% [10.0] code to find the action number goes here */ yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; /* %% [11.0] code for yylineno update goes here */ do_action: /* This label is used only to access EOF actions. */ /* %% [12.0] debug code goes here */ if ( yy_flex_debug ) { if ( yy_act == 0 ) std::cerr << "--scanner backing up\n"; else if ( yy_act < 27 ) std::cerr << "--accepting rule at line " << yy_rule_linenum[yy_act] << "(\"" << yytext << "\")\n"; else if ( yy_act == 27 ) std::cerr << "--accepting default rule (\"" << yytext << "\")\n"; else if ( yy_act == 28 ) std::cerr << "--(end of buffer or a NUL)\n"; else std::cerr << "--EOF (start condition " << YY_START << ")\n"; } switch ( yy_act ) { /* beginning of action switch */ /* %% [13.0] actions go here */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 50 "../s/reginit.l" { comment(); } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 51 "../s/reginit.l" /* ignore */; YY_BREAK case 3: YY_RULE_SETUP #line 54 "../s/reginit.l" yylval->number=atoi(yytext); return tok::DECVALUE; YY_BREAK case 4: YY_RULE_SETUP #line 55 "../s/reginit.l" yylval->number=strtoul(yytext+2,NULL,16); return tok::HEXVALUE; YY_BREAK case 5: YY_RULE_SETUP #line 57 "../s/reginit.l" return tok::SET; YY_BREAK case 6: YY_RULE_SETUP #line 58 "../s/reginit.l" return tok::OR; YY_BREAK case 7: YY_RULE_SETUP #line 59 "../s/reginit.l" return tok::XOR; YY_BREAK case 8: YY_RULE_SETUP #line 60 "../s/reginit.l" return tok::AND; YY_BREAK case 9: YY_RULE_SETUP #line 62 "../s/reginit.l" return tok::PLUS; YY_BREAK case 10: YY_RULE_SETUP #line 63 "../s/reginit.l" return tok::MINUS; YY_BREAK case 11: YY_RULE_SETUP #line 64 "../s/reginit.l" return tok::LSHIFT; YY_BREAK case 12: YY_RULE_SETUP #line 65 "../s/reginit.l" return tok::RSHIFT; YY_BREAK case 13: YY_RULE_SETUP #line 66 "../s/reginit.l" return tok::MULT; YY_BREAK case 14: YY_RULE_SETUP #line 67 "../s/reginit.l" return tok::DIVIDE; YY_BREAK case 15: YY_RULE_SETUP #line 68 "../s/reginit.l" return tok::MODULO; YY_BREAK case 16: YY_RULE_SETUP #line 69 "../s/reginit.l" return tok::NEGATION; YY_BREAK case 17: YY_RULE_SETUP #line 70 "../s/reginit.l" return tok::AND; YY_BREAK case 18: YY_RULE_SETUP #line 71 "../s/reginit.l" return tok::OR; YY_BREAK case 19: YY_RULE_SETUP #line 72 "../s/reginit.l" return tok::XOR; YY_BREAK case 20: YY_RULE_SETUP #line 73 "../s/reginit.l" return tok::LPAREN; YY_BREAK case 21: YY_RULE_SETUP #line 74 "../s/reginit.l" return tok::RPAREN; YY_BREAK case 22: YY_RULE_SETUP #line 75 "../s/reginit.l" return tok::EQUAL; YY_BREAK case 23: YY_RULE_SETUP #line 76 "../s/reginit.l" return tok::SEMICOLON; YY_BREAK case 24: YY_RULE_SETUP #line 79 "../s/reginit.l" yylloc->step (); YY_BREAK case 25: /* rule 25 can match eol */ YY_RULE_SETUP #line 80 "../s/reginit.l" yylloc->lines (yyleng); yylloc->step (); YY_BREAK case 26: YY_RULE_SETUP #line 81 "../s/reginit.l" std::cerr << "WARNING: bad character '" << yytext << " at " << *yylloc << std::endl; YY_BREAK case 27: YY_RULE_SETUP #line 82 "../s/reginit.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 979 "../bisonflex/reginit.yy.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* %ok-for-header */ /* %if-c++-only */ /* %not-for-header */ /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ) { yyin = arg_yyin; yyout = arg_yyout; yy_c_buf_p = 0; yy_init = 0; yy_start = 0; yy_flex_debug = 0; yylineno = 1; // this will only get updated if %option yylineno yy_did_buffer_switch_on_eof = 0; yy_looking_for_trail_begin = 0; yy_more_flag = 0; yy_more_len = 0; yy_more_offset = yy_prev_more_offset = 0; yy_start_stack_ptr = yy_start_stack_depth = 0; yy_start_stack = NULL; yy_buffer_stack = 0; yy_buffer_stack_top = 0; yy_buffer_stack_max = 0; yy_state_buf = 0; } /* The contents of this function are C++ specific, so the () macro is not used. */ yyFlexLexer::~yyFlexLexer() { delete [] yy_state_buf; reginitfree(yy_start_stack ); yy_delete_buffer( YY_CURRENT_BUFFER ); reginitfree(yy_buffer_stack ); } /* The contents of this function are C++ specific, so the () macro is not used. */ void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out ) { if ( new_in ) { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); } if ( new_out ) yyout = new_out; } #ifdef YY_INTERACTIVE int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) #else int yyFlexLexer::LexerInput( char* buf, int max_size ) #endif { if ( yyin->eof() || yyin->fail() ) return 0; #ifdef YY_INTERACTIVE yyin->get( buf[0] ); if ( yyin->eof() ) return 0; if ( yyin->bad() ) return -1; return 1; #else (void) yyin->read( buf, max_size ); if ( yyin->bad() ) return -1; else return yyin->gcount(); #endif } void yyFlexLexer::LexerOutput( const char* buf, int size ) { (void) yyout->write( buf, size ); } /* %ok-for-header */ /* %endif */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_get_next_buffer() /* %endif */ { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ reginitrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) reginitrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ /* %if-c-only */ /* %not-for-header */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_get_previous_state() /* %endif */ { register yy_state_type yy_current_state; register char *yy_cp; /* %% [15.0] code to get the start state into yy_current_state goes here */ yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { /* %% [16.0] code to find the next state goes here */ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 52 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) /* %endif */ { register int yy_is_jam; /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 52 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 51); return yy_is_jam ? 0 : yy_current_state; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyunput( int c, register char* yy_bp) /* %endif */ { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; /* %% [18.0] update yylineno here */ (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yyinput() /* %endif */ { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); /* %% [19.0] update BOL and yylineno */ return c; } /* %if-c-only */ /* %endif */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyrestart( std::istream* input_file ) /* %endif */ { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_init_buffer( YY_CURRENT_BUFFER, input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) /* %endif */ { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_load_buffer_state() /* %endif */ { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size ) /* %endif */ { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) reginitalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) reginitalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) reginitfree((void *) b->yy_ch_buf ); reginitfree((void *) b ); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ extern "C" int isatty (int ); /* %endif */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file ) /* %endif */ { int oerrno = errno; yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } /* %if-c-only */ /* %endif */ /* %if-c++-only */ b->yy_is_interactive = 0; /* %endif */ errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) /* %endif */ { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /* %if-c-or-c++ */ /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer) /* %endif */ { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /* %endif */ /* %if-c-or-c++ */ /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yypop_buffer_state (void) /* %endif */ { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* %endif */ /* %if-c-or-c++ */ /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yyensure_buffer_stack(void) /* %endif */ { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)reginitalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)reginitrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_push_state( int new_state ) /* %endif */ { if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) { yy_size_t new_size; (yy_start_stack_depth) += YY_START_STACK_INCR; new_size = (yy_start_stack_depth) * sizeof( int ); if ( ! (yy_start_stack) ) (yy_start_stack) = (int *) reginitalloc(new_size ); else (yy_start_stack) = (int *) reginitrealloc((void *) (yy_start_stack),new_size ); if ( ! (yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; BEGIN(new_state); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::yy_pop_state() /* %endif */ { if ( --(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); } /* %if-c-only */ /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_top_state() /* %endif */ { return (yy_start_stack)[(yy_start_stack_ptr) - 1]; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif /* %if-c-only */ /* %endif */ /* %if-c++-only */ void yyFlexLexer::LexerError( yyconst char msg[] ) { std::cerr << msg << std::endl; exit( YY_EXIT_FAILURE ); } /* %endif */ /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /* %if-c-only */ /* %if-reentrant */ /* %endif */ /* %if-reentrant */ /* %endif */ /* %endif */ /* %if-reentrant */ /* %if-bison-bridge */ /* %endif */ /* %endif if-c-only */ /* %if-c-only */ /* %endif */ /* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ /* %if-reentrant */ /* %endif */ /* %endif */ /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *reginitalloc (yy_size_t size ) { return (void *) malloc( size ); } void *reginitrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void reginitfree (void * ptr ) { free( (char *) ptr ); /* see reginitrealloc() for (char *) cast */ } /* %if-tables-serialization definitions */ /* %define-yytables The name for this specific scanner's tables. */ #define YYTABLES_NAME "yytables" /* %endif */ /* %ok-for-header */ #line 82 "../s/reginit.l" void RE::FlexScanner::comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0) { // putchar(c); } if ((c1 = yyinput()) != '/' && c != 0) { unput(c1); goto loop; } } xilinx-bootgen-2024.2/reginitscanner.h000077500000000000000000000051131475706442400177550ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _REGINITSCANNER_H_ #define _REGINITSCANNER_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ // Only include FlexLexer.h if it hasn't been already included #if ! defined(yyFlexLexerOnce) #undef yyFlexLexer #define yyFlexLexer reginitFlexLexer #include "FlexLexer.h" #endif // Override the interface for yylex since we namespaced it #undef YY_DECL #define YY_DECL int RE::FlexScanner::yylex() // Include Bison for types / tokens #include "reginit.tab.hpp" /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ namespace RE { class FlexScanner : public yyFlexLexer { public: // save the pointer to yylval so we can change it, and invoke scanner int yylex(RE::BisonParser::semantic_type * lval, RE::BisonParser::location_type* loc) { yylval = lval; yylloc = loc; return yylex(); } void comment(); std::string filename; private: // Scanning function created by Flex; make this private to force usage // of the overloaded method so we can get a pointer to Bison's yylval int yylex(); // point to yylval (provided by Bison in overloaded yylex) RE::BisonParser::semantic_type * yylval; RE::BisonParser::location_type * yylloc; }; } #endif xilinx-bootgen-2024.2/stack.hh000066400000000000000000000063601475706442400162210ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.7. */ /* Stack handling for Bison parsers in C++ Copyright (C) 2002-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file ../bisonflex/stack.hh ** Define the BIF::stack class. */ #ifndef YY_YY_BISONFLEX_STACK_HH_INCLUDED # define YY_YY_BISONFLEX_STACK_HH_INCLUDED # include /* Line 34 of stack.hh */ #line 24 "../s/bif.y" namespace BIF { /* Line 34 of stack.hh */ #line 48 "../bisonflex/stack.hh" template > class stack { public: // Hide our reversed order. typedef typename S::reverse_iterator iterator; typedef typename S::const_reverse_iterator const_iterator; stack () : seq_ () { } stack (unsigned int n) : seq_ (n) { } inline T& operator [] (unsigned int i) { return seq_[i]; } inline const T& operator [] (unsigned int i) const { return seq_[i]; } inline void push (const T& t) { seq_.push_front (t); } inline void pop (unsigned int n = 1) { for (; n; --n) seq_.pop_front (); } inline unsigned int height () const { return seq_.size (); } inline const_iterator begin () const { return seq_.rbegin (); } inline const_iterator end () const { return seq_.rend (); } private: S seq_; }; /// Present a slice of the top of a stack. template > class slice { public: slice (const S& stack, unsigned int range) : stack_ (stack) , range_ (range) { } inline const T& operator [] (unsigned int i) const { return stack_[range_ - i]; } private: const S& stack_; unsigned int range_; }; /* Line 116 of stack.hh */ #line 24 "../s/bif.y" } // BIF /* Line 116 of stack.hh */ #line 134 "../bisonflex/stack.hh" #endif /* !YY_YY_BISONFLEX_STACK_HH_INCLUDED */ xilinx-bootgen-2024.2/stringutils.h000077500000000000000000000120261475706442400173320ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #pragma once #ifndef _STRINGUTILS_H_ #define _STRINGUTILS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include // for std::transform #include #include #include /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class StringUtils { public: static bool EndsWith(const std::string& str, const std::string& suffix) { size_t i = str.rfind(suffix); return (i != std::string::npos) && (i == (str.length() - suffix.length())); } static std::string ChangeExtension(const std::string& source, const std::string& extension) { if (extension[0] != '.') { throw std::exception(); } std::string s = source; size_t i = s.rfind("."); size_t len = s.length() - i; s.replace(i,len,extension); return s; } static std::string RemoveExtension(const std::string& source) { std::string s = source; return s.substr(0, s.find_last_of(".")); } static std::string GetExtension(const std::string& source) { std::string s = source; size_t i = s.rfind("."); if (i == std::string::npos) return ""; std::string x = s.substr(i); return x; } static void ToLower(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); } static std::string BaseName(const std::string& fullpath) { size_t i1 = fullpath.rfind("/"); size_t i2 = fullpath.rfind("\\"); std::string x; if (i1 != std::string::npos) { x = fullpath.substr(i1+1); } else if (i2 != std::string::npos) { x = fullpath.substr(i2+1); } else { x = fullpath; } return x; } static std::string Format(const std::string fmt, ...) { std::string str; va_list ap; va_start(ap, fmt); str = vFormat(fmt,ap); va_end(ap); return str; } static std::string vFormat(const std::string fmt, va_list ap) { int size = 300; std::string str; while (1) { str.resize(size); int n = vsnprintf((char *)str.c_str(), size,fmt.c_str(), ap); if (n > -1 && n < size) { str.resize(n); return str; } if (n > -1) size = n + 1; else size *= 2; } return str; } static std::pair Split_jsonString(const std::string& str) { auto first = str.find_last_of('{'); if (first == std::string::npos) return{}; auto mid = str.find_first_of(':', first); if (mid == std::string::npos) return{}; auto last = str.find_first_of('}', mid); if (last == std::string::npos) return{}; return{ str.substr(first + 1, mid - first - 1), str.substr(mid + 1, last - mid - 1) }; } static std::string Trim_quotes(const std::string& str) { auto first = str.find_first_of('"'); if (first == std::string::npos) return{}; auto last = str.find_first_of('"', first + 1); if (last == std::string::npos) return{}; return str.substr(first + 1, last - first - 1); } static std::string FolderPath(const std::string& fullpath) { size_t i1 = fullpath.rfind("/"); size_t i2 = fullpath.rfind("\\"); std::string x; if (i1 != std::string::npos) { x = fullpath.substr(0, i1); } else if (i2 != std::string::npos) { x = fullpath.substr(0, i2); } else { x = "./"; } return x; } }; #endif xilinx-bootgen-2024.2/systemutils.h000077500000000000000000000230211475706442400173450ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef _SYSTEMUTILS_H_ #define _SYSTEMUTILS_H_ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #ifdef __cplusplus extern "C" { #endif /* ------------------------------------------------------------------------------- ********************************************* P R E P R O C E S S O R S *** ------------------------------------------------------------------------------- */ #define BITS_IN_BYTE 8 #define BITS_IN_A_WORD 32 /* ------------------------------------------------------------------------------- *************************************************** S T R U C T U R E S *** ------------------------------------------------------------------------------- */ struct UInt128 { uint64_t upper; uint64_t lower; }; typedef struct UInt128 UInt128; /* Read a big endian 16 bit word from a byte stream. */ #define ReadBigEndian16( addr ) \ ( ( (UInt16)( *( (uint8_t *)(addr) + 0 ) ) << 8 ) | \ (UInt16)( *( (uint8_t *)(addr) + 1 ) ) ) /* Write a big endian 16 bit word to a byte stream. */ #define WriteBigEndian16( addr, value ) \ *( (uint8_t *)(addr) + 0 ) = ( ( (value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( (value) & 0xFF ); /* Read a big endian 32 bit word from a byte stream. */ #define ReadBigEndian32( addr ) \ ( ( (uint32_t)( *( (uint8_t *)(addr) + 0 ) ) << 24 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 1 ) ) << 16 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 2 ) ) << 8 ) | \ (uint32_t)( *( (uint8_t *)(addr) + 3 ) ) ) /* Write a big endian 32 bit word to a byte stream. */ #define WriteBigEndian32( addr, value ) \ *( (uint8_t *)(addr) + 0 ) = ( ( (value) >> 24 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( ( (value) >> 16 ) & 0xFF ); \ *( (uint8_t *)(addr) + 2 ) = ( ( (value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 3 ) = ( (value) & 0xFF ); /* Read a big endian 64 bit word from a byte stream. */ #define ReadBigEndian64( addr ) \ ( ( (uint64_t)( *( (uint8_t *)(addr) + 0 ) ) << 56 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 1 ) ) << 48 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 2 ) ) << 40 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 3 ) ) << 32 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 4 ) ) << 24 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 5 ) ) << 16 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 6 ) ) << 8 ) | \ (uint64_t)( *( (uint8_t *)(addr) + 7 ) ) ) /* Write a big endian 64 bit word to a byte stream. */ #define WriteBigEndian64( addr, value ) \ *( (uint8_t *)(addr) + 0 ) = ( ( (uint64_t)(value) >> 56 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( ( (uint64_t)(value) >> 48 ) & 0xFF ); \ *( (uint8_t *)(addr) + 2 ) = ( ( (uint64_t)(value) >> 40 ) & 0xFF ); \ *( (uint8_t *)(addr) + 3 ) = ( ( (uint64_t)(value) >> 32 ) & 0xFF ); \ *( (uint8_t *)(addr) + 4 ) = ( ( (uint64_t)(value) >> 24 ) & 0xFF ); \ *( (uint8_t *)(addr) + 5 ) = ( ( (uint64_t)(value) >> 16 ) & 0xFF ); \ *( (uint8_t *)(addr) + 6 ) = ( ( (uint64_t)(value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 7 ) = ( (uint64_t)(value) & 0xFF ); /* Read a little endian 16 bit word from a byte stream. */ #define ReadLittleEndian16( addr ) \ ( ( (uint16_t)( *( (uint8_t *)(addr) + 1 ) ) << 8 ) | \ (uint16_t)( *( (uint8_t *)(addr) + 0 ) ) ) /* Write a little endian 16 bit word to a byte stream. */ #define WriteLittleEndian16( addr, value ) \ *( (uint8_t *)(addr) + 1 ) = ( ( (value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 0 ) = ( (value) & 0xFF ); /* Read a little endian 32 bit word from a byte stream. */ #define ReadLittleEndian32( addr ) \ ( ( (uint32_t)( *( (uint8_t *)(addr) + 3 ) ) << 24 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 2 ) ) << 16 ) | \ ( (uint32_t)( *( (uint8_t *)(addr) + 1 ) ) << 8 ) | \ (uint32_t)( *( (uint8_t *)(addr) + 0 ) ) ) /* Write a little endian 32 bit word to a byte stream. */ #define WriteLittleEndian32( addr, value ) \ *( (uint8_t *)(addr) + 3 ) = ( ( (value) >> 24 ) & 0xFF ); \ *( (uint8_t *)(addr) + 2 ) = ( ( (value) >> 16 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( ( (value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 0 ) = ( (value) & 0xFF ); /* Read a little endian 64 bit word from a byte stream. */ #define ReadLittleEndian64( addr ) \ ( ( (uint64_t)( *( (uint8_t *)(addr) + 7 ) ) << 56 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 6 ) ) << 48 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 5 ) ) << 40 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 4 ) ) << 32 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 3 ) ) << 24 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 2 ) ) << 16 ) | \ ( (uint64_t)( *( (uint8_t *)(addr) + 1 ) ) << 8 ) | \ (uint64_t)( *( (uint8_t *)(addr) + 0 ) ) ) /* Write a little endian 64 bit word to a byte stream. */ #define WriteLittleEndian64( addr, value ) \ *( (uint8_t *)(addr) + 7 ) = ( ( (uint64_t)(value) >> 56 ) & 0xFF ); \ *( (uint8_t *)(addr) + 6 ) = ( ( (uint64_t)(value) >> 48 ) & 0xFF ); \ *( (uint8_t *)(addr) + 5 ) = ( ( (uint64_t)(value) >> 40 ) & 0xFF ); \ *( (uint8_t *)(addr) + 4 ) = ( ( (uint64_t)(value) >> 32 ) & 0xFF ); \ *( (uint8_t *)(addr) + 3 ) = ( ( (uint64_t)(value) >> 24 ) & 0xFF ); \ *( (uint8_t *)(addr) + 2 ) = ( ( (uint64_t)(value) >> 16 ) & 0xFF ); \ *( (uint8_t *)(addr) + 1 ) = ( ( (uint64_t)(value) >> 8 ) & 0xFF ); \ *( (uint8_t *)(addr) + 0 ) = ( (uint64_t)(value) & 0xFF ); /* Swap the bytes in a 16 bit word. */ #define SwapUInt16Bytes( data16 ) ( ( ( (data16) >> BITS_IN_BYTE ) & 0x00FF ) | \ ( ( (data16) << BITS_IN_BYTE ) & 0xFF00 ) ) /* Swap the bytes in a 32 bit word. */ #define SwapUInt32Bytes( data32 ) ( ( ( (data32) >> ( BITS_IN_BYTE * 3 ) ) & 0x000000FF ) | \ ( ( (data32) >> ( BITS_IN_BYTE * 1 ) ) & 0x0000FF00 ) | \ ( ( (data32) << ( BITS_IN_BYTE * 1 ) ) & 0x00FF0000 ) | \ ( ( (data32) << ( BITS_IN_BYTE * 3 ) ) & 0xFF000000 ) ) /* Swap the bytes in a 64 bit word. */ #define SwapUInt64Bytes( data64 ) ( ( ( (data64) >> ( BITS_IN_BYTE * 7 ) ) & (uint64_t)0x00000000000000FFll ) | \ ( ( (data64) >> ( BITS_IN_BYTE * 5 ) ) & (uint64_t)0x000000000000FF00ll ) | \ ( ( (data64) >> ( BITS_IN_BYTE * 3 ) ) & (uint64_t)0x0000000000FF0000ll ) | \ ( ( (data64) >> ( BITS_IN_BYTE * 1 ) ) & (uint64_t)0x00000000FF000000ll ) | \ ( ( (data64) << ( BITS_IN_BYTE * 1 ) ) & (uint64_t)0x000000FF00000000ll ) | \ ( ( (data64) << ( BITS_IN_BYTE * 3 ) ) & (uint64_t)0x0000FF0000000000ll ) | \ ( ( (data64) << ( BITS_IN_BYTE * 5 ) ) & (uint64_t)0x00FF000000000000ll ) | \ ( ( (data64) << ( BITS_IN_BYTE * 7 ) ) & (uint64_t)0xFF00000000000000ll ) ) /* Trim it down to an even address boundary. */ #define RoundAddressDown( addr ) ( (uint64_t)(addr) & (uint64_t)~( sizeof( char * ) - 1 ) ) /* Increment it up to an even address boundary. */ #define RoundAddressUp( addr ) ( ( ( (uint64_t)(addr) ) + ( sizeof( char * ) - 1 ) ) & (uint64_t)~( sizeof( char * ) - 1 ) ) /* ------------------------------------------------------------------------------- ********************************************************* C L A S S E S *** ------------------------------------------------------------------------------- */ /******************************************************************************/ class DataMover { public: DataMover() {}; ~DataMover() {}; virtual uint32_t ReadData32(const uint8_t* addr) = 0; virtual void WriteData32(const uint8_t* addr, uint32_t word) = 0; }; /******************************************************************************/ class DataMoverLE : public DataMover { public: DataMoverLE() {}; ~DataMoverLE() {}; uint32_t ReadData32(const uint8_t* addr) { return ReadLittleEndian32(addr); } void WriteData32(const uint8_t* addr, uint32_t word) { WriteLittleEndian32(addr, word); } }; /******************************************************************************/ class DataMoverBE : public DataMover { public: DataMoverBE() {}; ~DataMoverBE() {}; uint32_t ReadData32(const uint8_t* addr) { return ReadBigEndian32(addr); } void WriteData32(const uint8_t* addr, uint32_t word) { WriteBigEndian32(addr, word); } }; #ifdef __cplusplus } #endif #endif xilinx-bootgen-2024.2/verifyimage-versal.cpp000077500000000000000000000630431475706442400211040ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include #include #include "readimage-versal.h" #include "authkeys-versal.h" #include "Keccak-compact.h" #include "authentication-versal.h" #include "Keccak-compact-versal.h" #include "partitionheadertable.h" #include "checksum.h" /*******************************************************************************/ void VersalReadImage::VerifyAuthentication(bool verifyImageOption) { ReadBinaryFile(); if (iHT->headerAuthCertificateWordOffset != 0) { VerifyHeaderTableSignature(); } else { //LOG_ERROR("Bootimage %s is not authenticated. Authentication verification cannot be done on this image.", binFilename.c_str()); } VerifyPartitionSignature(); if (authenticationVerified) { LOG_MSG("Authentication is verified on bootimage %s", binFilename.c_str()); } else { LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } } /******************************************************************************************************************************/ bool VersalReadImage::VerifyECDSASignature(bool nist, uint8_t * data, size_t dataLength, ACKeyECDSA *eckey, uint8_t* signature) { uint8_t shaHash[SHA3_LENGTH_BYTES] = { 0 }; Versalcrypto_hash(shaHash, data, dataLength, nist); BIGNUM *qx = BN_bin2bn(eckey->x, sizeof(eckey->x), NULL); BIGNUM *qy = BN_bin2bn(eckey->y, sizeof(eckey->y), NULL); BIGNUM *qr = BN_bin2bn(signature, EC_P384_KEY_LENGTH, NULL); BIGNUM *qs = BN_bin2bn(signature + EC_P384_KEY_LENGTH, EC_P384_KEY_LENGTH, NULL); EC_KEY *eckeyLocal = NULL; eckeyLocal = EC_KEY_new_by_curve_name(NID_secp384r1); EC_KEY_set_public_key_affine_coordinates(eckeyLocal, qx, qy); EC_KEY_set_asn1_flag(eckeyLocal, OPENSSL_EC_NAMED_CURVE); if (!EC_KEY_check_key(eckeyLocal)) { LOG_ERROR("Failed to check EC Key\n"); } ECDSA_SIG* ec_signature = ECDSA_SIG_new(); if (ec_signature != NULL) { #if OPENSSL_VERSION_NUMBER > 0x10100000L ECDSA_SIG_set0(ec_signature, qr, qs); #else ec_signature->r = qr; ec_signature->s = qs; #endif } if (1 != ECDSA_do_verify(shaHash, SHA3_LENGTH_BYTES, ec_signature, eckeyLocal)) { return false; } else { return true; } BN_free(qx); BN_free(qy); BN_free(qr); BN_free(qs); EC_KEY_free(eckeyLocal); ECDSA_SIG_free(ec_signature); } /******************************************************************************************************/ bool VersalReadImage::VerifyECDSAP521Signature(bool nist, uint8_t * data, size_t dataLength, ACKeyECDSAP521 *eckey, uint8_t* signature) { uint8_t shaHash[SHA3_LENGTH_BYTES] = { 0 }; Versalcrypto_hash(shaHash, data, dataLength, nist); BIGNUM *qx = BN_bin2bn(eckey->x, sizeof(eckey->x), NULL); BIGNUM *qy = BN_bin2bn(eckey->y, sizeof(eckey->y), NULL); BIGNUM *qr = BN_bin2bn(signature, EC_P521_KEY_LENGTH2, NULL); BIGNUM *qs = BN_bin2bn(signature + EC_P521_KEY_LENGTH2, EC_P521_KEY_LENGTH2, NULL); EC_KEY *eckeyLocal = NULL; eckeyLocal = EC_KEY_new_by_curve_name(NID_secp521r1); EC_KEY_set_public_key_affine_coordinates(eckeyLocal, qx, qy); EC_KEY_set_asn1_flag(eckeyLocal, OPENSSL_EC_NAMED_CURVE); if (!EC_KEY_check_key(eckeyLocal)) { LOG_ERROR("Failed to check EC Key\n"); } ECDSA_SIG* ec_signature = ECDSA_SIG_new(); if (ec_signature != NULL) { #if OPENSSL_VERSION_NUMBER > 0x10100000L ECDSA_SIG_set0(ec_signature, qr, qs); #else ec_signature->r = qr; ec_signature->s = qs; #endif } if (1 != ECDSA_do_verify(shaHash, 48, ec_signature, eckeyLocal)) { return false; } else { return true; } BN_free(qx); BN_free(qy); BN_free(qr); BN_free(qs); EC_KEY_free(eckeyLocal); ECDSA_SIG_free(ec_signature); } /*******************************************************************************/ bool VersalReadImage::VerifySignature(bool nist, uint8_t * data, size_t dataLength, ACKey4096Sha3Padding * acKey, uint8_t* signature) { /* Find SHA-384 hash from data */ uint8_t shaHash[SHA3_LENGTH_BYTES] = { 0 }; Versalcrypto_hash(shaHash, data, dataLength, nist); rsa = RSA_new(); BIGNUM *n = BN_bin2bn(acKey->N, sizeof(acKey->N), NULL); BIGNUM *e = BN_bin2bn(acKey->E, sizeof(acKey->E), NULL); #if OPENSSL_VERSION_NUMBER > 0x10100000L BIGNUM *d = NULL; RSA_set0_key(rsa, n, e, d); #else rsa->n = n; rsa->e = e; #endif /* Find SHA-384 hash from signature */ uint8_t opensslHashPadded[SIGN_LENGTH_VERSAL] = { 0 }; int ret = RSA_public_encrypt(SIGN_LENGTH_VERSAL, (const unsigned char*)signature, (unsigned char*)opensslHashPadded, rsa, RSA_NO_PADDING); if (ret < 0) { LOG_ERROR("RSA_public_encrypt error"); } if (opensslHashPadded[512 - 1] != 0xbc) { LOG_ERROR("Invalid EM"); } int maskedDBLen = 463; uint8_t* Buffer = new uint8_t[48]; uint8_t* maskDB = new uint8_t[maskedDBLen]; memcpy(Buffer, opensslHashPadded + maskedDBLen, 48); uint8_t masK[463] = { 0 }; RSA4096Sha3PaddingAuthenticationAlgorithm* s = NULL; if (s->MaskGenerationFunction(masK, maskedDBLen, Buffer, 48, EVP_sha384()) == -1) { LOG_ERROR("Authentication internal error"); } memset(maskDB,0x0,maskedDBLen); memcpy(maskDB,opensslHashPadded,463); uint8_t *DB; DB = new uint8_t[maskedDBLen]; for (int i = 0; i < 463; i++) { DB[i] = (masK[i] ^ maskDB[i]); } uint8_t salt[SALT_LENGTH] = { 0 }; memcpy(salt,DB + 415,SALT_LENGTH); uint8_t padding1[PAD1_LENGTH]; memset(padding1, 0, PAD1_LENGTH); //calculate mPad - add padding1 and salt to mHash uint8_t mPad[104]; memset(mPad, 0, 104); memcpy(mPad, padding1, PAD1_LENGTH); memcpy(mPad + PAD1_LENGTH, shaHash, 48); memcpy(mPad + PAD1_LENGTH + 48, salt, SALT_LENGTH); uint8_t *m1; uint8_t maskPadHash[48]; m1 = s -> AttachSHA3Padding(mPad, 104); Versalcrypto_hash(maskPadHash, m1, 208, false); uint8_t opensslHash[SHA3_LENGTH_BYTES] = { 0 }; memcpy(opensslHash,opensslHashPadded + 463, SHA3_LENGTH_BYTES); /* compare openssl Hash with calculated shaHash */ int compare = memcmp(maskPadHash, opensslHash, SHA3_LENGTH_BYTES); delete[] Buffer; delete[] maskDB; delete[] DB; return !compare; } /*******************************************************************************/ void VersalReadImage::VerifyHeaderTableSignature() { Separator(); LOG_MSG("Verifying Header Authentication Certificate"); uint64_t offset = 0; size_t result; FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); std::list::iterator auth_cert = aCs.begin(); bool smap_header_found = false; /* Verifying Header SPK Signature */ VerifySPKSignature(*auth_cert); /* Verifying IHT Signature */ uint32_t iHTLength = sizeof(VersalImageHeaderTableStructure) + (iHT->optionalDataSize * 4); uint8_t* tempIHBuffer = new uint8_t[iHTLength]; memset(tempIHBuffer, 0, iHTLength); bool signatureVerified = false; bH = new VersalBootHeaderStructure; result = fread(bH, 1, sizeof(VersalBootHeaderStructure), binFile); if ((bH->smapWords[0] == 0xDD000000) || (bH->smapWords[0] == 0x00DD0000) || (bH->smapWords[0] == 0x000000DD)) { smap_header_found = true; } if (bH->widthDetectionWord != 0xAA995566) { delete bH; bH = NULL; } if(bH != NULL) { offset = bH->imageHeaderByteOffset; } else { if(smap_header_found) { offset = sizeof(VersalSmapWidthTable); } else { offset = 0x00; } } if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempIHBuffer, 1, iHTLength, binFile); if (result != iHTLength) { LOG_ERROR("Error reading signature"); } } else { LOG_ERROR("Error parsing Headers from BootImage file %s", binFilename.c_str()); } if ((*(*auth_cert) & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(true,tempIHBuffer,iHTLength, (ACKeyECDSA *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_BH_SIGN_OFFSET); } else if((*(*auth_cert) & 0xF3) == 0x22) { LOG_ERROR("Authentication verification of IHT cannot be done with ECDSA-P521 algorithm"); } else if((*(*auth_cert) & 0xF3) == 0x11) { signatureVerified = VerifySignature(true, tempIHBuffer, iHTLength, (ACKey4096Sha3Padding*)(*auth_cert+ AC_SPK_KEY_OFFSET),*auth_cert + AC_BH_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } if (signatureVerified) { LOG_MSG(" Image Header Table Signature Verified"); } else { LOG_MSG(" Image Header Table Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempIHBuffer; /* Partition Signature should not be included for hash calculation. */ size_t headersSize = (iHT->totalMetaHdrLength * 4) - SIGN_LENGTH_VERSAL; size_t headersAcDataSize = sizeof(AuthCertificate4096Sha3PaddingStructure) - SIGN_LENGTH_VERSAL; uint8_t* tempBuffer = new uint8_t[headersSize]; memset(tempBuffer, 0, headersSize); if(bH != NULL) { offset = bH->imageHeaderByteOffset + sizeof(VersalImageHeaderTableStructure); } else { if(smap_header_found) { offset = sizeof(VersalSmapWidthTable) + sizeof(VersalImageHeaderTableStructure); } else { offset = sizeof(VersalImageHeaderTableStructure); } } offset += (iHT->optionalDataSize * 4); if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, headersAcDataSize, binFile); if (result != headersAcDataSize) { LOG_ERROR("Error reading signature"); } } else { LOG_ERROR("Error parsing Headers from BootImage file %s", binFilename.c_str()); } offset = iHT->firstImageHeaderWordOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer + headersAcDataSize, 1, headersSize - headersAcDataSize, binFile); if (result != headersSize - headersAcDataSize) { LOG_ERROR("Error reading signature"); } } else { LOG_ERROR("Error parsing Headers from BootImage file %s", binFilename.c_str()); } if ((*(*auth_cert) & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(true, tempBuffer, headersSize, (ACKeyECDSA *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_PARTITION_SIGN_OFFSET); } else if((*(*auth_cert) & 0xF3) == 0x22) { LOG_ERROR("Authentication verification of Metaheader cannot be done with ECDSA-P521 algorithm"); } else if((*(*auth_cert) & 0xF3) == 0x11) { signatureVerified = VerifySignature(true, tempBuffer, headersSize, (ACKey4096Sha3Padding *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_PARTITION_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } delete[] tempBuffer; if (signatureVerified) { LOG_MSG(" Header Signature Verified"); } else { LOG_MSG(" Header Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } fclose(binFile); } /*******************************************************************************/ void VersalReadImage::VerifySPKSignature(uint8_t* aC) { size_t size = 0; bool signatureVerified = false; size = sizeof(uint32_t) + sizeof(uint32_t) + VERSAL_ACKEY_STRUCT_SIZE + AC_SPK_SHA3PAD_SIZE; uint8_t* tempBuffer = new uint8_t[size]; memcpy(tempBuffer, aC, sizeof(uint32_t) + sizeof(uint32_t)); memcpy(tempBuffer + sizeof(uint32_t) + sizeof(uint32_t), aC + AC_SPK_KEY_OFFSET, VERSAL_ACKEY_STRUCT_SIZE+ AC_SPK_SHA3PAD_SIZE); uint8_t temp = 0; memcpy(&temp, aC, 1); if ((temp & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(false,tempBuffer,size, (ACKeyECDSA *)(aC + AC_PPK_KEY_OFFSET), aC + AC_SPK_SIGN_OFFSET); } else if ((temp & 0xF3) == 0x22) { signatureVerified = VerifyECDSAP521Signature(false,tempBuffer,size, (ACKeyECDSAP521 *)(aC + AC_PPK_KEY_OFFSET), aC + AC_SPK_SIGN_OFFSET); } else if ((temp & 0xF3) == 0x11) { signatureVerified = VerifySignature(false, tempBuffer, size, (ACKey4096Sha3Padding *)(aC + AC_PPK_KEY_OFFSET), aC + AC_SPK_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } if (signatureVerified) { LOG_MSG(" SPK Signature Verified"); } else { LOG_MSG(" SPK Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBuffer; } /*******************************************************************************/ void VersalReadImage::VerifyPartitionSignature(void) { size_t result; uint64_t offset = 0; bool signatureVerified = false; std::list::iterator auth_cert = aCs.begin(); auth_cert++; FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); bH = new VersalBootHeaderStructure; result = fread(bH, 1, sizeof(VersalBootHeaderStructure), binFile); /* Partition Extraction */ std::list::iterator partitionHdr = pHTs.begin(); for (std::list::iterator iH = iHs.begin(); iH != iHs.end(); iH++) { for ( uint32_t cnt_index = 0; cnt_index < (*iH)->dataSectionCount; cnt_index++,partitionHdr++,auth_cert++) { if ((*partitionHdr)->authCertificateOffset != 0) { Separator(); std::cout << "Verifying Partition " << (*iH)->imageName << "." << std::dec << cnt_index << std::endl; bool isItBootloader = ((*partitionHdr)->partitionWordOffset) * 4 == bH->sourceOffset ? 1 : 0; if (isItBootloader) { uint32_t bHLength = sizeof(VersalBootHeaderStructure) - sizeof(VersalSmapWidthTable); uint8_t* tempBHBuffer = new uint8_t[bHLength]; offset = sizeof(VersalSmapWidthTable); if (!(fseek(binFile, offset, SEEK_SET))) { size_t result = fread(tempBHBuffer, 1, bHLength, binFile); if (result != bHLength) { LOG_ERROR("Error reading boot header while verifying "); } } else { LOG_ERROR("Error parsing Boot Header from BootImage file %s", binFilename.c_str()); } if ((*(*auth_cert) & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(false,tempBHBuffer,bHLength, (ACKeyECDSA *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_BH_SIGN_OFFSET); } else if ((*(*auth_cert) & 0xF3) == 0x22) { LOG_ERROR("Authentication verification of BootHeader cannot be done with ECDSA-P521 algorithm"); } else if ((*(*auth_cert) & 0xF3) == 0x11) { signatureVerified = VerifySignature(false, tempBHBuffer, bHLength, (ACKey4096Sha3Padding *)(*auth_cert + AC_SPK_KEY_OFFSET),*auth_cert +AC_BH_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } if (signatureVerified) { LOG_MSG(" BootHeader Signature Verified"); } else { LOG_MSG(" BootHeader Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBHBuffer; } /* Verifying Partition SPK Signature */ VerifySPKSignature(*auth_cert); uint32_t actualSecureChunkSize = SECURE_32K_CHUNK - SHA3_LENGTH_BYTES; if(versalNetSeries && isItBootloader) actualSecureChunkSize = SECURE_16K_CHUNK - SHA3_LENGTH_BYTES; bool nist = true; /* Partition Signature should not be included for hash calculation. */ uint32_t encryptedSize = ((*partitionHdr)->encryptedPartitionLength * 4); if (isItBootloader && versalNetSeries) { encryptedSize = bH->plmLength; } uint32_t dataBufferLength = ((*partitionHdr)->totalPartitionLength * 4) - SIGN_LENGTH_VERSAL; uint32_t acBufferLength = sizeof(AuthCertificate4096Sha3PaddingStructure) - SIGN_LENGTH_VERSAL; uint8_t* tempBuffer = new uint8_t[dataBufferLength]; memset(tempBuffer, 0, dataBufferLength); offset = (*partitionHdr)->authCertificateOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, acBufferLength, binFile); if (result != acBufferLength) { LOG_ERROR("Error reading partition for hash calculation"); } } else { LOG_ERROR("Error parsing Partitions from BootImage file %s", binFilename.c_str()); } offset = (*partitionHdr)->partitionWordOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer + acBufferLength, 1, dataBufferLength - acBufferLength, binFile); if (result != dataBufferLength - acBufferLength) { LOG_ERROR("Error reading partition for hash calculation"); } } else { LOG_ERROR("Error parsing Partitions from BootImage file %s", binFilename.c_str()); } if (encryptedSize <= actualSecureChunkSize || (isItBootloader && !versalNetSeries)) { if (isItBootloader) { nist = false; } if ((*(*auth_cert) & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(nist, tempBuffer, dataBufferLength, (ACKeyECDSA *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_PARTITION_SIGN_OFFSET); } else if ((*(*auth_cert) & 0xF3) == 0x22) { signatureVerified = VerifyECDSAP521Signature(nist, tempBuffer, dataBufferLength, (ACKeyECDSAP521 *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_PARTITION_SIGN_OFFSET); } else if ((*(*auth_cert) & 0xF3) == 0x11) { signatureVerified = VerifySignature(nist, tempBuffer, dataBufferLength, (ACKey4096Sha3Padding *)(*auth_cert + AC_SPK_KEY_OFFSET), *auth_cert + AC_PARTITION_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } } else { uint32_t chunk0Size = acBufferLength + actualSecureChunkSize + SHA3_LENGTH_BYTES; if ((*partitionHdr)->partitionKeySource != KeySource::None) { chunk0Size += SECURE_HDR_SZ + AES_GCM_TAG_SZ; } /* Verify Signature */ if ((*(*auth_cert) & 0xF3) == 0x02) { signatureVerified = VerifyECDSASignature(true, tempBuffer, chunk0Size, (ACKeyECDSA *)(*auth_cert + AC_SPK_KEY_OFFSET),*auth_cert + AC_PARTITION_SIGN_OFFSET); } else if ((*(*auth_cert) & 0xF3) == 0x22) { signatureVerified = VerifyECDSAP521Signature(true, tempBuffer, chunk0Size, (ACKeyECDSAP521 *)(*auth_cert + AC_SPK_KEY_OFFSET),*auth_cert + AC_PARTITION_SIGN_OFFSET); } else if ((*(*auth_cert) & 0xF3) == 0x11) { signatureVerified = VerifySignature(true, tempBuffer, chunk0Size, (ACKey4096Sha3Padding *)(*auth_cert + AC_SPK_KEY_OFFSET),*auth_cert + AC_PARTITION_SIGN_OFFSET); } else { LOG_ERROR("Invalid Authentication Algorithm"); } if (signatureVerified) { uint32_t dataSize = actualSecureChunkSize + SHA3_LENGTH_BYTES; uint8_t* hashBuffer = new uint8_t[SHA3_LENGTH_BYTES]; if ((*partitionHdr)->partitionKeySource != KeySource::None) { encryptedSize -= (SECURE_HDR_SZ + AES_GCM_TAG_SZ); } int count = (encryptedSize / actualSecureChunkSize); if (encryptedSize % actualSecureChunkSize != 0) { count = count + 1; } for (int i = 1;i < count; i++) { uint32_t lastChunkSize = encryptedSize - ((count - 1) * actualSecureChunkSize); if(i == count - 1) { dataSize = lastChunkSize; } uint8_t* dataBuffer = new uint8_t[dataSize]; memcpy(hashBuffer, tempBuffer + chunk0Size - SHA3_LENGTH_BYTES + (actualSecureChunkSize + SHA3_LENGTH_BYTES) * (i-1), SHA3_LENGTH_BYTES); memcpy(dataBuffer, tempBuffer + chunk0Size + (actualSecureChunkSize + SHA3_LENGTH_BYTES) * (i-1), dataSize); uint8_t* shaHash = new uint8_t[SHA3_LENGTH_BYTES]; Versalcrypto_hash(shaHash, dataBuffer, dataSize, true); int compare = memcmp(shaHash, hashBuffer, SHA3_LENGTH_BYTES); delete[] shaHash; if (compare != 0) { LOG_ERROR(" Partition Verification Failed at Chunk %d", i); } delete[] dataBuffer; } delete[] hashBuffer; } } if (signatureVerified) { LOG_MSG(" Partition Signature Verified"); } else { LOG_MSG(" Partition Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBuffer; } else { //EXIT } } } fclose(binFile); Separator(); } xilinx-bootgen-2024.2/verifyimage-zynqmp.cpp000077500000000000000000000345431475706442400211510ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /* ------------------------------------------------------------------------------- *********************************************** H E A D E R F I L E S *** ------------------------------------------------------------------------------- */ #include "readimage-zynqmp.h" #include "authkeys.h" #include "Keccak-compact.h" #define BITSTREAM_AUTH_CHUNK_SIZE 0x800000 //8MB = 8*1024*1024 /*******************************************************************************/ static void RearrangeEndianess(uint8_t *array, uint32_t size) { uint32_t lastIndex = size - 1; char tempInt = 0; // If array is NULL, return if (!array) { return; } for (uint32_t loop = 0; loop <= (lastIndex / 2); loop++) { tempInt = array[loop]; array[loop] = array[lastIndex - loop]; array[lastIndex - loop] = tempInt; } } /*******************************************************************************/ void ZynqMpReadImage::VerifyAuthentication(bool verifyImageOption) { ReadBinaryFile(); if (iHT->headerAuthCertificateWordOffset != 0) { VerifyHeaderTableSignature(); } else { LOG_ERROR("Bootimage %s is not authenticated. Authentication verification cannot be done on this image.", binFilename.c_str()); } VerifyPartitionSignature(); if (authenticationVerified) { LOG_MSG("Authentication is verified on bootimage %s", binFilename.c_str()); } else { LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } } /*******************************************************************************/ bool ZynqMpReadImage::VerifySignature(bool nist, uint8_t * data, size_t dataLength, ACKey4096* acKey, uint8_t * signature) { /* Find SHA-384 hash from data */ uint8_t hashLength = SHA3_LENGTH_BYTES; uint8_t* shaHash = new uint8_t[hashLength]; if (nist) { crypto_hash_NIST_SHA3(shaHash, data, dataLength); } else { crypto_hash(shaHash, data, dataLength); } LOG_TRACE("Hash from data"); LOG_DUMP_BYTES(shaHash, hashLength); rsa = RSA_new(); BIGNUM* n = BN_new(); n->d = (BN_ULONG*)acKey->N; n->dmax = RSA_4096_KEY_LENGTH / sizeof(BN_ULONG); n->top = RSA_4096_KEY_LENGTH / sizeof(BN_ULONG); n->flags = 0; n->neg = 0; BIGNUM* e = BN_new(); e->d = (BN_ULONG*)acKey->E; e->dmax = 1; e->top = 1; e->flags = 0; e->neg = 0; #if OPENSSL_VERSION_NUMBER > 0x10100000L BIGNUM *d = NULL; RSA_set0_key(rsa, n, e, d); RearrangeEndianess((uint8_t*)RSA_get0_e(rsa)->d, sizeof(uint32_t)); RearrangeEndianess((uint8_t*)RSA_get0_n(rsa)->d, RSA_4096_KEY_LENGTH); #else rsa->n = n; rsa->e = e; RearrangeEndianess((uint8_t*)rsa->e->d, sizeof(uint32_t)); RearrangeEndianess((uint8_t*)rsa->n->d, RSA_4096_KEY_LENGTH); #endif /* Find SHA-384 hash from signature */ uint8_t* opensslHashPadded = new uint8_t[RSA_4096_KEY_LENGTH]; //chnage key length to signature length if (RSA_public_encrypt(RSA_4096_KEY_LENGTH, signature, (unsigned char*)opensslHashPadded, rsa, RSA_NO_PADDING) < 0) { LOG_ERROR("RSA_public_encrypt error"); } /* comment */ #if OPENSSL_VERSION_NUMBER > 0x10100000L RearrangeEndianess((uint8_t*)RSA_get0_n(rsa)->d, RSA_4096_KEY_LENGTH); RearrangeEndianess((uint8_t*)RSA_get0_e(rsa)->d, sizeof(uint32_t)); #else RearrangeEndianess((uint8_t*)rsa->n->d, RSA_4096_KEY_LENGTH); RearrangeEndianess((uint8_t*)rsa->e->d, sizeof(uint32_t)); #endif uint8_t* opensslHash = new uint8_t[hashLength]; memcpy(opensslHash,opensslHashPadded + RSA_4096_KEY_LENGTH - hashLength, hashLength); LOG_TRACE("Hash from signature"); LOG_DUMP_BYTES(opensslHash, hashLength); /* compare openssl Hash with calculated shaHash */ if (memcmp(shaHash, opensslHash, hashLength) == 0) { delete[] shaHash; delete[] opensslHash; delete[] opensslHashPadded; return true; } else { delete[] shaHash; delete[] opensslHash; delete[] opensslHashPadded; return false; } } /*******************************************************************************/ void ZynqMpReadImage::VerifyHeaderTableSignature() { Separator(); LOG_MSG("Verifying Header Authentication Certificate"); uint64_t offset = 0; size_t result; FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); AuthCertificate4096Structure* auth_cert = (AuthCertificate4096Structure*)(aCs.front()); /* Verifying Header SPK Signature */ VerifySPKSignature(auth_cert); /* Partition Signature should not be included for hash calculation. */ size_t headersSize = bH->sourceOffset - bH->imageHeaderByteOffset - RSA_4096_KEY_LENGTH; if(bH->sourceOffset == 0) { headersSize = (pHT->partitionWordOffset * 4) - bH->imageHeaderByteOffset - RSA_4096_KEY_LENGTH; } uint8_t* tempBuffer = new uint8_t[headersSize]; memset(tempBuffer, 0, headersSize); offset = bH->imageHeaderByteOffset; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, headersSize, binFile); if (result != headersSize) { LOG_ERROR("Error reading signature"); } } else { LOG_ERROR("Error parsing Headers from BootImage file %s", binFilename.c_str()); } bool signatureVerified = VerifySignature(true, tempBuffer, headersSize, &auth_cert->acSpk, (unsigned char*)(&auth_cert->acPartitionSignature)); if (signatureVerified) { LOG_MSG(" Header Signature Verified"); } else { LOG_MSG(" Header Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } fclose(binFile); delete[] tempBuffer; } /*******************************************************************************/ void ZynqMpReadImage::VerifySPKSignature(AuthCertificate4096Structure* auth_cert) { bool nist = false; size_t size = 0; ACKey4096 key; if (auth_cert->acHeader & 0x80000) { nist = true; } // Hash of SPK - AH + SPK ID + SPK FULL + Padding size = sizeof(auth_cert->acHeader) + sizeof(auth_cert->spkId) + sizeof(key.N) + sizeof(key.N_extension) + sizeof(key.E) + sizeof(key.Padding); uint8_t* tempBuffer = new uint8_t[size]; WriteLittleEndian32(tempBuffer, auth_cert->acHeader); WriteLittleEndian32(tempBuffer + sizeof(auth_cert->acHeader), auth_cert->spkId); memcpy(tempBuffer + sizeof(auth_cert->acHeader) + sizeof(auth_cert->spkId), auth_cert->acSpk.N, sizeof(key.N)); memcpy(tempBuffer + sizeof(auth_cert->acHeader) + sizeof(auth_cert->spkId) + sizeof(key.N), auth_cert->acSpk.N_extension, sizeof(key.N_extension)); memcpy(tempBuffer + sizeof(auth_cert->acHeader) + sizeof(auth_cert->spkId) + sizeof(key.N) + sizeof(key.N_extension), auth_cert->acSpk.E, sizeof(key.E)); memcpy(tempBuffer + sizeof(auth_cert->acHeader) + sizeof(auth_cert->spkId) + sizeof(key.N) + sizeof(key.N_extension) + sizeof(key.E), auth_cert->acSpk.Padding, sizeof(key.Padding)); bool signatureVerified = VerifySignature(nist, tempBuffer, size, &auth_cert->acPpk, (unsigned char*)(&auth_cert->acSpkSignature)); if (signatureVerified) { LOG_MSG(" SPK Signature Verified"); } else { LOG_MSG(" SPK Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBuffer; } /*******************************************************************************/ void ZynqMpReadImage::VerifyPartitionSignature(void) { size_t result; uint64_t offset = 0; std::list::iterator authCertificate = aCs.begin(); authCertificate++; FILE *binFile; binFile = fopen(binFilename.c_str(), "rb"); /* Partition Extraction */ std::list::iterator partitionName = pHTNames.begin(); for (std::list::iterator partitionHdr = pHTs.begin(); partitionHdr != pHTs.end(); partitionHdr++, authCertificate++, partitionName++) { if ((*partitionHdr)->authCertificateOffset != 0) { Separator(); LOG_MSG("Verifying Partition '%s' Authentication Certificate", (*partitionName).c_str()); AuthCertificate4096Structure* auth_cert = (AuthCertificate4096Structure*)(*authCertificate); bool checkLoadAddrInBhAndPht = ((*partitionHdr)->destinationExecAddress == bH->fsblExecAddress); bool isItBootloader = (checkLoadAddrInBhAndPht && (bH->sourceOffset != 0)); if (isItBootloader) { uint32_t bHLength = sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable); if (bH->fsblAttributes & 0xC0) { bHLength += PUF_DATA_LENGTH; } uint8_t* tempBHBuffer = new uint8_t[bHLength]; size_t result = fread(tempBHBuffer, 1, bHLength, binFile); if (result != bHLength) { LOG_ERROR("Error reading boot header while verifying "); } bool signatureVerified = VerifySignature(false, tempBHBuffer, bHLength, &auth_cert->acSpk, (unsigned char*)(&auth_cert->acBhSignature)); if (signatureVerified) { LOG_MSG(" BootHeader Signature Verified"); } else { LOG_MSG(" BootHeader Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBHBuffer; } /* Verifying Partition SPK Signature */ VerifySPKSignature(auth_cert); /* Partition Signature should not be included for hash calculation. */ uint32_t bufferLength = ((*partitionHdr)->totalPartitionLength * 4) - RSA_4096_KEY_LENGTH; bool signatureVerified = false; if (((((*partitionHdr)->partitionAttributes) >> PH_DEST_DEVICE_SHIFT_ZYNQMP) & PH_DEST_DEVICE_MASK_ZYNQMP) == 2) { bufferLength = ((*partitionHdr)->totalPartitionLength * 4); } uint8_t* tempBuffer = new uint8_t[bufferLength]; memset(tempBuffer, 0, bufferLength); offset = (*partitionHdr)->partitionWordOffset * 4; if (!(fseek(binFile, offset, SEEK_SET))) { result = fread(tempBuffer, 1, bufferLength, binFile); if (result != bufferLength) { LOG_ERROR("Error reading partition for hash calculation"); } } else { LOG_ERROR("Error parsing Partitions from BootImage file %s",binFilename.c_str()); } if (((((*partitionHdr)->partitionAttributes) >> PH_DEST_DEVICE_SHIFT_ZYNQMP) & PH_DEST_DEVICE_MASK_ZYNQMP) == 2) { uint32_t blockSize = BITSTREAM_AUTH_CHUNK_SIZE; uint32_t lastBlockSize = ((*partitionHdr)->totalPartitionLength * 4) - (sizeof(AuthCertificate4096Structure) * plAcCount) - (BITSTREAM_AUTH_CHUNK_SIZE * (plAcCount - 1)); for(int i = 0; iacSpk, (unsigned char*)(&cert->acPartitionSignature)); if(!signatureVerified) { LOG_MSG(" Partition Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] buffer; } } else { signatureVerified = VerifySignature(!isItBootloader, tempBuffer, bufferLength, &auth_cert->acSpk, (unsigned char*)(&auth_cert->acPartitionSignature)); } if (signatureVerified) { LOG_MSG(" Partition Signature Verified"); } else { LOG_MSG(" Partition Signature Verification Failed"); authenticationVerified = false; LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); } delete[] tempBuffer; } else { //EXIT } } fclose(binFile); Separator(); } xilinx-bootgen-2024.2/version.h000077500000000000000000000305631475706442400164360ustar00rootroot00000000000000/****************************************************************************** * Copyright 2015-2022 Xilinx, Inc. * Copyright 2022-2023 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #ifndef RDI_VERSION #define RDI_VERSION "2024.2" #endif #define PROGRAMNAME "Bootgen" #define COPYRIGHT "Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.\n" /****************************************************************************** help ******************************************************************************/ #define HELP "\ ------------------------------------------------------------------------------+\n\ COMMAND LINE OPTIONS |\n\ ------------------------------------------------------------------------------+\n\ arch - Device Architecture |\n\ bif_help - Print the BIF help summary |\n\ dual_ospi_mode - Generate 2 output files for Dual OSPI |\n\ dual_qspi_mode - Generate 2 output files for Dual QSPI |\n\ dump - Dumps components from PDI as bin files |\n\ dump_dir - Dumps components in specified directory |\n\ efuseppkbits - Generate PPK hash for e-fuse |\n\ encrypt - AES Key storage on device |\n\ encryption_dump - Generate encryption log file |\n\ fill - Fill byte for padding |\n\ generate_hashes - Generate SHA hashes (PKCS#1v1.5) |\n\ generate_keys - Generate authentication keys |\n\ help - Print the help summary |\n\ image - Input Boot Image File (.bif) |\n\ log - Generate log file |\n\ nonbooting - Generate an intermediate boot image |\n\ o - Output filename in MCS/BIN format |\n\ overlay_cdo - Overlay CDO files of Boot Image File |\n\ p - Part name for generating nky file |\n\ padimageheader - Pad header tables |\n\ process_bitstream - Outputs bitstream in bin/mcs format |\n\ read - Dumps the header tables in human readable form |\n\ authenticatedjtag - Generate a Image to authenticate PSK and enable jtag |\n\ split - Split partitions to diff files |\n\ spksignature - Generate SPK signature file |\n\ verify - Verify BootImage authentication |\n\ verify_kdf - Verify AES key generation |\n\ w - Overwrite mode |\n\ zynqmpes1 - Generate boot image for ZynqMP ES1 |\n\ enable_auth_opt - Enables authentication optimization |\n\ ------------------------------------------------------------------------------+\n\ Note : Some options are valid only for specific architectures. |\n\ Help for such options include a list of supported architectures. |\n\ If an option is supported for all architectures, this list is not |\n\ included in help |\n\ Example : Supported architectures : zynqmp, versal |\n\ ------------------------------------------------------------------------------+\n\ For more information on bootgen options, use the command |\n\ bootgen -help