# HG changeset patch # User Mychaela Falconia # Date 1582954567 0 # Node ID 9cecc930d78f6e8324c055cb8b649eee67319a89 # Parent ae39d76d5b7a37010a84267b4862e7c2041eb8f0 fluid-mnf: original source from TI, defenestrated line endings and rearranged directory structure, but no *.[ch] source file content changes yet diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/README Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,11 @@ +In the summer of 2019 we (FreeCalypso) had recovered a copy of TI's original +FLUID package including source, but this TI original FLUID source targets only +Windows, no Unix or Linux support included. Back in 2007 or earlier Openmoko +had made their own port of FLUID to Linux and we have their Linux/ARM binary, +but the source for that Linux port appears to have been lost. + +This directory contains what is going to be my (Mother Mychaela's) attempt to +do my own port of FLUID to Unix/Linux; I am starting by checking in TI's +original source with defenestrated line endings. I am also changing the +directory structure a little bit, and I have checked the files in according to +what will be my new directory structure. diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/calplus/ram_load.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/calplus/ram_load.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,299 @@ +/* %Z% nom : %M% SID: %I% date : %G% */ +/* Filename: %M% */ +/* Version: %I% */ +/****************************************************************************** + * WIRELESS COMMUNICATION SYSTEM DEVELOPMENT + * + * (C) 2002 Texas Instruments France. All rights reserved + * + * Author : Francois AMAND + * + * + * Important Note + * -------------- + * + * This S/W is a preliminary version. It contains information on a product + * under development and is issued for evaluation purposes only. Features + * characteristics, data and other information are subject to change. + * + * The S/W is furnished under Non Disclosure Agreement and may be used or + * copied only in accordance with the terms of the agreement. It is an offence + * to copy the software in any way except as specifically set out in the + * agreement. No part of this document may be reproduced or transmitted in any + * form or by any means, electronic or mechanical, including photocopying and + * recording, for any purpose without the express written permission of Texas + * Instruments Inc. + * + ****************************************************************************** + * + * FILE NAME: ram_load.c + * + * + * PURPOSE: Describe the RAM loader state machine used during boot procedure + * in order to download a FLASH programmer into the Internal RAM if + * CALYPSOPLUS chip. + * + * + * + * FILE REFERENCES: + * + * Name IO Description + * ------------- -- --------------------------------------------- + * + * + * + * EXTERNAL VARIABLES: + * + * Source: + * + * Name Type IO Description + * ------------------- --------------- -- ---------------------------- + * + * + * EXTERNAL REFERENCES: + * + * Name Description + * ------------------ ------------------------------------------------------- + * + * + * + * ABNORMAL TERMINATION CONDITIONS, ERROR AND WARNING MESSAGES: + * + * + * + * ASSUMPTION, CONSTRAINTS, RESTRICTIONS: + * + * + * + * NOTES: + * + * + * + * REQUIREMENTS/FUNCTIONAL SPECIFICATION REFERENCES: + * + * + * + * + * DEVELOPMENT HISTORY: + * + * Date Name(s) Version Description + * ---------- -------------- ------- -------------------------------------- + * 31-May-02 Francois AMAND V1.0.0 Import from CALYPSO + * + * ALGORITHM: Use the RAM loader state machine defined in CALPLUS208 specifica- + * tion. + * + * + *****************************************************************************/ + + +#ifndef _RAM_LOADER_H_ + #define _RAM_LOADER_H_ + + /* + * Include files + */ + #include "standard.h" + #include "secure_types.h" + + #define C_MAX_PLATFORM_DATA 64192 + + /* + * Main buffer size + */ + // Include manufacture certificate + platform data + manufacturer certificate signature + #define C_MAX_BUFFER_SIZE (sizeof(T_MANUFACTURER_CERTIFICATE) + C_MAX_PLATFORM_DATA + C_MANUF_SIG_SIZE * C_WORD32LGB) + + /* + * Serial interface choice + */ + enum { + #ifdef _SERIAL_IRDA_ + C_SERIAL_ID_MODEM = 0, + C_SERIAL_ID_IRDA = 1 + #else + C_SERIAL_ID_MODEM = 0 + #endif + }; + + + /* + * RAM loader state + */ + typedef enum { + C_RESET_STATE = 0, + C_SIGNALLING_STATE = 1, + C_AWAIT_PARAMETER_STATE = 2, + C_COMMAND_PHASE_STATE = 3 + } T_RAM_LOADER_PC_STATE; + + + /* + * RAM loader event + */ + typedef enum { + C_NO_EVENT = 0, + + C_USER_DOWNLOAD_REQUEST = 1, + C_USER_ABORT_REQUEST = 2, + + C_SIGNALLING_TIMEOUT = 3, + C_WATCHDOG_TIMEOUT = 4, + + C_SIGNALLING_RESPONSE = 5, + C_PARAMETER_ACK_RESPONSE = 6, + C_PARAMETER_NACK_RESPONSE = 7, + C_WRITE_ACK_RESPONSE = 8, + C_WRITE_NACK_RESPONSE = 9, + C_CERTIFICATE_ACK_RESPONSE = 10 + } T_RAM_LOADER_PC_EVENT; + + + /* + * RAM loader command + */ + typedef enum { + C_SIGNALLING_REQUEST_CMD = 0, + C_PARAMETER_REQUEST_CMD = 1, + C_WRITE_REQUEST_CMD = 2, + C_ABORT_REQUEST_CMD = 3, + C_CERTIFICATE_REQUEST_CMD = 4 + } T_RAM_LOADER_PC_COMMAND; + + + /* + * RAM loader timer + */ + typedef enum { + C_SIGNALLING_TIMER = 0, + C_WATCHDOG_TIMER = 1 + } T_RAM_LOADER_PC_TIMER; + + #define C_RAM_LOADER_PC_NB_TIMER 2 + + + /* + * Timeout definition in ms + */ + #define C_SIGNALLING_TIMEOUT_VALUE 4L /* 2 ms */ + #define C_WATCHDOG_TIMEOUT_VALUE 120000L /* 2 mn */ + + + /* + * RAM loader status + */ + typedef enum { + C_NO_STATUS = 0, + C_BAD_INPUT_FILE = 1, + C_SUCCESS = 2, + C_BAD_PARAMETERS = 3, + C_ERROR_DURING_WRITE = 4, + C_BAD_ADDRESS_OF_BRANCH = 5, + C_WATCHDOG_TIMER_REACHED = 6, + C_USER_ABORT = 7 + } T_RAM_LOADER_PC_STATUS; + + + enum { + C_COMMAND_NOT_RECEIVED = 0, + C_COMMAND_RECEIVED = 1, + C_SERIAL_TIMEOUT = 2 + }; + + typedef struct { + UWORD8 d_nb_data; + UWORD32 d_address; + UWORD8 *p_block; + } T_WRITE_REQUEST; + + + typedef struct { + UWORD16 d_max_byte; + UWORD8 a_data[sizeof(T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER)]; + } T_FRAME; + + + typedef struct { + UWORD8 d_device_id; + UWORD8 d_baud_rate; + char *p_file_name; + + /* + * Signalling response variable + */ + UWORD16 d_romcode_version; + UWORD8 a_hash_man_pub_key[C_MD5HASHLG * C_WORD32LGB]; + UWORD8 a_die_id[C_WORD32LGB * C_DIE_ID_SIZE]; + UWORD8 a_Certsig[C_WORD32LGB * C_MANUF_SIG_SIZE]; + + /* + * Parameter NACK response variable + */ + UWORD8 d_param_req_sts; + + /* + * Certificate request variable + */ + BOOLEAN b_certificate_request; + + /* + * Certificate response variable + */ + union { + UWORD8 a_firm_cert[C_MAX_BUFFER_SIZE]; /* Take into account max data_platform size */ + T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA d_firm_cert; + } u_firm_cert; + + /* + * Command request variable + */ + UWORD32 d_uart_timeout; + union { + UWORD8 a_code_certificate[sizeof(T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER)]; + T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER d_code_certificate; + } u_code_certificate; + + /* + * Write request variable + */ + UWORD32 d_nb_byte_in_block; + UWORD32 d_nb_byte_sent; + UWORD8 *p_block_buffer; + UWORD32 d_block_address; + UWORD32 d_block_size; + + /* + * Mobile received variable + */ + //UWORD16 d_max_block_size; + //UWORD16 d_mobile_buffer_size; + UWORD8 d_write_status; + + //T_WRITE_REQUEST d_parameter_request; + } T_RAM_LOADER; + + + /* + * RAM loader baud rate definition + */ + typedef enum { + C_BAUD_RATE_812500 = 0, + C_BAUD_RATE_406250 = 1, + C_BAUD_RATE_203125 = 2, + C_BAUD_RATE_115200 = 3, + C_BAUD_RATE_57600 = 4, + C_BAUD_RATE_38400 = 5, + C_BAUD_RATE_28800 = 6, + C_BAUD_RATE_19200 = 7, + C_BAUD_RATE_DEFAULT = 7, + C_BAUD_RATE_9600 = 8 + } T_BAUD_RATE; + + + #define C_BLOCK_INDEX_OFFSET 0 + #define C_NB_BLOCK_OFFSET 1 + #define C_BLOCK_SIZE_OFFSET 2 + #define C_BLOCK_ADDRESS_OFFSET 4 + #define C_BLOCK_DATA_OFFSET 8 + +#endif diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/calplus/secure_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/calplus/secure_types.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,508 @@ +/* %Z% nom : %M% SID: %I% date : %G% */ +/* Filename: %M% */ +/* Version: %I% */ +/****************************************************************************** + * WIRELESS COMMUNICATION SYSTEM DEVELOPMENT + * + * (C) 2002 Texas Instruments France. All rights reserved + * + * Author : Constantin HAIDAMOUS + * + * + * Important Note + * -------------- + * + * This S/W is a preliminary version. It contains information on a product + * under development and is issued for evaluation purposes only. Features + * characteristics, data and other information are subject to change. + * + * The S/W is furnished under Non Disclosure Agreement and may be used or + * copied only in accordance with the terms of the agreement. It is an offence + * to copy the software in any way except as specifically set out in the + * agreement. No part of this document may be reproduced or transmitted in any + * form or by any means, electronic or mechanical, including photocopying and + * recording, for any purpose without the express written permission of Texas + * Instruments Inc. + * + ****************************************************************************** + * + * FILE NAME: secure_types.h + * + * + * PURPOSE: + * + * + * FILE REFERENCES: + * + * Name IO Description + * ------------- -- --------------------------------------------- + * + * + * + * EXTERNAL VARIABLES: + * + * Source: none + * + * Name Type IO Description + * ------------------- --------------- -- ---------------------------- + * + * + * + * ABNORMAL TERMINATION CONDITIONS, ERROR AND WARNING MESSAGES: + * + * + * + * ASSUMPTION, CONSTRAINTS, RESTRICTIONS: + * + * + * + * NOTES: + * + * + * + * REQUIREMENTS/FUNCTIONAL SPECIFICATION REFERENCES: + * + * + * + * + * DEVELOPMENT HISTORY: + * + * Date Name(s) Version Description + * ---------- -------------------- ------- --------------------------------- + * 04/12/2002 Constantin HAIDAMOUS V1.0.0 First release + * 22-Apr-02 Francois AMAND V1.0.1 Update of secure status to + * facilitate integration in final + * ROM code. + * Data alignment in struture to + * optimize memory requirement. + * Management of global secure data. + * 28-Apr-02 Francois AMAND V1.0.2 Update some constants to be + * compliant with certificate + * definition. + * Add CALYPSO PLUS specific + * parameters structure. + * Differentiate Manufacturer and + * Platform certificate. + * Add debug request field in Manu- + * facturer certificate. + * Optimize certificate field size. + * Change commentary wrapper to be + * ANSI compliant. + * 29-Apr-02 Francois AMAND V1.0.3 Remove unused constant. + * Set under compilation flag the + * secure services. + * 14-May-02 Francois AMAND V1.0.4 Add CONF_CSI field in T_CONF_PARAM + * structure definition. + * Change name of CS_MODE to EX_CTRL + * Change size of DCCTRL_CSx to 8 + * bits to optimize size and alignment. + * 17-May-02 Francois AMAND V1.0.5 Modification of hashing size for + * binding/unbinding. + * 17-May-02 Constantin HAIDAMOUS V1.0.6 Integration of data structure for + * binding/unbinding services API . + * 17-May-02 Francois AMAND V1.0.7 Integration of RSA S/W and Check + * ROM in Secure Services. + * Update of Secure Services manage- + * ment. + * 22-May-02 Constantin HAIDAMOUS V1.0.8 Changing RSA modulus length , Max + * RSA length =2048 bits. Adding initial + * vectore for Binding structure. + * 27-May-02 Francois AMAND V1.0.9 Changing SAMSON to CALYPSO. + * Addition of Secure Services for + * RUN Time checker. + * 28-May-02 Constantin HAIDAMOUS V1.0.10 Changing C_PLAT_SIG_SIZE to 4. + * + * 06-June-02 Constantin HAIDAMOUS V1.0.11 Changing Secure service API. + * + * 12-Jun-02 Francois AMAND V1.0.12 Update of T_CONF_PARAM according + * to last memory interface spec. + * 13-Jun-02 Constantin HAIDAMOUS V1.0.13 Update of T_UNBINDCTX for segmented + * unbind operation optimization. + * 14-Jun-02 Constantin HAIDAMOUS V1.0.14 Update of T_BINDCTX for segmented + * bind operation . + * 14-Jun-02 Francois AMAND V1.0.15 Force d_temp in Secure RAM. + * Remove other definitions. + * 25-Jun-02 Francois AMAND V1.0.16 Addition of Platform unbinding + * during boot concept under compi- + * lation flag C_PLATFORM_UNBIND_BOOT. + * 27-Jun-02 Constantin HAIDAMOUS V1.0.17 Adding C_SECURE_RNG_ALARM to E_SECURE_STATUS + * C_SECURE_RNG_ALARM = C_RNG_ALARM from Safenet + * 09-Jul-02 Constantin HAIDAMOUS V1.0.18 Adding Application ID and Timeout for Bind function + * 16-Jul-02 Francois AMAND V1.0.19 Add S/W pseudo-random generator. + * 19-Jul-02 Francois AMAND V1.0.20 Remove S/W pseudo-random. + * 01-Aug-02 Constantin HAIDAMOUS V1.0.21 Removing boolean b_HashDone in Bind and Unbind Context + * 27-Jan-03 Francois AMAND V2.0.0 Remove of C_PLATFORM_UNBIND_BOOT flag + * 27-Jan-03 Francois AMAND V2.0.1 Add compliance with SW@P 2.0 (REQ03047) + * 20-Mar-03 Francois AMAND V2.0.2 Code cleaning + * + * ALGORITHM: + * + * + *******************************************************************************/ + + +#include "standard.h" + +#ifndef _SECURE_TYPES_H + #define _SECURE_TYPES_H + + #ifndef C_SECURE_SERVICES + #define C_SECURE_SERVICES 1 + #endif + + #ifndef C_CHIPSET + #define C_CHIPSET_CALYPSO 4 + #define C_CHIPSET_CALYPSOPLUS 11 + #define C_CHIPSET C_CHIPSET_CALYPSOPLUS + #endif + + + + /**************************************************************************** + * Constants + ****************************************************************************/ + + #define C_WORD32LGB 4 + +// #ifndef NULL /* To avoid conflict with other compilers */ +// #define NULL (UWORD32 *) 0x00000000L +// #endif + + /* Certificate block */ + + /* Length in long word (32 bits) */ + + #define C_SHA1HASHLG 5 + #define C_MD5HASHLG 4 + + #define C_RSAKEYLG 64 /* Max Modulus size : 2048 bits */ + #define C_RSASIGLG C_RSAKEYLG + + #define C_DIE_ID_SIZE 2 /* DIE ID defined on 64-bits */ + + #define C_PLATFORM_DATA_SIZE 16048 /* Maximum value to have CertSize coded on 16-bits */ + + #if C_SECURE_SERVICES == 1 + #define C_IVLG 2 + #define C_TDESKEYLG 4 + #define C_TDESKEYLGB C_TDESKEYLG * C_WORD32LGB + #define C_PLAT_SIG_SIZE 4 /* Must be a multiple of 64 bits */ + #endif + + #define C_MANUF_SIG_SIZE C_RSASIGLG + + + /* Certificate Type */ + + #define C_CERTTYPE_MAN 0x00 + #define C_CERTTYPE_PLAT 0x01 + + #if C_SECURE_SERVICES == 1 + /* Confidentiality request */ + + #define C_CRYPTVOID 0x00 + #define C_CRYPTNOREQUEST 0x00 + #define C_CRYPTREQUEST 0x01 + #endif + + + /* Debug request */ + + #define C_DEBUGNOREQUEST 0x00 + #define C_DEBUGREQUEST 0x01 + + + /* CS image check request */ + + #define C_CSIMGNOREQUEST 0x00 + #define C_CSIMGREQUEST 0x01 + + + /* Temporary block */ + + #define C_TEMPDATALG 32 + #define C_TEMPDATALGB C_TEMPDATALG * C_WORD32LGB + + #define C_CERT_TEMP_SWKEY 0 + #define C_CERT_TEMP_DATA C_CERT_TEMP_SWKEY + C_TDESKEYLG + + + /**************************************************************************** + * Structures + ****************************************************************************/ + + /* CALYPSO PLUS Parameters */ + typedef struct { + /* External Memory Interface configuration */ + UWORD16 d_conf_cs5; + UWORD16 d_exws_cs5; + UWORD16 d_ex_ctrl; + + /* Authentication configuration */ + UWORD16 d_cs_img_req; + UWORD32 d_flash_size; + UWORD32 d_granularity; + } T_CONF_PARAM; + + + /* RSA Public key */ + + typedef struct + { + UWORD32 a_Modulus[C_RSAKEYLG]; /* Public Modulus */ + UWORD32 d_ModulusLength; /* Public Modulus length in bytes */ + UWORD32 d_Exponent; /* Public Exponent */ + } T_RSAPUBKEY; + + + /*Certificate Structure*/ + + typedef struct + { + UWORD16 d_Certsize; /* Size of Certificate */ + UWORD8 d_Certtype; /* Type of Certificate */ + UWORD8 d_Debugrequest; /* Debug Request */ + UWORD32 d_Addcode; /* Start Address of Code */ + UWORD32 d_Codesize; /* Size of Code */ + UWORD32 d_CodeStartAdd; /* Entry Point Address */ + T_RSAPUBKEY d_Manpubkey; /* Manufacturer Public Key */ + T_RSAPUBKEY d_Origpubkey; /* Originator Public Key */ + UWORD32 a_Origpubkeysig[C_MANUF_SIG_SIZE]; /* Originator Public Key Signature */ + UWORD32 a_Swsig[C_MANUF_SIG_SIZE]; /* Software Signature */ + T_CONF_PARAM d_Confparam; /* Configuration Parameters */ + UWORD32 a_die_id[C_DIE_ID_SIZE]; /* Die Id */ + } T_MANUFACTURER_CERTIFICATE; + + + /* + * Manufacturer Certificate structure containing dynamic Platform Data + */ + typedef struct + { + T_MANUFACTURER_CERTIFICATE d_manufacturer_certificate; + UWORD32 a_platform_data[C_PLATFORM_DATA_SIZE]; /* Platform Data */ + UWORD32 a_Certsig[C_MANUF_SIG_SIZE]; /* Certificate Signature */ + } T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA; + + + /* + * Manufacturer Certificate structure for the flash programmer without the dynamic Platform Data + */ + typedef struct + { + UWORD16 d_Certsize; /* Size of Certificate */ + UWORD8 d_Certtype; /* Type of Certificate */ + UWORD8 d_Debugrequest; /* Debug Request */ + UWORD32 d_Addcode; /* Start Address of Code */ + UWORD32 d_Codesize; /* Size of Code */ + UWORD32 d_CodeStartAdd; /* Entry Point Address */ + T_RSAPUBKEY d_Manpubkey; /* Manufacturer Public Key */ + T_RSAPUBKEY d_Origpubkey; /* Originator Public Key */ + UWORD32 a_Origpubkeysig[C_MANUF_SIG_SIZE]; /* Originator Public Key Signature */ + UWORD32 a_Swsig[C_MANUF_SIG_SIZE]; /* Software Signature */ + T_CONF_PARAM d_Confparam; /* Configuration Parameters */ + UWORD32 a_die_id[C_DIE_ID_SIZE]; /* Die Id */ + UWORD32 a_Certsig[C_MANUF_SIG_SIZE]; /* Certificate Signature */ + } T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER; + + + #if C_SECURE_SERVICES == 1 + /* + * Define ROM secure service entry point address + */ + #define C_ROM_SSERVICE_ENTRY_POINT_ADDR 0x00000024L + + /* + * Definition of function pointer to use ROM Secure Services + */ + typedef UWORD16 (*T_ROM_SSERVICE) (UWORD16, void *, void *); + + + typedef struct + { + UWORD16 d_Certsize; /* Size of Certificate */ + UWORD8 d_Certtype; /* Type of Certificate */ + UWORD8 d_Confrequest; /* Confidentiality Request */ + UWORD32 d_Addcode; /* Start Address of Code */ + UWORD32 d_Codesize; /* Size of Code */ + UWORD32 d_AppID; /* Application Id */ + UWORD32 a_iv[C_IVLG]; /* Initial Vector for TDES CBC */ + UWORD32 a_Encswkey[C_TDESKEYLG]; /* Encrypted S/W Key */ + UWORD32 a_Swsig[C_PLAT_SIG_SIZE]; /* Software Signature */ + UWORD32 a_Certsig[C_PLAT_SIG_SIZE]; /* Certificate Signature */ + } T_PLATFORM_CERTIFICATE; + + + /* Unbind Context Structure used for segmented Unbind operation */ + + typedef struct + { + UWORD32 d_Startpos; /* Start Position of Data to Process */ + UWORD32 d_Currentpos; /* Current Position of Data to Process */ + UWORD32 a_Currentdigest[C_MD5HASHLG]; /* Current Digest */ + UWORD32 d_Digcount; /* Digest Count */ + UWORD32 a_Currentiv[C_IVLG]; /* Current Initial Vector */ + UWORD32 a_Encswkey[C_TDESKEYLG]; /* Encrypted TDES Software Key */ + UWORD32 a_iv[C_IVLG]; /* Initial Vector */ + UWORD32 d_Codesize; /* Code Size */ + UWORD32 d_AppID; /* Application Id */ + UWORD32 a_Swsig[C_PLAT_SIG_SIZE]; /* Software Signature */ + UWORD8 d_Confrequest; /* Confidentiality Request */ + BOOLEAN b_UnbindDone; /* Set to 1 if Data Unbinding is Done */ + } T_UNBINDCTX; + + + /* Bind Context Structure used for segmented Bind operation */ + + typedef struct + { + UWORD32 d_Startpos; /* Start Position of Data to Process */ + UWORD32 d_Currentpos; /* Current Position of Data to Process */ + UWORD32 a_Currentdigest[C_MD5HASHLG]; /* Current Digest */ + UWORD32 d_Digcount; /* Digest Count */ + UWORD32 a_Currentiv[C_IVLG]; /* Current Initial Vector */ + UWORD32 a_Encswkey[C_TDESKEYLG]; /* Encrypted TDES Software Key */ + UWORD32 a_iv[C_IVLG]; /* Initial Vector */ + UWORD32 d_Addcode; /* Store Address of Code */ + UWORD32 d_Codesize; /* Code Size */ + UWORD32 d_AppID; /* Application Id */ + UWORD8 d_Confrequest; /* Confidentiality Request */ + BOOLEAN b_KeyCreateDone; /* Set to 1 if TDES Software Key Creation is Done */ + BOOLEAN b_BindDone; /* Set to 1 if Data Binding is Done */ + } T_BINDCTX; + + + typedef struct + { + T_PLATFORM_CERTIFICATE* p_Cert; + UWORD32* p_Code; + T_PLATFORM_CERTIFICATE* p_CertCtx; + T_UNBINDCTX* p_UnbindCtx; + UWORD32 d_Steplength; + BOOLEAN b_start; + } T_SSERVICE_UNBIND; + + + + typedef struct + { + T_PLATFORM_CERTIFICATE* p_Cert; + UWORD32* p_Code; + T_PLATFORM_CERTIFICATE* p_CertCtx; + T_BINDCTX* p_BindCtx; + UWORD32 d_Steplength; + UWORD32 d_timeout; + BOOLEAN b_start; + } T_SSERVICE_BIND; + + + /* + * Structure definition for RSA S/W secure services + */ + typedef struct + { + UWORD32 * p_datain; + UWORD32 * p_dataout; + UWORD32 output_length; + T_RSAPUBKEY * p_rsapubkey; + UWORD32 * p_rsaheap; + } T_SSERVICE_RSA; + + + /* + * Structure definition for Checker ROM secure services + */ + typedef struct + { + UWORD16 d_checksum; + UWORD16 d_rom_id; + } T_SSERVICE_CHECKROM; + + + /* + * Structure definition for Run Time Checker secure services + */ + typedef struct + { + UWORD32 * p_rsaheap; + T_MANUFACTURER_CERTIFICATE * p_certificate; + } T_SSERVICE_RUNTIMECHECKER; + + + /* + * Structure definition for Run Time Platform Data Checker secure services + */ + typedef struct + { + T_PLATFORM_CERTIFICATE* p_Cert; + } T_SSERVICE_RUNTIME_PLAT_CHECKER; + + + #endif /* C_SECURE_SERVICES == 1 */ + + /**************************************************************************** + * Global variables + ****************************************************************************/ + #ifndef SECURE_GLOBAL + #define SECURE_GLOBAL extern + #endif + + #ifdef _TMS470 + #pragma DATA_SECTION(d_temp,".secdata") + #pragma DATA_SECTION(a_hash_certificate,".secdata") + #endif + + SECURE_GLOBAL UWORD32 d_temp[C_TEMPDATALG]; /* Temporary data in Secure RAM */ + SECURE_GLOBAL UWORD32 a_hash_certificate[C_SHA1HASHLG]; /* SHA-1 hashing of Manufacturer Certificate */ + + /**************************************************************************** + * Status + ****************************************************************************/ + + typedef enum + { + C_SECURE_ERROR = 0, + C_SECURE_SUCCESS = 1, + C_SECURE_INVALID_ID = 2, + C_SECURE_RNG_ALARM = 3, + C_SECURE_INVALID_DIE_ID = 4, + C_SECURE_BLANK_DIE_ID = 5 + } E_SECURE_STATUS; + + + /**************************************************************************** + * Function prototype for secure services + ****************************************************************************/ + + #if C_SECURE_SERVICES == 1 + #define C_MAX_DEFINED_ID 6 + #define C_SEC_SERVICE_BINDING_ID 0x0000 + #define C_SEC_SERVICE_UNBINDING_ID 0x0001 + #define C_SEC_SERVICE_RSA_ID 0x0002 + #define C_SEC_SERVICE_CHECKROM_ID 0x0003 + #define C_SEC_SERVICE_RUN_TIME_CHECKER_ID 0x0004 + #define C_SEC_SERVICE_RUN_TIME_PLATFORM_DATA_CHECKER 0x0005 + + E_SECURE_STATUS ROM_Sservice_Unbind(UWORD16 reserved, + T_SSERVICE_UNBIND* p_StructUnbind); + + E_SECURE_STATUS ROM_Sservice_Bind(UWORD16 reserved, + T_SSERVICE_BIND* p_StructBind); + + E_SECURE_STATUS ROM_Sservice_Rsa(UWORD16 reserved, + T_SSERVICE_RSA* p_StructRsa); + + E_SECURE_STATUS ROM_Sservice_CheckRom(UWORD16 reserved, + T_SSERVICE_CHECKROM* p_StructCheckRom); + + E_SECURE_STATUS ROM_Sservice_RunTimeChecker( + UWORD16 reserved, + T_SSERVICE_RUNTIMECHECKER* p_StructRunTimeChecker); + + E_SECURE_STATUS ROM_Sservice_RunTimePlatformDataChecker( + UWORD16 reserved, + T_SSERVICE_RUNTIME_PLAT_CHECKER* p_StructRunTimePlatChecker); + + #endif + +#endif /* _SECURE_TYPES_H */ diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/calplus/standard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/calplus/standard.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,17 @@ +#ifndef _STANDARD_H_ + #define _STANDARD_H_ + + #define _PC_RAM_LOADER_ + + typedef unsigned char UWORD8; + typedef unsigned short int UWORD16; + typedef unsigned long int UWORD32; + + typedef unsigned char BOOLEAN; + + enum { + C_FALSE = 0, + C_TRUE = 1 + }; + +#endif diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/efluid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/efluid.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,62 @@ +/* This file is autogenerated --- do not edit. */ + +#include "fluid.h" + +char *main_strerror(int error) +{ + switch (error) { + case E_OK: return "Ok"; /* 0 */ + case E_DRIVER_INIT: return "Driver failed to initialize"; /* -3 */ + case E_DRIVER_WAIT: return "Driver recv_wait() failed"; /* -4 */ + case E_UART_INIT: return "UART failed to initialize"; /* -5 */ + case E_UART_PARAM: return "UART parameter bad or unsupported"; /* -6 */ + case E_UART_DRV_SEND: return "UART driver transmit error"; /* -7 */ + case E_UART_DRV_RECV: return "UART driver receive error"; /* -8 */ + case E_RECV_TIMEOUT: return "Receive timeout (no target reply)"; /* -10 */ + case E_RECV_ANTITIMEOUT: return "Receive anti-timeout (target replied!?)"; /* -11 */ + case E_SEND_CHECKSUM: return "Transmit checksum error"; /* -12 */ + case E_RECV_CHECKSUM: return "Receive checksum error"; /* -13 */ + case E_PROTO_ERROR: return "Protocol error (bad char from target)"; /* -14 */ + case E_INVALID: return "Invalid command parameter"; /* -15 */ + case E_FIFO_OVERFLOW: return "RX FIFO overflow in target"; /* -16 */ + case E_FLASH_UNKNOWN: return "Flash device unknown"; /* -20 */ + case E_FLASH_TIMEOUT: return "Flash operation timeout"; /* -21 */ + case E_FLASH_VERIFY: return "Flash verify error"; /* -22 */ + case E_FLASH_COMMAND: return "Flash command sequence error"; /* -23 */ + case E_FLASH_VPPRANGE: return "Flash Vpp range error"; /* -24 */ + case E_FLASH_LOCKED: return "Flash block locked error"; /* -25 */ + case E_FLASH_ERROR: return "Flash error (unknown!?)"; /* -26 */ + case E_TARGET_TYPE: return "Target type not detected, unspecified or unknown"; /* -27 */ + case E_TARGET_MEMORY: return "Target out of memory"; /* -28 */ + case E_PARSER_EOF: return "Unexpected end of file"; /* -30 */ + case E_PARSER_KEYWORD: return "Syntax error: keyword expected"; /* -31 */ + case E_PARSER_STRING: return "Syntax error: string expected"; /* -32 */ + case E_PARSER_NUMBER: return "Syntax error: number expected"; /* -33 */ + case E_PARSER_END_BRACE: return "Syntax error: missing end brace"; /* -34 */ + case E_PARSER_SYNTAX: return "Syntax error"; /* -35 */ + case E_PARSER_MEMMAP: return "Undefined flash memmap"; /* -36 */ + case E_PARSER_ALGORITHM: return "Undefined flash algorithm"; /* -37 */ + case E_BOOTLOADER: return "Unsupported bootloader"; /* -40 */ + case E_FILE_OPEN: return "File open error"; /* -50 */ + case E_FILE_CLOSE: return "File close error"; /* -52 */ + case E_FILE_READ: return "File read error"; /* -53 */ + case E_FILE_WRITE: return "File write error"; /* -54 */ + case E_FILE_FORMAT: return "File format/syntax error"; /* -55 */ + case E_FILE_EMPTY: return "File empty or unreadable?"; /* -56 */ + case E_FILE_BUF_SMALL: return "File buffer too small"; /* -57 */ + case E_FILE_INPUT: return "No input file name supplied"; /* -58 */ + case E_FILE_OUTPUT: return "No output file name supplied"; /* -59 */ + case E_ADDR_RANGE: return "Bad address range"; /* -70 */ + case E_ERASE_SPEC: return "Bad erase override specifier"; /* -71 */ + case E_READ_SPEC: return "Bad memory read specifier"; /* -72 */ + case E_WRITE_SPEC: return "Bad memory write specifier"; /* -73 */ + case E_BADARG: return "Bad argument or out of range"; /* -80 */ + case E_ARG_MULTI: return "Multiple ambiguous arguments supplied"; /* -81 */ + case E_ARG_TOOMANY: return "Too many arguments supplied"; /* -82 */ + case E_MEMORY: return "Out of memory"; /* -85 */ + case E_BUFFER: return "Internal (static) buffer too small"; /* -86 */ + case E_ROM_SSERVICE: return "Secure ROM service error"; /* -90 */ + case E_INTERNAL: return "Internal program state error"; /* -99 */ + default: return "unknown error code!"; + } +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/fileio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/fileio.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,592 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * File reading/loading + * + * $Id: fileio.c 1.24 Mon, 28 Apr 2003 08:49:16 +0200 tsj $ + * + ******************************************************************************/ + +#include "fluid.h" +#include "flash.h" +#include "fileio.h" +#include "misc.h" +#include "trace.h" +#include "../target/target.h" +#include "../inc/secure_types.h" // Secure Calypso Plus + +#include +#include +#include +#include + + +/****************************************************************************** + * Globals + ******************************************************************************/ + +// Secure Calypso Plus +extern int bootloader_is_secure_rom; +extern int a_certified_cmd_file_name; + +#define HEX_MOTOROLA_LINE_SIZE 32 // number of bytes in each line +#define HEX_MOTOROLA_ADDR_SIZE 32 // number of bits in addresses (16, 24 or 32) + + +struct { + char type; + char size; + uint32 addr; + uint8 data[128]; + uint8 dummy; // required - don't remove! +} mhex; + + +int hexfile_read(char *name, char *buf, int buf_size, + char *usage_map, int usage_map_chunk_size); +int hexline_motorola_read(char* line); +int hextoint(char *src, int digits); +void hextobytes(uint8 *dst, char *src, int bytes); + +int hexblock_write(char *buf, int size, unsigned long addr, int addr_size, + char hexfile_type); +int hexline_motorola_write(char *buf, int size, + unsigned long addr, int addr_size); +int hexfile_write_open(char *name, char hexfile_type, char *buf, int size); +int hexfile_write_close(char hexfile_type, int addr_size); + +/****************************************************************************** + * File Reading + ******************************************************************************/ + +// Convert image from one endian type to another. The memory width is +// specified with . +void buffer_endian_convert(unsigned char *buf, int buf_size, int width) +{ + unsigned char tmp1, tmp2; + int i; + + tr(TrHexWrite, "buffer_endian_convert(*, %d, %d)\n", buf_size, width); + + for (i = 0; i < buf_size; i += width) { + if (width == 16 || width == 2) { + tmp1 = buf[i+0]; + buf[i+0] = buf[i+1]; + buf[i+1] = tmp1; + } + else if (width == 32 || width == 4) { + tmp1 = buf[i+0]; + tmp2 = buf[i+1]; + buf[i+0] = buf[i+3]; + buf[i+1] = buf[i+2]; + buf[i+2] = tmp2; + buf[i+3] = tmp1; + } + } +} + +int file_read_rc(char *filename) +{ + // TODO: Read the .fluidrc file. It can contain the following + // directives: + // + // path = /* semi-colon? separated list of directories in which + // to look for m0 files etc. */ + // target = [h]|[c] + // baudrate = + // port = + // more? + + return 0; +} + +extern void tr_image_usage_map(void); + +int file_read_image(char *image, int image_size, + char *usage_map, int usage_map_chunk_size) +{ + int size, size_total = 0, i = 0; + int time_load; + + flowf(NORMAL, "Reading image file:"); + + memset(image, 0xFF, image_size); + memset(usage_map, 0, image_size / usage_map_chunk_size); + + if (arg_file_list[0] == NULL) + main_warning(E_FILE_INPUT); + + time_load = stopwatch_start(); + + while (arg_file_list[i] != NULL) + { + flowf(NORMAL, " '%s'", arg_file_list[i]); + if ((size = hexfile_read(arg_file_list[i], image, image_size, + usage_map, usage_map_chunk_size)) < 0) { + flowf(ALWAYS, " MESSAGE: File '%s' not found\n", arg_file_list[i]); + main_error(size); + } + + size_total += size; + flowf(NORMAL, " (%dkB)", (size + 512) / 1024); + + i++; + if (arg_file_list[i] != NULL) + flowf(NORMAL, ","); + } + time_load = (stopwatch_stop(time_load) + 50) /100; + flowf(BLABBER, " (%d.%ds)", time_load / 10, time_load % 10); + flowf(NORMAL, " ok\n"); + + // Now convert image from big endian to little endian format + buffer_endian_convert(image, image_size, arg_hexfile_memwidth); + + return size_total; +} + +int file_read_cmd(char *image, int image_size, char *filename) +{ + //char filename[20] = "cmd.m0"; + + memset(image, 0, image_size); + + flowf(BLABBER, "Reading cmd file '%s': ", filename); + if ((image_size = hexfile_read(filename, image, image_size, 0, 0)) < 0) { + flowf(ALWAYS, "MESSAGE: File '%s' not found\n", filename); + main_error(image_size); + } + flowf(BLABBER, "(%dB) ok\n", image_size); + + return image_size; +} + +int file_read_method(char *image, int image_size, struct device_s *device) +{ + char filename[20]; + + strncpy(filename, + algorithm_name_lookup_by_id(device->algorithm_id), + 20 - sizeof(".m0")); + strcat(filename, ".m0"); + + memset(image, 0, image_size); + + flowf(BLABBER, "Reading method file '%s': ", filename); + if ((image_size = hexfile_read(filename, image, image_size, 0, 0)) < 0) { + flowf(ALWAYS, "MESSAGE: File '%s' not found\n", filename); + main_error(image_size); + } + flowf(BLABBER, "(%dB) ok\n", image_size); + + return image_size; +} + + +/****************************************************************************** + * Hex File Read Functions + ******************************************************************************/ + +// Read an input file in Motorola (or Intel) hex format. On success, return +// the number of raw data bytes read. +int hexfile_read(char *filename, char *buf, int buf_size, + char *usage_map, int usage_map_chunk_size) +{ + FILE* stream; + char line[100]; + uint32 addr; + int type, mysize = 0; + + // First look for file in current directory. Then look for it in the + // directory where the fluid executable was found. + flowf(DEBUG, "(looking for '%s') ", filename); + + if ((stream = fopen(filename, "rt")) == NULL) + { + char buf[256]; + + flowf(DEBUG, "(oops) "); + + if (pathname_make(buf, sizeof(buf), argv_0, filename) < 0) + return E_BUFFER; + + flowf(DEBUG, "(looking for '%s') ", buf); + + if ((stream = fopen(buf, "rt")) == NULL) + return E_FILE_OPEN; + } + flowf(DEBUG, "(ok) "); + + // TODO?: Read the first character of the file and determine the file + // type this way (Motorola format, Intel format or .out format) + type = 'S'; + + while (fgets(line, 100, stream) != NULL) { + switch (type) { + case 'S': + if (hexline_motorola_read(line)) { + mysize += (int) mhex.size; + + // Secure Calypso Plus + if (bootloader_is_secure_rom && + strcmp(filename, (char *)&a_certified_cmd_file_name) == 0 && + mhex.addr >= CMD_SECURE_CALP_OFFSET) { + // The flash programmer is linked to 0x08020000 in internal + // SRAM. + addr = mhex.addr - CMD_SECURE_CALP_OFFSET; + } + else if (mhex.addr >= CALP_OFFSET) + // Assume linked to Calypso Plus (0x04000000 Flash Base) + addr = mhex.addr - CALP_OFFSET; + else + addr = mhex.addr; + + if (addr > (uint32) buf_size) { + fprintf(stderr, "Address too big: 0x%08X\n", (int) addr); + return E_FILE_BUF_SMALL; + } + memcpy(&buf[addr], &mhex.data[0], mhex.size); + // Update the image usage map + if (usage_map != NULL) { + usage_map[(addr) / usage_map_chunk_size] = 'x'; + usage_map[(addr + mhex.size - 1) / usage_map_chunk_size] = 'x'; + } + } + break; + case '?': + // Intel format + break; + case 'O': + // .out format + break; + default: + return E_FILE_FORMAT; + } + } + fclose(stream); + + return mysize; +} + +// Read and decode one line of a Motorola hex file. +// Original design and code by Delta Technologies, 2001. +int hexline_motorola_read(char* line) +{ + mhex.type = (uint8) line[1] - '0'; + mhex.size = hextoint(&line[2], 2); + + tr(TrHexRead, "S%d%02X", mhex.type, mhex.size); + + switch (mhex.type) { + case 0: + // First record in file - no action required + mhex.size = 0; + break; + case 1: + // Data record 16-bit address: S1nnAAAAxxxxxxxxxxxxxxxCC + mhex.size -= 3; + mhex.addr = hextoint(&line[4], 4); + tr(TrCont|TrHexRead, "%04X", mhex.addr); + hextobytes(&mhex.data[0], &line[8], mhex.size); + break; + case 2: + // Data record 24-bit address: S2nnAAAAAAxxxxxxxxxxxxxxxCC + mhex.size -= 4; + mhex.addr = hextoint(&line[4], 6); + tr(TrCont|TrHexRead, "%06X", mhex.addr); + hextobytes(&mhex.data[0], &line[10], mhex.size); + break; + case 3: + // Data record 32-bit address: S3nnAAAAAAAAxxxxxxxxxxxxxxxCC + mhex.size -= 5; + mhex.addr = hextoint(&line[4], 8); + tr(TrCont|TrHexRead, "%08X", mhex.addr); + hextobytes(&mhex.data[0], &line[12], mhex.size); + break; + case 7: + // End of file record 32-bit address + mhex.size = 0; + break; + case 8: + // End of file record 24-bit address + mhex.size = 0; + break; + case 9: + // End of file record 16-bit address + mhex.size = 0; + break; + default: + fprintf(stderr, "WARNING: Illegal hex line: %s\n", line); + main_error(E_FILE_FORMAT); + } + tr(TrCont|TrHexRead, "\n"); + + return mhex.size; +} + +int hextoint(char *src, int digits) +{ + int number = 0; + char ch; + + while (digits-- && *src) { + ch = *src++; + if (ch >= '0' && ch <= '9') + ch = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + ch = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + ch = ch - 'a' + 10; + else + break; + number = (number << 4) + ch; + } + return number; +} + +void hextobytes(uint8 *dst, char *src, int bytes) +{ + while (bytes-- && *src) { + *dst++ = + (src[0] - (src[0] <= '9' ? '0' : 'A' - 10)) * 16 + + (src[1] - (src[1] <= '9' ? '0' : 'A' - 10)); + src += 2; + tr(TrCont|TrHexRead, "%02X", dst[-1]); + } +} + + +/****************************************************************************** + * File Writing + ******************************************************************************/ + +static FILE* ostream; + +int file_write_image(char *image, int image_size, + struct image_part_s *image_list) +{ + int size, size_total = 0; + struct image_part_s *image_list_start = image_list; + + if (arg_show_hexdump == 0 && arg_file_list[0] == NULL) + main_fatal(E_FILE_OUTPUT); + + if (arg_file_list[1] != NULL) + main_fatal(E_ARG_MULTI); + + if (arg_file_list[0] != NULL) + { + flowf(NORMAL, "Writing flash image file: '%s' ", arg_file_list[0]); + + if ((size = hexfile_write_open(arg_file_list[0], arg_hexfile_type, + image, image_size)) < 0) + main_error(size); + + while (image_list->size != 0) + { + // Note that we wrap/mirror memory each 'image_size' bytes + if ((size = + hexblock_write(&image[image_list->addr & (image_size - 1)], + image_list->size, + image_list->addr, 32, + arg_hexfile_type)) < 0) + main_error(E_FILE_BUF_SMALL); + + size_total += size; + flowf(NORMAL, "(%dkB) ", (size + 512) / 1024); + image_list++; + } + if (hexfile_write_close(arg_hexfile_type, 32) < 0) + main_error(E_FILE_CLOSE); + + flowf(NORMAL, " ok\n"); + } + + if (arg_show_hexdump) { + image_list = image_list_start; + while (image_list->size != 0) + { + hexdump(&image[image_list->addr & (image_size - 1)], + image_list->size, + image_list->addr, 1); + putchar('\n'); + image_list++; + } + } + + return size_total; +} + +int file_write_die_id(unsigned char *die_id, char *filename) { + int i; + + if (arg_hexfile_type == 'b') { + // Binary write + if ((ostream = fopen(filename, "wb")) == NULL) + return E_FILE_OPEN; + + if (fwrite(die_id, C_WORD32LGB * C_DIE_ID_SIZE, 1, ostream) < 0) + return E_FILE_WRITE; + } + else { + // Text write + if ((ostream = fopen(filename, "wt")) == NULL) + return E_FILE_OPEN; + + for (i = 0 ; i < (C_WORD32LGB * C_DIE_ID_SIZE) ; i++) + fprintf(ostream, "0x%2.2x ", die_id[i]); + } + + fclose(ostream); + + return 0; +} + +/****************************************************************************** + * Hex File Write Functions + ******************************************************************************/ + +int hexblock_write(char *buf, int size, unsigned long addr, int addr_size, + char hexfile_type) +{ + int size_start = size; + int line_size; + + tr(TrHexWrite, "hexblock_write(*, %d, 0x%x, %d, '%c')\n", + size, addr, addr_size, hexfile_type); + + while (size > 0) { + switch (hexfile_type) { + case 'b': + line_size = fwrite(buf, 1, size, ostream); + if (line_size < size_start) + return E_FILE_WRITE; + break; + case 'm': + case 'S': + line_size = (size > HEX_MOTOROLA_LINE_SIZE ? + HEX_MOTOROLA_LINE_SIZE : size); + hexline_motorola_write(buf, line_size, addr, addr_size); + break; + case '?': + // Intel format + break; + default: + main_fatal(E_FILE_FORMAT); + } + buf += line_size; + size -= line_size; + addr += line_size; + } + + return size_start; +} + +int hexfile_write_open(char *name, char hexfile_type, char *buf, int size) +{ + if ((ostream = fopen(name, "wt")) == NULL) + return E_FILE_OPEN; + + // Write file header + switch (hexfile_type) { + case 'b': + // Binary format --- close file, then reopen it for binary writing + if (fclose(ostream) == EOF) + return E_FILE_OPEN; + if ((ostream = fopen(name, "wb")) == NULL) + return E_FILE_OPEN; + flowf(VERBOSE, "(binary) "); + break; + case 'm': + case 'S': + // Motorola hex files are always in big endian format. + flowf(VERBOSE, "(motorola) "); + buffer_endian_convert(buf, size, arg_hexfile_memwidth); + fprintf(ostream,"S0030000FC\n"); + break; + case '?': + flowf(VERBOSE, "(intel) "); + // Intel format + break; + default: + return E_FILE_FORMAT; + } + + return 0; +} + +int hexfile_write_close(char hexfile_type, int addr_size) +{ + switch (hexfile_type) { + case 'b': + // Binary format --- do nothing + break; + case 'm': + case 'S': + switch (addr_size) { + case 16: fprintf(ostream, "S9030000FC\n"); break; + case 24: fprintf(ostream, "S804000000FB\n"); break; + case 32: fprintf(ostream, "S70500000000FA\n"); break; + } + break; + case '?': + // Intel format + break; + default: + return E_FILE_FORMAT; + } + + fclose(ostream); + + return 0; +} + +int hexline_motorola_write(char *buf, int size, + unsigned long addr, int addr_size) +{ + uint8 cksum; + int i; + + tr(TrHexWrite, "hexline_motorola_write(*, %d, 0x%x, %d)\n", + size, addr, addr_size); + + if (addr_size == 0) { + if ((addr + (unsigned long)(size - 1)) < 0x10000L) + addr_size = 16; + else if ((addr + (unsigned long)(size - 1)) < 0x1000000L) + addr_size = 24; + else + addr_size = 32; + } + switch (addr_size) { + case 16: + fprintf(ostream, "S1%02X%04lX", size + 3, addr); + cksum = size + 3; + break; + case 24: + fprintf(ostream, "S2%02X%06lX", size + 4, addr); + cksum = size + 4; + break; + case 32: + fprintf(ostream, "S3%02X%08lX", size + 5, addr); + cksum = size + 5; + break; + } + cksum += + (uint8) ((addr >> 24) & 0xFF) + + (uint8) ((addr >> 16) & 0xFF) + + (uint8) ((addr >> 8) & 0xFF) + + (uint8) ((addr >> 0) & 0xFF); + + for (i = 0; i < size; i++) { + fprintf(ostream,"%02X", buf[i] & 0xFF); + cksum += buf[i]; + } + cksum = ~cksum; + fprintf(ostream,"%02X\n", cksum); + + return 0; +} + diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/fileio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/fileio.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,29 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * File reading/loading + * + * $Id: fileio.h 1.5 Wed, 09 Jan 2002 13:01:15 +0100 mmj $ + * + ******************************************************************************/ + + +struct image_part_s { + uint32 addr; + uint32 size; +}; + +void buffer_endian_convert(unsigned char *buf, int size, int width); + +int file_read_rc(char *filename); +int file_read_image(char *image, int image_size, + char *usage_map, int usage_map_chunk_size); +int file_read_cmd(char *image, int image_size, char *filename); // Secure Calypso Plus +int file_read_method(char *image, int image_size, struct device_s *device); + +int file_write_image(char *image, int image_size, + struct image_part_s *image_list); +int file_write_die_id(unsigned char *die_id, char *filename); diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/flash.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/flash.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,614 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Flash device database and lookup + * + * $Id: flash.c 1.26 Wed, 30 Oct 2002 12:09:08 +0100 tsj $ + * + ******************************************************************************/ + +#include "fluid.h" +#include "misc.h" +#include "flash.h" +#include "trace.h" + +#include +#include +#include +#include + + +/****************************************************************************** + * Global, Static definitions + ******************************************************************************/ + +const struct algorithm_s algorithms[] = { + { ALGORITHM_AMD, "amd" }, + { ALGORITHM_INTEL, "intel" }, + { ALGORITHM_INTEL_BW, "intel_bw" }, + { ALGORITHM_MITSUBISHI, "mitsubishi" }, + { ALGORITHM_SST, "sst" }, + { 0, "unknown" } +}; + +struct manufact_s manufacturers[] = { + { MANUFACT_AMD, "AMD" }, + { MANUFACT_ATMEL, "Atmel" }, + { MANUFACT_FUJITSU, "Fujitsu" }, + { MANUFACT_INTEL, "Intel" }, + { MANUFACT_MXIC, "MXIC" }, + { MANUFACT_MITSUBISHI, "Mitsubishi" }, + { MANUFACT_SAMSUNG, "Samsung" }, + { MANUFACT_SHARP, "Sharp" }, + { MANUFACT_STM, "STM" }, + { MANUFACT_SST, "SST" }, + { MANUFACT_TOSHIBA, "Toshiba" }, + { 0x00, "Unknown" } +}; + + +/****************************************************************************** + * Default Device Database + ******************************************************************************/ + +struct memmap_s map_63x64_8x8 = { + 0, + "63x64_8x8kB", + 63 + 8, + { + { 0x000000, 0x10000 }, { 0x010000, 0x10000 }, + { 0x020000, 0x10000 }, { 0x030000, 0x10000 }, + { 0x040000, 0x10000 }, { 0x050000, 0x10000 }, + { 0x060000, 0x10000 }, { 0x070000, 0x10000 }, + { 0x080000, 0x10000 }, { 0x090000, 0x10000 }, + { 0x0A0000, 0x10000 }, { 0x0B0000, 0x10000 }, + { 0x0C0000, 0x10000 }, { 0x0D0000, 0x10000 }, + { 0x0E0000, 0x10000 }, { 0x0F0000, 0x10000 }, + + { 0x100000, 0x10000 }, { 0x110000, 0x10000 }, + { 0x120000, 0x10000 }, { 0x130000, 0x10000 }, + { 0x140000, 0x10000 }, { 0x150000, 0x10000 }, + { 0x160000, 0x10000 }, { 0x170000, 0x10000 }, + { 0x180000, 0x10000 }, { 0x190000, 0x10000 }, + { 0x1A0000, 0x10000 }, { 0x1B0000, 0x10000 }, + { 0x1C0000, 0x10000 }, { 0x1D0000, 0x10000 }, + { 0x1E0000, 0x10000 }, { 0x1F0000, 0x10000 }, + + { 0x200000, 0x10000 }, { 0x210000, 0x10000 }, + { 0x220000, 0x10000 }, { 0x230000, 0x10000 }, + { 0x240000, 0x10000 }, { 0x250000, 0x10000 }, + { 0x260000, 0x10000 }, { 0x270000, 0x10000 }, + { 0x280000, 0x10000 }, { 0x290000, 0x10000 }, + { 0x2A0000, 0x10000 }, { 0x2B0000, 0x10000 }, + { 0x2C0000, 0x10000 }, { 0x2D0000, 0x10000 }, + { 0x2E0000, 0x10000 }, { 0x2F0000, 0x10000 }, + + { 0x300000, 0x10000 }, { 0x310000, 0x10000 }, + { 0x320000, 0x10000 }, { 0x330000, 0x10000 }, + { 0x340000, 0x10000 }, { 0x350000, 0x10000 }, + { 0x360000, 0x10000 }, { 0x370000, 0x10000 }, + { 0x380000, 0x10000 }, { 0x390000, 0x10000 }, + { 0x3A0000, 0x10000 }, { 0x3B0000, 0x10000 }, + { 0x3C0000, 0x10000 }, { 0x3D0000, 0x10000 }, + { 0x3E0000, 0x10000 }, + + { 0x3F0000, 0x02000 }, { 0x3F2000, 0x02000 }, + { 0x3F4000, 0x02000 }, { 0x3F6000, 0x02000 }, + { 0x3F8000, 0x02000 }, { 0x3FA000, 0x02000 }, + { 0x3FC000, 0x02000 }, { 0x3FE000, 0x02000 }, + } +}; + +struct memmap_s *memmaps = &map_63x64_8x8; + +// Default B-Sample device +struct device_s device_fujitsu_dl323t = { + 0, + ALGORITHM_AMD, + MANUFACT_FUJITSU, + 0x2250, + "MBM29DL323DT", + 0, + 0, + &map_63x64_8x8 +}; + +// Default C-Sample device +struct device_s device_amd_dl322t = { + &device_fujitsu_dl323t, // link to next (previous) device defintion + ALGORITHM_AMD, + MANUFACT_AMD, + 0x2255, + "Am29DL322DT", + 0, + 0, + &map_63x64_8x8 +}; + +struct device_s *devices = &device_amd_dl322t; + + +/****************************************************************************** + * Device file reading and parsing + ******************************************************************************/ + +#define INBUF_SIZE 1024 + +static char inbuf[INBUF_SIZE]; +static char *pin; +static FILE *fp; +static int linenum; + +static char string[1024]; +static int length; +static int number; + +enum ParserTokens { + TOKEN_EOF, + TOKEN_STRING, + TOKEN_NUMBER, + TOKEN_KEYWORD +}; + +enum ParserKeywords { + KEYWORD_NONE, + KEYWORD_DEVICE, + KEYWORD_MEMMAP +}; + +void parser_error(int error) +{ + fprintf(stderr, "At line %d, ", linenum); + main_fatal(error); +} + +void file_read_devices(char *filename) +{ + int token, i, n = 0; + struct device_s *device; + struct memmap_s *memmap; + + flowf(BLABBER, "Reading '%s': ", filename); + + // First look for file in current directory. Then look for it in the + // directory where the fluid executable was found. + if ((fp = fopen(filename, "rt")) == NULL) + { + char buf[256]; + + if (pathname_make(buf, sizeof(buf), argv_0, filename) < 0) + main_fatal(E_BUFFER); + + flowf(DEBUG, "(looking for '%s') ", buf); + + if ((fp = fopen(buf, "rt")) == NULL) { + fprintf(stderr, "WARNING: file '%s' not found. Using default device database.\n", filename); + return; + } + } + + devices = (struct device_s *) 0; + memmaps = (struct memmap_s *) 0; + + pin = inbuf; + inbuf[0] = '\n'; + linenum = 0; + + // Each loop represents one block/statement of the file + while ((token = get_keyword()) != E_PARSER_EOF) { + switch (token) { + case KEYWORD_MEMMAP: + tr(TrBegin|TrParser, "keyword: memmap {\n"); + if ((token = get_string()) < 0) + parser_error(token); + + if ((memmap = malloc(sizeof(struct memmap_s) + length + 1)) == NULL) + parser_error(E_MEMORY); + memmap->name = (char *) memmap + sizeof(struct memmap_s); + strcpy(memmap->name, string); + + if ((token = get_token()) != '{') + parser_error(E_PARSER_SYNTAX); + + i = 0; + while ((token = get_token()) == TOKEN_NUMBER) + { + memmap->sectors[i].addr = number; + + if ((token = get_number()) < 0) + parser_error(token); + memmap->sectors[i].size = number; + + i++; + } + if (token != '}') + parser_error(E_PARSER_END_BRACE); + + memmap->size = i; + + // Append to linked list + memmap->next = memmaps; + memmaps = memmap; + + tr(TrEnd|TrParser, "}\n"); + break; + + case KEYWORD_DEVICE: + tr(TrBegin|TrParser, "keyword: device {\n"); + if ((token = get_string()) < 0) + parser_error(token); + if ((device = malloc(sizeof(struct device_s) + length + 1)) == NULL) + parser_error(E_MEMORY); + device->name = (char *) device + sizeof(struct device_s); + strcpy(device->name, string); + + if ((token = get_number()) < 0) + parser_error(token); + device->manufacturer_id = number; + + if ((token = get_number()) < 0) + parser_error(token); + device->device_id = number; + + if ((token = get_string()) < 0) + parser_error(token); + device->algorithm_id = algorithm_id_lookup_by_name(string); + if (device->algorithm_id == 0) + parser_error(E_PARSER_ALGORITHM); + + if ((token = get_string()) < 0) + parser_error(token); + device->memmap = memmap_lookup_by_name(string); + if (device->memmap == 0) + parser_error(E_PARSER_MEMMAP); + + // Append to linked list + device->next = devices; + devices = device; + + tr(TrEnd|TrParser, "}\n"); + break; + default: + parser_error(E_PARSER_KEYWORD); + } + n++; + } + + flowf(BLABBER, "(%d blocks read) ok.\n", n); +} + +int get_next_line(void) +{ + int result; + + result = (fgets(inbuf, INBUF_SIZE, fp) != NULL); + + pin = inbuf; + linenum++; + + tr(TrParser, "get_next_line() (%d) %d ", result); + + return result; +} + +int get_token(void) +{ + char *pin_start, *pin_end; + int whitespace; + + { + char tmp[8]; + for (whitespace = 0; whitespace < 7; whitespace++) + tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]); + tmp[7] = 0; + tr(TrParser, "get_token() ('%s...')", tmp); + } + + whitespace = 1; + + while (whitespace) + { + if (*pin == ' ' || *pin == '\t' || *pin == '\n') { + // Skip white-space + tr(TrParser, " skip white-space {"); + while (*pin == ' ' || *pin == '\t' || *pin == '\n') + { + while (*pin == ' ' || *pin == '\t') + pin++; + + // If end of line, read the next line + if (*pin == '\n') { + if (get_next_line() == 0) + return TOKEN_EOF; + } + } + tr(TrCont|TrParser, "}"); + } + else if (pin[0] == '/' && pin[1] == '*') { + // Skip comment + tr(TrParser, " skip comment {"); + while (pin[0] != '*' || pin[1] != '/') + { + while ((pin[0] != '*' || pin[1] != '/') && *pin != '\n') + pin++; + + // If end of line, read the next line + if (*pin == '\n') { + if (get_next_line() == 0) + return TOKEN_EOF; + } + else { + pin += 2; + break; + } + } + tr(TrCont|TrParser, "}"); + } + else { + whitespace = 0; + } + } + + { + char tmp[8]; + for (whitespace = 0; whitespace < 7; whitespace++) + tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]); + tmp[7] = 0; + tr(TrCont|TrParser, " ('%s...')\n", tmp); + } + + // See if token is a string + if (isalpha(*pin) || *pin == '_') { + pin_start = pin; + while (isalnum(*pin) || *pin == '_') + pin++; + length = pin - pin_start; + strncpy(string, pin_start, length); + string[length] = 0; + return TOKEN_STRING; + } + + // See if token is a number + if (isdigit(*pin)) { + number = (int) strtol(pin, &pin_end, 0); + pin = pin_end; + if (*pin_end == 'k') { + number *= 1024; + pin++; + } + return TOKEN_NUMBER; + } + + // Token is a character + return *pin++; +} + +int get_keyword(void) +{ + int token; + + token = get_token(); + tr(TrParser, "get_keyword() (%d) ", token); + + if (token == TOKEN_EOF) + return E_PARSER_EOF; + + if (token != TOKEN_STRING) + return E_PARSER_KEYWORD; + + if (strcmp("memmap", string) == 0) + token = KEYWORD_MEMMAP; + else if (strcmp("device", string) == 0) + token = KEYWORD_DEVICE; + else + token = E_PARSER_KEYWORD; + + tr(TrCont|TrParser, "%d\n", token); + return token; +} + +int get_string(void) +{ + int token; + + token = get_token(); + tr(TrParser, "get_string() (%d) ", token); + + if (token == TOKEN_EOF) + return E_PARSER_EOF; + + if (token != TOKEN_STRING) + return E_PARSER_STRING; + + tr(TrCont|TrParser, "'%s'\n", string); + return 0; +} + +int get_number(void) +{ + int token; + + token = get_token(); + tr(TrParser, "get_number() (%d) ", token); + + if (token == TOKEN_EOF) + return E_PARSER_EOF; + + if (token != TOKEN_NUMBER) + return E_PARSER_NUMBER; + + tr(TrCont|TrParser, "0x%X\n", number); + return 0; +} + + +/****************************************************************************** + * Functions + ******************************************************************************/ + +// Estimate the time taken for erasure and programming of the flash +// device. is the number of bytes to program. +int time_compute(struct device_s *device, + int sectors, int bytes, int chunks, + int *time_erase, int *time_program, int *time_transfer) +{ + int te = 0; // sector erase time in milli seconds + int tp = 16; // 16-bit word program time in micro seconds + int tdt, tco, trp; + + switch (device->algorithm_id) { + case ALGORITHM_AMD: te = 700; break; + case ALGORITHM_INTEL: te = 800; break; + case ALGORITHM_INTEL_BW: te = 1300; break; + case ALGORITHM_MITSUBISHI: te = 40; break; + case ALGORITHM_SST: te = 20; break; + } + *time_erase = te * sectors; + + // Data transmission time: with 12 bytes per chunk + tdt = (bytes + 12 * chunks) / (arg_uart_baudrate / 10) * 1000; + + // Communication overhead time: 2 waits of 10ms per chunk. + tco = chunks * 2 * 10; + + *time_transfer = tdt + tco; + + // Raw programming time: + *time_program = trp = (bytes / 2) * tp / 1000; + + tr(TrUtility, "tdt = %d\n", tdt); + tr(TrUtility, "tco = %d\n", tco); + tr(TrUtility, "trp = %d\n", trp); + + return *time_erase + *time_transfer; +} + +void device_print(struct device_s *device, char format) +{ + int device_size = + (device->memmap->sectors[device->memmap->size - 1].addr + + device->memmap->sectors[device->memmap->size - 1].size) / + (1024 * 1024 / 8); + + if (format == 'l') { + printf("%s %s (0x%02X, 0x%04X). %dMb in %d sectors, %s algorithm", + manufacturer_name_lookup_by_id(device->manufacturer_id), + device->name, + device->manufacturer_id, + device->device_id, + device_size, + device->memmap->size, + algorithm_name_lookup_by_id(device->algorithm_id)); + } + else if (format == 's') { + printf("(0x%02X, 0x%04X) %s %s", + device->manufacturer_id, + device->device_id, + manufacturer_name_lookup_by_id(device->manufacturer_id), + device->name); + } +} + +void devices_list(void) +{ + struct device_s *device = devices; + + while (device != NULL) { + device_print(device, 'l'); + putchar('\n'); + device = device->next; + } +} + +struct device_s *device_lookup_by_id(int m, int d) +{ + struct device_s *device = devices; + + while (device != NULL) { + if ((m & 0xFF) == device->manufacturer_id && d == device->device_id) + return device; + device = device->next; + } + return (struct device_s *) 0; +} + +struct device_s *device_lookup_by_name(char *name) +{ + struct device_s *device = devices; + + while (device != NULL) { + if (strcmp(name, device->name) == 0) + return device; + device = device->next; + } + return (struct device_s *) 0; + +} + +struct memmap_s *memmap_lookup_by_name(char *name) +{ + struct memmap_s *memmap = memmaps; + + while (memmap != NULL) { + if (strcmp(name, memmap->name) == 0) + return memmap; + memmap = memmap->next; + } + return (struct memmap_s *) 0; +} + +char *manufacturer_name_lookup_by_id(int id) +{ + int i = 0; + + while (manufacturers[i].id != 0) { + if (manufacturers[i].id == id) + return manufacturers[i].name; + i++; + } + + return manufacturers[i].name; +} + +int manufacturer_id_lookup_by_name(char *name) +{ + int i = 0; + + while (manufacturers[i].id != 0) { + if (strcmp(manufacturers[i].name, name) == 0) + return manufacturers[i].id; + i++; + } + + return 0; +} + +char *algorithm_name_lookup_by_id(int id) +{ + int i = 0; + + while (algorithms[i].id != 0) { + if (algorithms[i].id == id) + return algorithms[i].name; + i++; + } + + return algorithms[i].name; +} + +int algorithm_id_lookup_by_name(char *name) +{ + int i = 0; + + while (algorithms[i].id != 0) { + if (strcmp(algorithms[i].name, name) == 0) + return algorithms[i].id; + i++; + } + + return 0; +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/flash.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/flash.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,102 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Flash device database and lookup + * + * $Id: flash.h 1.11 Wed, 30 Oct 2002 12:09:08 +0100 tsj $ + * + ******************************************************************************/ + + +/****************************************************************************** + * Prototypes + ******************************************************************************/ + +struct sector_s { + int addr; + int size; +}; + +// We make room for a device of 2047 * 64kB + plus 8 * 8kB sectors (eg. 1Gb) +struct memmap_s { + struct memmap_s *next; + char *name; + int size; + struct sector_s sectors[2047+7]; +}; + +struct device_s { + struct device_s *next; + int algorithm_id; + int manufacturer_id; + int device_id; + char *name; + int t_erase; // typical time (milli-seconds) for erasing one sector + int t_program; // typical time (micro-seconds) for programming one word + struct memmap_s *memmap; +}; + +struct manufact_s { + // struct manufact_s *next; + int id; + char *name; +}; + +struct algorithm_s { + int id; + char *name; +}; + +enum FlashAlgorithms { + ALGORITHM_AMD = 1, + ALGORITHM_AMDFAST, + ALGORITHM_INTEL, + ALGORITHM_INTEL_BW, + ALGORITHM_MITSUBISHI, + ALGORITHM_SST +}; + +enum FlashManufacturers { + MANUFACT_AMD = 0x01, + MANUFACT_ATMEL = 0x1F, + MANUFACT_FUJITSU = 0x04, + MANUFACT_INTEL = 0x89, + MANUFACT_MXIC = 0xC2, + MANUFACT_MITSUBISHI = 0x1C, + MANUFACT_SAMSUNG = 0xEC, + MANUFACT_SHARP = 0xB0, + MANUFACT_STM = 0x20, + MANUFACT_SST = 0xBF, + MANUFACT_TOSHIBA = 0x98, + MANUFACT_TEST = 0xFF +}; + + +/****************************************************************************** + * Prototypes + ******************************************************************************/ + +void device_print(struct device_s *device, char format); +void devices_list(void); +void file_read_devices(char *filename); + +int get_next_line(void); +int get_token(void); +int get_keyword(void); +int get_string(void); +int get_number(void); + +int time_compute(struct device_s *device, + int sectors, int bytes, int chunks, + int *time_erase, int *time_program, int *time_trransfer); + +struct device_s *device_lookup_by_id(int manid, int devid); +struct memmap_s *memmap_lookup_by_name(char *name); +char *manufacturer_name_lookup_by_id(int id); +int manufacturer_id_lookup_by_name(char *name); +char *algorithm_name_lookup_by_id(int id); +int algorithm_id_lookup_by_name(char *name); diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/fluid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/fluid.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,818 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Main, command-line argument parsing, error handling. + * + * $Id: fluid.c 1.50 Thu, 14 Nov 2002 13:10:05 +0100 tsj $ + * + ******************************************************************************/ + +#include "fluid.h" +#include "flash.h" +#include "fileio.h" +#include "trace.h" +// Secure Calypso Plus +#include "../inc/ram_load.h" + +#include +#include +#include +#include + +#if defined(MSC) || defined(BCC) + #include "getopt.h" + #include "windows.h" +#else + #include +#endif + +#include // for ERANGE + + +/****************************************************************************** + * Prototypes and Globals + ******************************************************************************/ + +extern T_RAM_LOADER d_ram_loader; // Secure Calypso Plus + +char *arg_file_list[ARG_FILE_LIST_SIZE_MAX] = { (char *) 0 }; +int arg_file_list_size = 0; + +char *arg_erase_override = ""; +char *arg_read = ""; +char *arg_write = ""; +int arg_checksum = 1; +int arg_compress = 1; +int arg_dry_run = 0; +int arg_list_devices = 0; +char arg_target_type = 0; +int arg_image_map_show = 0; +int arg_sector_map_show = 0; +int arg_sector_list_show = 0; +int arg_timers_show = 0; +int arg_timers_extended_show = 0; +int arg_checksum_show = 0; +int arg_show_hexdump = 0; +int arg_target_trace_enable = 0; +int arg_progress = 'a'; +char arg_hexfile_type = 'm'; +char arg_hexfile_memwidth = 2; + +int arg_target_reset = 1; +int arg_rom_bootloader = 0; +int arg_boot_delay_rom = 15; +int arg_boot_delay_fluid = 15; +int arg_device_id0 = -1; +int arg_device_id1 = -1; + +int arg_uart_port = 1; +int arg_uart_baudrate = 115200; +char arg_uart_flowcontrol[] = "pn"; +char arg_uart_level_convert = 0; + +char arg_verbose = 0; +int arg_debug_resume = 0; +int arg_debug_trace_pe = 0; +int arg_keep_going = 0; +int arg_show_main_args = 0; +int arg_skip_erase = 0; + +// Secure Calypso Plus +char *arg_die_id_file_name = ""; +char *arg_imeisv = ""; +char *arg_platform_certificate_addr = ""; +int arg_request_certificate = 0; +int arg_delay_for_changing_cs5 = 0; +int arg_uart_baudrate_during_cmd_download = 115200; +int arg_uart_timeout_configuration = 0; +int arg_block_size = 8 * 1024; // Must be a modulus of 64 bytes, except for the last command. + +int arg_usage = 0; + +char *argv_0; + +int arg_tr_mask = 0; +int arg_tr_spaces = 2; +char *arg_tr_file = NULL; + +int arg_errorfd = 2; + +static void main_usage(void); +static void main_args(int argc, char *argv[]); +static long arg_long_get(void); + +extern int fluid_machine(void); +extern int fluid_compress(void); +extern int fluid_decompress(void); + +extern int serial_is_baudrate(int bps); + + +/****************************************************************************** + * Error handling + ******************************************************************************/ + +extern char *main_strerror(int error); + +char *win32_strerror(void) +{ + static char buf[220]; + int error; + char *p = buf; + + error = GetLastError(); + p += sprintf(buf, "%d: ", error); + + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + p, sizeof(buf) - 20, NULL) == 0) + sprintf(p, "(Unknown Win32 error)"); + + return buf; +} + +void main_msg(char *format, ...) +{ + va_list args; + char buf[1024]; + + va_start(args, format); + vsprintf(buf, format, args); + va_end(args); + + if (arg_errorfd == 2) { + fprintf(stderr, "%s", buf); + fflush(stderr); + } + else { + fprintf(stdout, "%s", buf); + fflush(stdout); + } +} + +void main_error_str(char type, int error, char *string) +{ + // If it was an OS error... + if (error < E_OS) { + error -= E_OS; + main_msg("OS-ERROR: %s", win32_strerror()); + } + + main_msg(" %s(%d): %s%s\n", (type == 'w' ? "WARNING" : "ERROR"), + -error, main_strerror(error), string); +} + +void main_warning(int error) +{ + main_error_str('w', error, ""); +} + +void main_error(int error) +{ + main_error_str('e', error, ""); + + if (arg_keep_going == 0) + exit(-error); +} + +void main_fatal(int error) +{ + main_error(error); + exit(-error); +} + + +/****************************************************************************** + * Command line parsing + ******************************************************************************/ + +static void main_help(void) +{ + printf( + "\n" + "You have started fluid with no command line arguments\n" + "\n" + "To see all the available command line arguments, start fluid\n" + "from a command line prompt (cmd.exe or similar) with:\n" + "\n" + " fluid -h\n" + "\n" + "To see some basic and common examples of usage, start fluid with:\n" + "\n" + " fluid -ic\n" + "\n" + "You can get an overview of all the available examples with:\n" + "\n" + " fluid -ii\n" + "\n" +// "Please read the README file for notes and other info and read the\n" +// "HISTORY file to see what has happened with fluid since last release.\n" +// "\n" + "Press RETURN to exit...\n" + ); + getchar(); +} + +static void main_example(int type) +{ + switch (type) { + case 'c': + printf( + "Download into board:\n" + " fluid -f gsm.m0\n" + "\n" + "Simulate a download into board (dry-run):\n" + " fluid -n -f gsm.m0\n" + "\n" + "Check if file has already been downloaded into board:\n" + " fluid -n -f gsm.m0\n" + "\n" + "Download into board without erasing boot sector:\n" + " fluid -e-0 -f gsm.m0\n" + "\n" + "Download into board with another progress indication:\n" + " fluid -gc -f gsm.m0\n" + "\n" + ); + break; + case 'a': + printf( + "Download into board with more output verbosity:\n" + " fluid -v -v -f gsm.m0\n" + "\n" + "Show the image map (which parts of the flash are used, which are not):\n" + " fluid -si -n -f gsm.m0\n" + "\n" + "Show both the image and the erase maps:\n" + " fluid -sis -n -f gsm.m0\n" + "\n" + "Download into board without delta download:\n" + " fluid -C -f gsm.m0\n" + "\n" + ); + break; + case 'e': + printf( + "Erase all flash (including boot sector!):\n" + " fluid -e+*\n" + "\n" + "Erase all flash except the boot sector:\n" + " fluid -e+*,-0\n" + "\n" + "Erase the last megabyte of a 4MB flash device:\n" + " fluid -e+3M..4M\n" + "\n" + "Erase all flash except sectors 1..7 and addresses 1984k..2048k:\n" + " fluid -e+*,-1..8,-1984k..2048k\n" + "\n" + ); + break; + case 'r': + printf( + "Read whole FFS system from a B-Sample:\n" + " fluid -r3M..4M -f bsffs.m0\n" + "\n" + "Then copy/download it (e.g., to another B-Sample):\n" + " fluid -f bsffs.m0\n" + "\n" + "Read serial switch config from a B- or C-Sample:\n" + "(serial switch config is in sector 2 on TI releases earlier than SSA-5.3.1)\n" + " fluid -r0x11ffe..0x12000 -f usxx.m0 -sx\n" + "\n" + "Copy it to a(nother) B- or C-sample:\n" + " fluid -f usxx.m0\n" + "\n"); + break; + case 'w': + printf( + "Over-write image with a byte string at a specific address:\n" + " fluid -f gsm.m0 -w7800=0x11,0x22,0x33,0x44,0x55,0x66\n" + "\n" + "Write zeroes into top-most 2MB of C-Sample flash memory:\n" + " fluid -w2M..4M=0\n" + "\n" + "Write a string to a specific address:\n" + " fluid -w0x1800=\"\"\"Mads\"\"\",0\n" + "\n"); + break; + case 's': + printf( + "Reset target, doing nothing else (requires special cable):\n" + " fluid -n -or\n" + "\n" + ); + break; + default: + printf( + "Avaliable examples:\n" + " a = Advanced, common usage\n" + " c = Common usage\n" + " e = Erase override\n" + " r = Read target memory\n" + " w = Write target memory\n" + " s = Special usage\n" + ); + break; + } + exit(0); +} + +static void main_debug_usage(void) +{ + printf("Debug usage: fluid [OPTIONS...]\n" + "\n" + " -d r Display target (remote) tracing.\n" + " -d c Resume fluid state machine in command interpreter.\n" + " -d o Display final command line option values.\n" + " -d t Trace mask in human format:\n" + " a = All, except ?\n" + " * = All\n" + " g = getchar()\n" + " p = putchar()\n" + " G = target driver receive\n" + " P = target driver transmit\n" + " w = target wait\n" + " t = target/transport layer driver\n" + " h = hexfile read/decode\n" + " H = hexfile write/encode\n" + " r = device file parser\n" + " c = Command line argument parser\n" + " u = utility functions\n" + " m = state machine functions\n" + " \n" + " -d v Display info on compiler used.\n" + " -d f Trace to file.\n" + " -d i Trace indentation multiplier. Default is 2.\n" + " -d m Trace mask. Default is 0.\n" + " -t Trace mask in human format. Same as '-d t'.\n" + "\n" + "B-/C-/D-Sample LEDs layout:\n" + "\n" + "+---0---+---1---+---2---+---3---+---4---+---5---+---6---+---7---+\n" + "| Recv | Erase | Prog | Overhd| Idle | | | Busy |\n" + "+-------+-------+-------+-------+-------+-------+-------+-------+\n" + ); + exit(0); +} + +static void main_args_debug_trace(void) +{ + while (*optarg) { + switch(*optarg++) { + case 'a': arg_tr_mask |= TrAll & ~(0); break; + case '*': arg_tr_mask |= TrAll; break; + case 'm': arg_tr_mask |= TrMachines; break; + case 'g': arg_tr_mask |= TrGetChar; break; + case 'p': arg_tr_mask |= TrPutChar; break; + case 'G': arg_tr_mask |= TrDriverGet; break; + case 'P': arg_tr_mask |= TrDriverPut; break; + case 'w': arg_tr_mask |= TrTargetWait; break; + case 't': arg_tr_mask |= TrTargetDrv; break; + case 'h': arg_tr_mask |= TrHexRead; break; + case 'H': arg_tr_mask |= TrHexWrite; break; + case 'r': arg_tr_mask |= TrParser; break; + case 'c': arg_tr_mask |= TrArgParser; break; + case 'C': arg_tr_mask |= TrCmdLineParser; break; + case 'u': arg_tr_mask |= TrUtility; break; + } + } +} + +static void fluid_welcome(void) +{ + flowf(NORMAL, + "FLUID Revision 2.27, (23 Aug 2004). Copyright Texas Instruments, 2001-2004.\n"); +} + +static void fluid_compile_info(void) +{ + flowf( + NORMAL, + "Compiled " __DATE__ " " __TIME__ " with " +#if defined(MSC) + "Microsoft cl.exe" +#elif defined(BCC) + "Borland bcc" +#else + "GNU gcc" +#endif + "\n"); +} + +static void main_usage(void) +{ + printf( + "Usage: fluid [OPTIONS...]\n" + "\n"); + if (!arg_usage) + fluid_welcome(); + printf( + "FLUID is a Flash Loader Utility Independent of Device\n" + "This version supports:\n" + " TI GSM Boot Loader V6.x.x (with fluid patch)\n" + " TI ROM Boot Loader (Calypso devices only)\n" + "\n" + " -f Flash image file (input or output file).\n" + " -p Serial port number. Default is 1.\n" + " -b Serial baudrate. Default is 115200.\n" + " -t Target type (Default is auto-detect):\n" + " h = Hercules\n" + " u = Ulysses\n" + " c = Calypso\n" + " l = Calypso Lite\n" + " p = Calypso Plus\n" + " -l List all known flash devices.\n" + " -c, -C Do or do not checksum target memory thus enabling delta\n" + " download (only program changed sectors). Default is on.\n" + " -z, -Z Do or do not compress data on download. Default is on.\n" + " -g Progress indication type:\n" + " a = asterisks (default), c = chars, d = dots,\n" + " x = address+size, n = none\n" + " -e [+|-]..,... or [+|-],...<\n" + " Erase/program override. Erase or don't erase flash\n" + " memory in the range [addr0..addr1[. Use '-ie' to see\n" + " examples of usage\n" + " -<...> = do *not* erase and program\n" + " +<...> = force erase\n" + " Giving as an asterisk, '*', means all sectors\n" + " -r ..,...\n" + " Read target memory range [addr0..addr1[ and write the\n" + " bytes to output file specified.\n" + " -w ..=:...\n" + " Write bytes to image. The bytes b0..bN are replicated\n" + " through the whole memory range [addr0..addr1[\n" + " -o Extra options:\n" + " o = Only bootstrap using ROM boot loader (Calypso devices only)\n" + " O = Do NOT use ROM boot loader\n" + " e = Skip erase (Require empty flash)\n" + " r = Reset target after download (default)\n" + " R = Do NOT reset target after download\n" + " l = Activate (old-fashioned) UART level conversion\n" + " m = Select Motorola hexfile output format (default)\n" + " b = Select binary/raw file output format\n" + " i, = Disable device auto-detection and set manufacturer\n" + " id and device id\n" + " d, = Set detection delay (in ms) for ROM and fluid boot\n" + " loader, respectively\n" + " 1, 2, 4 = Select hexfile memory width 1, 2 or 4. Default is 2\n" + " -s Show additional info:\n" + " i = image map\n" + " s = sector erase map\n" + " l = sector erase list\n" + " t = target timers, T = extended target timer info\n" + " x = hexdump of target memory (together with '-r')\n" + " c = checksums\n" + " -n Dry run. Do not program the flash device.\n" + " -v Be verbose. Multiple '-v's means more verbosity.\n" + " -q Be quiet.\n" +// " -y Use stdout for error messages.\n" + " -dh Display help on debug and trace options.\n" + " -h Display this help.\n" + " -i Display examples (i = index/overview of examples).\n" + // Secure Calypso Plus + "\n Secure Calypso Plus options:\n" + " -I IMEI protection options:\n" + " d = Retrieve die id from target and write to .\n" + " n = 16 digits representing the IMEI-SV, [8 TAC]+[6 SNR]+\n" + " [2 SVN], which is used for non-secure E-samples or\n" + " secure E-samples when the die id is not added to the\n" + " DIE_ID field of the manufacturer certificate.\n" + " a = Address of the platform certificate stored in flash.\n" + " -R Request firmware certificate.\n" + " -D Insert a delay before detection of flash type. This delay is used\n" + " for changing the memory mapping on CS5 due to a bug in ROM code\n" + " 0x0410 (see SECURITY.txt) or for connecting to target via JTAG.\n" + " -U UART baudrate during flash programmer download. Default is 115200.\n" + " -u UART timeout configuration. Default is 0.\n" + " -B Block size. Must be a modulus of 64 bytes. Default is %d bytes.\n", arg_block_size + // End Secure Calypso Plus + ); +} + +static void main_args(int argc, char *argv[]) +{ + char ch; + int i; + // IMEI Protection + char d_i, d_digit; + char a_imeisv_format[] = "The IMEI-SV must consist of 16 digits in compliance with the following format:\n[8 TAC]+[6 SNR]+[2 SVN]\n"; + + if (argc == 1) { + fluid_welcome(); + main_help(); + exit(0); + } + + for (i = argc - 1; i >= 0; i--) { + // TODO?: scan for filenames. + } + + while ((ch = getopt(argc, argv, + "f:p:b:cCzZjJt:e:s:r:w:nlqg:o:vkd:i:hVyI:RD:U:u:B:")) != -1) + { + switch (ch) + { + case 'f': + if (arg_file_list_size < ARG_FILE_LIST_SIZE_MAX - 1) + arg_file_list[arg_file_list_size++] = optarg; + arg_file_list[arg_file_list_size] = NULL; + break; + case 'p': + arg_uart_port = arg_long_get(); + if (arg_uart_port < 1 || 24 < arg_uart_port) + main_error(E_BADARG); + break; + case 'b': + arg_uart_baudrate = arg_long_get(); + arg_uart_baudrate = serial_is_baudrate(arg_uart_baudrate); + if (arg_uart_baudrate == 0) + main_error(E_BADARG); + break; + case 't': + arg_target_type = *optarg; + break; + case 'c': arg_checksum = 1; break; + case 'C': arg_checksum = 0; break; + case 'z': arg_compress = 1; break; + case 'Z': arg_compress = 0; break; + case 'e': + if (*arg_erase_override != 0) + main_error(E_ARG_MULTI); + arg_erase_override = optarg; + break; + case 's': + while (*optarg) { + switch(*optarg++) { + case 'i': arg_image_map_show++; break; + case 's': arg_sector_map_show++; break; + case 'l': arg_sector_list_show++; break; + case 't': arg_timers_show++; break; + case 'T': arg_timers_extended_show++; break; + case 'c': arg_checksum_show++; break; + case 'x': arg_show_hexdump++; break; + } + } + break; + case 'r': + if (*arg_read != 0) + main_error(E_ARG_MULTI); + arg_read = optarg; + break; + case 'w': + if (*arg_write != 0) + main_error(E_ARG_MULTI); + arg_write = optarg; + break; + case 'l': arg_list_devices = 1; break; + case 'n': arg_dry_run++; break; + case 'k': arg_keep_going = 1; break; + case 'v': arg_verbose++; break; + case 'q': arg_verbose--; break; + case 'g': + if (*optarg != 'a' && + *optarg != 'c' && + *optarg != 'd' && + *optarg != 'x' && + *optarg != 'n') + main_error(E_BADARG); + arg_progress = *optarg; + break; + case 'o': + while (*optarg) { + tr(TrCmdLineParser, "main_args(): -o%s", optarg); + switch (*optarg) { + case 'e': arg_skip_erase = 1; break; + case 'R': arg_target_reset = 0; break; + case 'r': arg_target_reset = 2; break; + case 'o': arg_rom_bootloader = 1; break; + case 'O': arg_rom_bootloader = -1; break; + case 'l': arg_uart_level_convert = 1; break; + case 'b': + case 'm': arg_hexfile_type = *optarg; break; + case 'i': + optarg++; + arg_device_id0 = arg_long_get(); + if (*optarg == ',') { + optarg++; + arg_device_id1 = arg_long_get(); + } + else { + fprintf(stderr, "arg: '%s'", optarg); + main_error(E_BADARG); + } + optarg--; + break; + case 'd': + optarg++; + arg_boot_delay_rom = arg_long_get(); + if (*optarg == ',') { + optarg++; + arg_boot_delay_fluid = arg_long_get(); + } + else if (*optarg == 0) + arg_boot_delay_fluid = arg_boot_delay_rom; + else { + fprintf(stderr, "arg: '%s'", optarg); + main_error(E_BADARG); + } + optarg--; + break; + case '1': + case '2': + case '4': + arg_hexfile_memwidth = *optarg - '0'; + break; + default: + main_error(E_BADARG); + } + tr(TrCmdLineParser, "\n"); + optarg++; + } + break; + case 'd': + while (*optarg) { + switch (*optarg++) { + case 'h': main_debug_usage(); break; + case 'c': arg_debug_resume = 1; break; + case 'p': arg_debug_trace_pe = 1; break; + case 'r': arg_target_trace_enable = 1; break; + case 'o': arg_show_main_args = 1; break; + case 't': main_args_debug_trace(); break; + case 'v': fluid_compile_info(); exit(0); break; + case 'f': arg_tr_file = optarg; optarg += strlen(optarg); break; + case 'm': arg_tr_mask = arg_long_get(); break; + case 'i': arg_tr_spaces = arg_long_get(); break; + default: + main_error(E_BADARG); + } + } + optarg++; + break; + case 'i': main_example(*optarg); break; + case 'h': arg_usage = 1; break; + case 'V': fluid_welcome(); exit(0); + case 'y': arg_errorfd = 1; break; + // IMEI Protection + case 'I': + switch (*optarg++) { + case 'd': + if (*arg_die_id_file_name != 0) + main_error(E_ARG_MULTI); + if (*optarg == 0) + optarg++; + arg_die_id_file_name = optarg; + break; + case 'n': + if (*arg_imeisv != 0) + main_error(E_ARG_MULTI); + if (*optarg == 0) + optarg++; + arg_imeisv = optarg; + if (strlen(arg_imeisv) != C_IMEISV_DIGITS) { + fprintf(stderr, a_imeisv_format); + main_error(E_BADARG); + } + for (d_i = 0; d_i < C_IMEISV_DIGITS; d_i++) { + sscanf(arg_imeisv++, "%1c", &d_digit); + if (d_digit < '0' ||d_digit > '9') { + fprintf(stderr, a_imeisv_format); + main_error(E_BADARG); + } + } + arg_imeisv = optarg; // Re-assign arg_imeisv after error check + break; + case 'a': + if (*arg_platform_certificate_addr != 0) + main_error(E_ARG_MULTI); + if (*optarg == 0) + optarg++; + arg_platform_certificate_addr = optarg; + if ((strlen(arg_platform_certificate_addr) == C_PLATFORM_CERT_ADDR_DIGITS + 2) && + (arg_platform_certificate_addr[0] == '0') && + (arg_platform_certificate_addr[1] == 'x')) + arg_platform_certificate_addr += 2; + else if (strlen(arg_platform_certificate_addr) != C_PLATFORM_CERT_ADDR_DIGITS) { + fprintf(stderr, "The platform certificate address must comply with the following format, e.g.,\n0x04650000\n"); + main_error(E_BADARG); + } + break; + default: + main_error(E_BADARG); + } + break; + // Secure Calypso Plus + case 'R': + arg_request_certificate = 1; + d_ram_loader.b_certificate_request = C_TRUE; + break; + case 'D': + arg_delay_for_changing_cs5 = arg_long_get(); + if (arg_delay_for_changing_cs5 < 0) + main_error(E_BADARG); + break; + case 'U': + arg_uart_baudrate_during_cmd_download = arg_long_get(); + if (arg_uart_baudrate_during_cmd_download < 0) + main_error(E_BADARG); + break; + case 'u': + arg_uart_timeout_configuration = arg_long_get(); + d_ram_loader.d_uart_timeout = (UWORD32) arg_uart_timeout_configuration; + if (d_ram_loader.d_uart_timeout < 0) + main_error(E_BADARG); + break; + case 'B': + arg_block_size = arg_long_get(); + d_ram_loader.d_nb_byte_in_block = (UWORD32) arg_block_size; + if (d_ram_loader.d_nb_byte_in_block < 1) + main_error(E_BADARG); + break; + // End Secure Calypso Plus + default: + main_usage(); + exit(-E_BADARG); + } + } + + if (arg_usage) { + main_usage(); + exit(0); + } + + if (arg_show_main_args) { + printf("Command line option values:\n"); + printf("argv[0] = '%s'\n", argv[0]); + printf("\n"); + printf("port = %d\n", arg_uart_port); + printf("baudrate = %d\n", arg_uart_baudrate); + + printf("target_trace_enable = %d\n", arg_target_trace_enable); + printf("\n"); + } + +} + +static long arg_long_get(void) +{ + long value; + char *endp; + + errno = 0; + value = strtol(optarg, &endp, 0); + + if (errno == ERANGE || endp == optarg) { + fprintf(stderr, "Invalid command line number argument: '%s'", optarg); + exit(1); + } + optarg = endp; + return value; +} + + +/****************************************************************************** + * Globals and Main + ******************************************************************************/ + +int flowf(int level, char *format, ...) +{ + int n = 0; + va_list args; + char buf[1024]; + + if (level <= arg_verbose) { + va_start(args, format); + vsprintf(buf, format, args); + + n = fprintf(stdout, "%s", buf); + } + fflush(stdout); + + return n; +} + +int main(int argc, char *argv[]) +{ + int error; + + file_read_rc(".fluidrc"); + + main_args(argc, argv); + argv_0 = argv[0]; + + if (arg_verbose >= NORMAL) + fluid_welcome(); + + // Init tracing library + tr_init(arg_tr_spaces, arg_tr_file); + tr_mask(TrMAIN | arg_tr_mask); + + error = fluid_machine(); + + if (error < 0) + main_error(error); + + exit(-error); +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/fluid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/fluid.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,213 @@ +/****************************************************************************** + * FLUID (Flash Loader and Utility Independent of Device) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * Main + * + * $Id: fluid.h 1.43 Fri, 25 Oct 2002 14:46:33 +0200 tsj $ + * + ******************************************************************************/ + + +/****************************************************************************** + * Exception definitions + ******************************************************************************/ + +enum Exceptions { + E_OK = 0, /* Ok */ + + E_DRIVER_INIT = -3, /* Driver failed to initialize */ + E_DRIVER_WAIT = -4, /* Driver recv_wait() failed */ + + E_UART_INIT = -5, /* UART failed to initialize */ + E_UART_PARAM = -6, /* UART parameter bad or unsupported */ + E_UART_DRV_SEND = -7, /* UART driver transmit error */ + E_UART_DRV_RECV = -8, /* UART driver receive error */ + + E_RECV_TIMEOUT = -10, /* Receive timeout (no target reply) */ + E_RECV_ANTITIMEOUT = -11, /* Receive anti-timeout (target replied!?) */ + E_SEND_CHECKSUM = -12, /* Transmit checksum error */ + E_RECV_CHECKSUM = -13, /* Receive checksum error */ + E_PROTO_ERROR = -14, /* Protocol error (bad char from target) */ + E_INVALID = -15, /* Invalid command parameter */ + E_FIFO_OVERFLOW = -16, /* RX FIFO overflow in target */ + + E_FLASH_UNKNOWN = -20, /* Flash device unknown */ + E_FLASH_TIMEOUT = -21, /* Flash operation timeout */ + E_FLASH_VERIFY = -22, /* Flash verify error */ + E_FLASH_COMMAND = -23, /* Flash command sequence error */ + E_FLASH_VPPRANGE = -24, /* Flash Vpp range error */ + E_FLASH_LOCKED = -25, /* Flash block locked error */ + E_FLASH_ERROR = -26, /* Flash error (unknown!?) */ + E_TARGET_TYPE = -27, /* Target type not detected, unspecified or unknown */ + E_TARGET_MEMORY = -28, /* Target out of memory */ + + E_PARSER_EOF = -30, /* Unexpected end of file */ + E_PARSER_KEYWORD = -31, /* Syntax error: keyword expected */ + E_PARSER_STRING = -32, /* Syntax error: string expected */ + E_PARSER_NUMBER = -33, /* Syntax error: number expected */ + E_PARSER_END_BRACE = -34, /* Syntax error: missing end brace */ + E_PARSER_SYNTAX = -35, /* Syntax error */ + E_PARSER_MEMMAP = -36, /* Undefined flash memmap */ + E_PARSER_ALGORITHM = -37, /* Undefined flash algorithm */ + + E_BOOTLOADER = -40, /* Unsupported bootloader */ + + E_FILE_OPEN = -50, /* File open error */ + E_FILE_CLOSE = -52, /* File close error */ + E_FILE_READ = -53, /* File read error */ + E_FILE_WRITE = -54, /* File write error */ + E_FILE_FORMAT = -55, /* File format/syntax error */ + E_FILE_EMPTY = -56, /* File empty or unreadable? */ + E_FILE_BUF_SMALL = -57, /* File buffer too small */ + E_FILE_INPUT = -58, /* No input file name supplied */ + E_FILE_OUTPUT = -59, /* No output file name supplied */ + + E_ADDR_RANGE = -70, /* Bad address range */ + E_ERASE_SPEC = -71, /* Bad erase override specifier */ + E_READ_SPEC = -72, /* Bad memory read specifier */ + E_WRITE_SPEC = -73, /* Bad memory write specifier */ + + E_BADARG = -80, /* Bad argument or out of range */ + E_ARG_MULTI = -81, /* Multiple ambiguous arguments supplied */ + E_ARG_TOOMANY = -82, /* Too many arguments supplied */ + + E_MEMORY = -85, /* Out of memory */ + E_BUFFER = -86, /* Internal (static) buffer too small */ + + E_ROM_SSERVICE = -90, /* Secure ROM service error */ + + E_INTERNAL = -99, /* Internal program state error */ + + E_OS = -100 +}; + + +/****************************************************************************** + * Typedefs and Prototypes + ******************************************************************************/ + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned long uint32; +typedef signed char int8; +typedef signed short int16; +typedef signed long int32; + +void main_warning(int error); +void main_error(int error); +void main_fatal(int error); +void main_msg(char *format, ...); + +int flowf(int level, char *format, ...); + + +/****************************************************************************** + * Globals + ******************************************************************************/ + +#define ARG_FILE_LIST_SIZE_MAX 8 + +extern char *arg_file_list[ARG_FILE_LIST_SIZE_MAX]; +extern int arg_file_list_size; + +extern char *arg_erase_override; +extern char *arg_read; +extern char *arg_write; +extern int arg_checksum; +extern int arg_compress; +extern int arg_flash_read; +extern int arg_dry_run; +extern int arg_list_devices; +extern char arg_target_type; +extern int arg_image_map_show; +extern int arg_sector_map_show; +extern int arg_sector_list_show; +extern int arg_timers_show; +extern int arg_timers_extended_show; +extern int arg_checksum_show; +extern int arg_show_hexdump; +extern int arg_target_trace_enable; +extern int arg_progress; +extern char arg_hexfile_type; +extern char arg_hexfile_memwidth; + +extern int arg_target_reset; +extern int arg_rom_bootloader; +extern int arg_boot_delay_rom; +extern int arg_boot_delay_fluid; +extern int arg_device_id0; +extern int arg_device_id1; + +extern int arg_uart_port; +extern int arg_uart_baudrate; +extern char arg_uart_flowcontrol[2]; +extern char arg_uart_level_convert; + +extern char arg_verbose; +extern int arg_debug_resume; +extern int arg_debug_trace_pe; +extern int arg_keep_going; + +extern char *argv_0; + +extern int arg_trlevel; +extern int arg_trmask; +extern int arg_trspaces; +extern int arg_skip_erase; + +extern int arg_errorfd; + +// Secure Calypso Plus +extern char *arg_die_id_file_name; +extern char *arg_imeisv; +extern char *arg_platform_certificate_addr; +extern int arg_request_certificate; +extern int arg_delay_for_changing_cs5; +extern int arg_uart_baudrate_during_cmd_download; +extern int arg_uart_timeout_configuration; +extern int arg_block_size; + +// IMEI protection +#define C_IMEISV_DIGITS 16 +#define C_IMEISV_BYTES 8 +#define C_PLATFORM_CERT_ADDR_DIGITS 8 +#define C_PLATFORM_CERT_ADDR_BYTES 4 +// End Secure Calypso Plus + +enum VERBOSITY_LEVELS { + TESTOUTPUT = -2, // Only test output. + ALWAYS = -2, + QUIET = -1, // No messsages at all. + NORMAL = 0, // Overview message level. + VERBOSE = 1, // Detailed messages. Useful for diagnosing problems. + BLABBER = 2, // Very verbose messages. Useful for debugging. + DEBUG = 3 // Very very verbose messages. Useful for debugging. +}; + + +/****************************************************************************** + * Trace mask bits definition + ******************************************************************************/ + +enum TraceMaskBits { + TrMAIN = 1 << 24, + + TrUtility = TrMAIN | 0x000002, + TrMachines = TrMAIN | 0x000004, + + TrTargetDrv = TrMAIN | 0x000010, + TrTargetWait = TrMAIN | 0x000020, + + TrGetChar = TrMAIN | 0x000100, + TrPutChar = TrMAIN | 0x000200, + TrDriverGet = TrMAIN | 0x000400, + TrDriverPut = TrMAIN | 0x000800, + + TrHexRead = TrMAIN | 0x001000, + TrHexWrite = TrMAIN | 0x002000, + TrArgParser = TrMAIN | 0x004000, + TrCmdLineParser = TrMAIN | 0x008000, + + TrParser = TrMAIN | 0x010000 +}; diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/getopt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/getopt.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,674 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 + 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#ifndef __STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (optstring) + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { +#ifndef NOPRCS + return EOF; +#endif + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if (nameend - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + else + fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/getopt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/getopt.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,119 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +/* Josh's comment: many GNU developers are ignorant of C++ */ + +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int , char *const *, const char *); +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/lz.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/lz.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,59 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Simple LZ77 compressor (c) Texas Instruments, Jesper Pedersem TI-DK + * + * $Id: lz.h 1.4 Thu, 31 Oct 2002 13:12:27 +0100 tsj $ + * + ******************************************************************************/ + +#ifndef _LZ_H_ +#define _LZ_H_ 1 + +// Algorithmn efficiency constants + +// Don't compress unless we have a > THRESHOLD match +#define THRESHOLD 2 + +// Number of bits to use for position, when storing a match +#define POS_BITS 12 +#define POS_MASK 0x0FFF + +// Number of bits to use for length, when storing a match +#define LEN_BITS 4 +#define LEN_MASK 0xF000 + +// Size and size-mask of sliding window +#define WINDOW_SIZE (1 << POS_BITS) +#define WINDOW_MASK (WINDOW_SIZE - 1) + +// Maximum match length +#define MAX_MATCH ((1 << LEN_BITS) + THRESHOLD) + +// This structure is only being used by lzdecode/decompress(). +struct lz_s { + uint8 window[WINDOW_SIZE]; // Sliding window buffer + int16 window_pos; // Current window position + + // Static variables for get_bits() + uint32 bitbuf; // buffer for remaining bits + uint8 bitbuf_size; // number of bits in buffer + + // Global input/output buffer pointers and sizes + uint8 *buffer_in; + uint32 buffer_in_size; + uint32 total_in_size; + uint8 *buffer_out; + uint32 buffer_out_size; + uint32 total_out_size; +}; + + +void compress_init(void); +int compress(char *outbuf, char *inbuf, int size); + +void decompress_init(struct lz_s *plz); +int decompress(struct lz_s *plz, + unsigned char *outbuf, unsigned char *inbuf, int size); + +#endif diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/lzdecode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/lzdecode.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,142 @@ +/******************************************************************************* + * + * Simple LZ77 compressor (c) Texas Instruments, Jesper Pedersem TI-DK + * + * File format: + * --------------------------------------------------- + * | Tag | Data | Tag | Data | Tag | Data etc... + * --------------------------------------------------- + * + * Where TAG is 1 bit indicating how to interpret the following data + * (0 = uncompressed, 1 = compressed) + * + * Depending on TAG the Data is: + * 0 : One uncompressed char of raw data + * 1 : A length of and a pointer to a match in the previous data + * + * ---------------------------------------- + * Length + pointer = | Length (3 bits) | Position (12 bits) | + * ---------------------------------------- + * MSB LSB MSB LSB + * + * Compression threshold is 1 i.e. add 1 to Length to get the actual Length. + * + * It has been found that 5+14 bits is the most optimum for our kind of + * data, but we use only 3+12 bits for improoved speed. Compression is + * almost as good because we can set the threshold at 1 instead of 2 (2 char + * matches can be compressed to 12+3 bits) + * + * With a 12 bit position we can use 4K for the sliding window. Position + * indicates where the match exists as an absolute address into the + * window. This way we have a very simple "pseudo sliding window" which + * automatically enables RLE (Run Length Encoding). + * + * The code performs a "lazy" string search i.e. a match will be dropped if + * it prevents an even greater match for the very next string. This yeild + * slightly better compression (approx. 1%) at minor cost of compression + * speed - decompression time is the same! A second order lazy match could + * be implemented, but it gives an insignificant improovement of about 0.1% + * when compressing executeables + * + ******************************************************************************/ + +#if (TARGET == 0) +#include "fluid.h" +#include +#endif + +#include "lz.h" + + +/****************************************************************************** + * Globals + ******************************************************************************/ + + +/****************************************************************************** + * getchar/putchar + ******************************************************************************/ + +#define EOF -1 + +#define LZ_PUTCHAR(data) \ + *plz->buffer_out++ = data; \ + plz->buffer_out_size++; + + + +/****************************************************************************** + * Code + ******************************************************************************/ +uint8 get_byte(struct lz_s *plz) +{ + plz->buffer_in_size--; + return(*plz->buffer_in++); +} + +uint16 get_word(struct lz_s *plz) +{ + uint16 tmp; + + tmp = (*plz->buffer_in++) << 8; + tmp |= (*plz->buffer_in++); + plz->buffer_in_size -= 2; + return(tmp); +} + + +void decompress_init(struct lz_s *plz) +{ + plz->window_pos = 0; + plz->bitbuf = 0; + plz->bitbuf_size = 0; +} + +int decompress(struct lz_s *plz, + unsigned char *outbuf, unsigned char *inbuf, int size) +{ + int16 match_pos; + int16 match_len, i; + int8 ch; + uint8 tag_byte; + uint8 tag_pos; + uint16 tmp; + + + plz->buffer_out = outbuf; + plz->buffer_out_size = 0; + plz->buffer_in = inbuf; + plz->buffer_in_size = size; + + while(plz->buffer_in_size > 0) + { + tag_byte = get_byte(plz); + + for(tag_pos = 0x80; (plz->buffer_in_size > 0) && (tag_pos > 0x00); tag_pos >>= 0x01) + { + if(tag_byte & tag_pos) // Compressed? + { + tmp = get_word(plz); + match_len = (tmp >> POS_BITS) + THRESHOLD + 1; + match_pos = (tmp & POS_MASK); + for (i = 0; i < match_len; i++) + { + plz->window[plz->window_pos] = plz->window[WINDOW_MASK & (match_pos + i)]; + LZ_PUTCHAR(plz->window[plz->window_pos]); + plz->window_pos++; + plz->window_pos &= WINDOW_MASK; + } + } + else + { + ch = get_byte(plz); + plz->window[plz->window_pos] = ch; + LZ_PUTCHAR(ch); + plz->window_pos++; + plz->window_pos &= WINDOW_MASK; + } + } + } + return plz->buffer_out_size; +} + diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/lzencode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/lzencode.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,349 @@ +/******************************************************************************* + * + * Simple LZ77 compressor (c) Texas Instruments, Jesper Pedersem TI-DK + * + * File format: + * --------------------------------------------------- + * | Tag | Data | Tag | Data | Tag | Data etc... + * --------------------------------------------------- + * + * Where TAG is 1 bit indicating how to interpret the following data + * (0 = uncompressed, 1 = compressed) + * + * Depending on TAG the Data is: + * 0 : One uncompressed char of raw data + * 1 : A length of and a pointer to a match in the previous data + * + * ---------------------------------------- + * Length + pointer = | Length (3 bits) | Position (12 bits) | + * ---------------------------------------- + * MSB LSB MSB LSB + * + * Compression threshold is 1 i.e. add 1 to Length to get the actual Length. + * + * It has been found that 5+14 bits is the most optimum for our kind of + * data, but we use only 3+12 bits for improoved speed. Compression is + * almost as good because we can set the threshold at 1 instead of 2 (2 char + * matches can be compressed to 12+3 bits) + * + * With a 12 bit position we can use 4K for the sliding window. Position + * indicates where the match exists as an absolute address into the + * window. This way we have a very simple "pseudo sliding window" which + * automatically enables RLE (Run Length Encoding). + * + * The code performs a "lazy" string search i.e. a match will be dropped if + * it prevents an even greater match for the very next string. This yeild + * slightly better compression (approx. 1%) at minor cost of compression + * speed - decompression time is the same! A second order lazy match could + * be implemented, but it gives an insignificant improovement of about 0.1% + * when compressing executeables + * + * Searching in the window is done with help from an index and we maintain + * the window as a single linked list to further speed up the compression. + * + ******************************************************************************/ + +#include "fluid.h" +#include "lz.h" + +#include +#include +#include +#include + + +/****************************************************************************** + * + ******************************************************************************/ + +#define NIL -1 // Used for indexing purposes + +// When we find a match put it into a struct like this. +typedef struct { + int16 pos; + int8 len; +} match_def_t; + + +/****************************************************************************** + * Globals + ******************************************************************************/ + +static uint8 window[WINDOW_SIZE]; // Our sliding window buffer +static int16 window_pos; // And the current position in it +static uint8 lookahead; // number of bytes in the lookahead area + +// Global input/output buffer pointers +static uint8 *buffer_out; +static uint8 *buffer_in; +static uint32 buffer_out_size; +static uint32 buffer_in_size; + +static uint32 total_in_size = 0; +static uint32 total_out_size = 0; + +static uint8 *p_tag_byte = 0; +static uint8 tag_pos = 0; + +static int16 lookup[256]; // Table for looking up a link to any given character +static int16 lookup_end[256]; // The last link in the window. +static int16 next[WINDOW_SIZE]; // Contain links to next similar chars + + + +/****************************************************************************** + * getchar/putchar + ******************************************************************************/ + +static int lze_getchar(void) +{ + total_in_size++; + + if (buffer_in_size-- > 0) + return *buffer_in++; + + buffer_in_size++; + + return EOF; +} + +static int lze_putchar(unsigned char data) +{ + total_out_size++; + + *buffer_out++ = data; + buffer_out_size++; + + return 0; +} + +static int lze_putword(uint16 data) +{ + total_out_size += 2; + + *buffer_out++ = (uint8)((data >> 8) & 0x00FF); + *buffer_out++ = (uint8)(data & 0x00FF); + buffer_out_size += 2; + + return 0; +} + +/****************************************************************************** + * Code + ******************************************************************************/ + + +// Searches for the best possible match to the string at 'source_pos' within +// the window. Lazy searches is made faster by specifying a match to beat +// 'match_len' so we don't vaste time by testing too small matches. Will +// stop at any match 'max_len' in size. +match_def_t find_best_match(int16 source_pos, int16 match_len, int16 max_len) +{ + match_def_t current, best; + int16 start_pos; + + best.len = match_len; + + if ((start_pos = lookup[window[source_pos]]) != NIL) // Get the first entry + { + current.pos = start_pos; + do + { + if (window[WINDOW_MASK & (current.pos + best.len)] == + window[WINDOW_MASK & (source_pos + best.len)]) // Possible match? + { + current.len = 1; + + while((window[WINDOW_MASK & (current.pos + current.len)] == + window[WINDOW_MASK & (source_pos + current.len)]) && + current.len < max_len) + current.len++; + if (current.len > best.len) + best = current; + } + if (best.len >= max_len) + break; // no need to search for better matches when we have the best + + current.pos = next[current.pos]; // jump to next matching char + } while(current.pos != NIL); // All. possibilities tested? + } + if (best.len <= match_len) + best.len = 0; + return best; +} + +// Will remove 'count' links from 'begin' to make room for new data. Will be +// called when we need to overwrite some of the window by new lookahead +// chars. +void clear_index_positions(uint16 begin, uint16 count) +{ + uint16 i, pos; + + for (i = 0; i < count; i++) + { + pos = WINDOW_MASK & (begin +i ); + + if (lookup[window[pos]] == pos) { + if (lookup_end[window[pos]] == pos) + lookup[window[pos]] = lookup_end[window[pos]] = NIL; + else + lookup[window[pos]] = next[pos]; + } + } +} + + +// Generate indexes for a string, so the match routines can find the +// characters in it very fast! We need to clean up obsolete indexes after +// this routine has been called +void index_string(int16 source_pos, int16 source_len) +{ + int16 i, j; + uint8 c; + + for (i=0; i>= 0x01; + } +} + + + +// Puts an uncompressed char into the file and update the window +// position. We cannot just putc(data) because the offset might be any +// number of bits off. +void save_raw(uint8 data) +{ + update_tag_byte(0); + lze_putchar(data); + + index_string(window_pos, 1); + window_pos = WINDOW_MASK & (window_pos + 1); + lookahead--; +} + +// Puts a compressed match (length and position) into the file and update +// the window position. +void save_compressed(uint8 len, uint16 pos) +{ + uint16 tmp = 0x0000; + + update_tag_byte(1); + + tmp = ((uint8)(len - (THRESHOLD + 1))) << POS_BITS; + tmp |= ((uint16)(pos & POS_MASK)); + + lze_putword(tmp); + + index_string(window_pos, len); + window_pos = WINDOW_MASK & (window_pos + len); + lookahead -= len; +} + +void compress_init(void) +{ + int i; + + // Initialize - whole window is unindexed at beginning + for (i = 0; i < 256; i++) + lookup[i] = lookup_end[i] = NIL; + for (i = 0; i < WINDOW_SIZE; i++) + next[i] = window[i] = NIL; + + buffer_out_size = 0; + window_pos = 0; +} + +int compress(char *outbuf, char *inbuf, int size) +{ + int ch, eof; + match_def_t match, lazy_match; + + buffer_out = outbuf; + buffer_out_size = 0; + buffer_in = inbuf; + buffer_in_size = size; + if (size <= 0) + return 0; + + p_tag_byte = NULL; + tag_pos = 0x00; + + do + { + clear_index_positions(WINDOW_MASK & (window_pos + lookahead), MAX_MATCH); + + // (re-)fill the lookahead buffer from the bit-stream + while (lookahead < MAX_MATCH) { + eof = ((ch = lze_getchar()) == EOF); + window[WINDOW_MASK & (window_pos + lookahead++)] = (uint8) ch; + if (eof) { + window[WINDOW_MASK & (window_pos + --lookahead)] = 0; + break; + } + } + // End of compression? + if (lookahead == 0) + break; + + // Search for a match so we can compress the data + match = find_best_match(window_pos, THRESHOLD, lookahead); + + if (match.len > THRESHOLD) { + + lazy_match.len = 0; + + // check if the lazy match is better + if (match.len < lookahead - 1) { + lazy_match = find_best_match(WINDOW_MASK & (window_pos + 1), + match.len, lookahead-1); + } + if (lazy_match.len > match.len) { + // skip the current and use the lazy + save_raw(window[window_pos]); + save_compressed(lazy_match.len, lazy_match.pos); + } + else { + save_compressed(match.len, match.pos); + } + } + else { + // Compression failed - just stuff the raw data + save_raw(window[window_pos]); + } + + } while (!eof || lookahead > 0); + +// put_bits(-1, 0); // No more data, so flush the buffer and exit + + return buffer_out_size; +} + diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/machine.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/machine.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,2635 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * Original state-machine logic by Delta Technologies, Copyright, 2001. + * + * Core functionality. State machines and support functions. + * + * $Id: machine.c 1.35.1.37 Mon, 28 Apr 2003 08:49:16 +0200 tsj $ + * + ******************************************************************************/ + +#include "fluid.h" +#include "flash.h" +#include "target.h" +#include "fileio.h" +#include "../target/protocol.h" +#include "misc.h" +#include "lz.h" +#include "trace.h" +// Secure Calypso Plus +#include "../inc/ram_load.h" +#include "../inc/secure_types.h" + +#include +#include +#include +#include + +/****************************************************************************** + * Constants and typedefs + ******************************************************************************/ + +// Due to memory wrap/mirror used in flash_read_machine(), IMAGE_SIZE_MAX +// *must* be a power of two. +#define IMAGE_SIZE_MAX (8 * 1024 * 1024) + +#define IMAGE_CHUNK_SIZE 8192 + +#define ERASE_LIST_SIZE_MAX 256 +#define SECTOR_MAP_SIZE_MAX 256 + +#define TARGET_PROGRAM_SIZE_MAX (8 * 1024) + +#define READ_LIST_SIZE_MAX 40 + +#define RETRIES_MAX 30 + +// Default target receive delay in milli-seconds. +#define TARGET_RECV_DELAY 250 +#define TARGET_RECV_LONG_DELAY 1000 + +// Default target reset delay in milli-seconds. +#define TARGET_RESET_DELAY 200 + +// CS_MODE 0: Flash at 0x04000000 @ CS5 on E-Sample +#define CALP_OFFSET 0x04000000 + +/****************************************************************************** + * Globals + ******************************************************************************/ + +// Secure Calypso Plus +T_RAM_LOADER d_ram_loader; +T_FRAME d_frame; +UWORD16 d_certificate_length = 0; +char a_certified_cmd_file_name[] = "cmdp_cert.m0"; + +struct target_s { + uint32 cmd_load_addr; + uint32 method_load_addr; + const char type; + const char *name; + const char *prefix; +}; +// Note that the ROM bootloader of Calypso rev. A devices are unable to +// write the bottom 128kB of internal RAM. Therefore the address have been +// changed from 0x804000 to 0x0820000 +const struct target_s target[] = +{ + { 0x0000000, 0x0000000, 'u', "Unknown", "oops" }, + { 0x0000000, 0x0000000, 'u', "Unknown1", "oops1" }, + { 0x0000000, 0x0000000, 'G', "Gemini?", "gem?" }, + { 0x3004000, 0x3000000, 'U', "Ulysses", "uly" }, + { 0x0820000, 0x0800000, 'C', "Calypso", "cal" }, + { 0x0804000, 0x0800000, 'c', "Calypso Lite", "cal_l" }, + { 0x8020000, 0x8000100, 'P', "Calypso Plus", "cal_p" } +}; +int target_type; +int target_clk; // 13000000 or 14745600 + +struct device_s *device; + +uint8 target_program[TARGET_PROGRAM_SIZE_MAX]; +int target_program_size; +int target_fifo_size; + +uint8 image[IMAGE_SIZE_MAX]; +int image_size; // size of image buffer +int image_chunk_size; // number of bytes in each chunk +int image_size_in_chunks; // size of image buffer in chunks + +// Each byte in the image_map represents one chunk of the image. Each byte +// can have one of the following values: +// '\0' = no data in this chunk +// 's' = skip this chunk when programming +// 'c' = chunk checksum ok, skip this chunk when programming +// 'x' = used +uint8 image_map[IMAGE_SIZE_MAX / IMAGE_CHUNK_SIZE]; +int image_map_size; // number of entries in image_map + +// Each byte in the sector_map represents one sector. Each byte can have one +// of the following values: +// '\0' = sector unused (don't erase) +// 'c' = sector already empty/erased (don't erase) (not used) +// 's' = skip this sector when erasing (due to erase override) +// 'X' = force erase this sector (due to erase override) +// 'x' = erase this sector (normal case --- sector is covered by image) +int sector_map[SECTOR_MAP_SIZE_MAX]; +int sector_map_size; + +int erase_list[ERASE_LIST_SIZE_MAX]; +int erase_list_size; + +struct image_part_s read_list[READ_LIST_SIZE_MAX]; +int read_list_size; +int read_total_size; + +int image_map_count_used_chunks(void); +int image_map_update(void); +int sector_map_init(void); + +void image_map_show(void); +void sector_map_show(void); +void target_timers_show(void); + +void parse_arg_erase_override(char *p); +void parse_arg_read(char *p); +void parse_arg_write(char *p); + +void error_proto(char ch, char ch_expected); + +int target_type_set(uint16 code); + +// Secure Calypso Plus +void f_print_signalling_response(int level); +void f_print_certificate_platform_data(int level, T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA *p_certificate); +void f_print_certificate(int level, T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER *p_certificate); +void f_print_parameter_nack_status(int level, UWORD8 d_parameter_nack_sts); +void f_print_write_nack_status(int level, UWORD8 d_write_nack_sts); +UWORD8 f_convert_uart_baud_rate(UWORD32 d_baud_rate); +void target_imei_protection(void); + +/****************************************************************************** + * Main + ******************************************************************************/ + +void bootloader_machine(void); +void cmd_machine(void); +void flash_checksum_machine(void); +void flash_detect_machine(void); +void method_download_machine(void); +void flash_program_machine(void); +void flash_read_machine(void); +void target_reset_machine(void); + +void fluid_machine(void) +{ + int error; + + // If user has specifically asked fluid just to reset the target, we do + // that and only that! This way, we can use fluid just to reset the + // target without doing anything else! + if (arg_target_reset == 2 && arg_dry_run) { + flowf(VERBOSE, "Resetting target: "); + target_reset(0); + target_wait(0, TARGET_RESET_DELAY); + target_reset(1); + flowf(VERBOSE, "ok\n"); + } + + file_read_devices("devices.txt"); + + if (arg_list_devices) { + devices_list(); + exit(0); + } + + image_size = IMAGE_SIZE_MAX; + image_chunk_size = IMAGE_CHUNK_SIZE; + image_map_size = IMAGE_SIZE_MAX / image_chunk_size; + image_size_in_chunks = + (image_size + image_chunk_size - 1) / image_chunk_size; + + // Read the flash image file(s) unless user wants to read from the flash + if (*arg_read == 0) { + file_read_image(image, IMAGE_SIZE_MAX, image_map, image_chunk_size); + + // Optionally overwrite image with values given on the command-line + parse_arg_write(arg_write); + + if (arg_image_map_show) + image_map_show(); + } + + if ((error = target_driver_init(arg_uart_port, 115200, + arg_uart_flowcontrol)) < 0) + main_fatal(error); + + if (target_type_set(arg_target_type) != 0) + flowf(VERBOSE, "Target type '%s' selected.\n", target[target_type].name); + + // Conditionally disable tracing + if (arg_debug_trace_pe) + tr_enable(0); + + if (arg_debug_resume) { + // If resuming in command interpreter, we should set the baudrate + // because we do not pass through the code that normally sets it. + if ((error = target_driver_baudrate(arg_uart_baudrate)) < 0) + main_fatal(error); + } + else { + bootloader_machine(); + cmd_machine(); + } + if (*arg_read != 0) { + parse_arg_read(arg_read); + flash_read_machine(); + file_write_image(image, image_size, read_list); + } + else { + if (arg_checksum) + flash_checksum_machine(); + flash_detect_machine(); + if (!arg_debug_resume) { + method_download_machine(); + } + tr_enable(1); // Ensure full tracing is on + flash_program_machine(); + if (*arg_imeisv && *arg_platform_certificate_addr) + target_imei_protection(); + if (arg_timers_show) + target_timers_show(); + if (arg_target_reset == 1) + target_reset_machine(); + } +} + + +/****************************************************************************** + * Bootloader (TI Target Monitor) Access + ******************************************************************************/ + +// Invoke the Fluid bootloader embedded in the TI bootloader/target-monitor +// code. The command to enter the loader is 0xAA 0x01 0xDD, which must be +// received by the phone within 50ms from reset. + +int bootloader_is_rom; +int bootloader_is_secure_rom; // Secure Calypso Plus +int bootloader_blocksize_max; + +void bootloader_fluid_init(void); +void bootloader_rom_init(void); +void bootloader_secure_rom_init(void); // Secure Calypso Plus + +void bootloader_machine(void) +{ + // FIXME: why do we have to send an additional char (0) ? + uint8 sendbuf_rom[3] = { '<', 'i', 0x0 }; + uint8 sendbuf_fluid[3] = { 0xAA, 0x01, 0xDD }; + int i, error; + char ch1, ch2; + // Secure Calypso Plus + UWORD16 d_j; + + target_trace_enable(0); + + flowf(NORMAL, "Bootloader: "); + + // Wait a short while with power removed, then flush receive buffer. + target_power(1); + target_reset(0); + target_wait(0, TARGET_RESET_DELAY); + target_reset(1); + target_recv_reset(); + + // Continuously send Fluid Bootloader escape sequence until we get an + // acknowledgement. Note that we have to establish contact within 50ms + // from reset, otherwise we lose our chance! Note that we actually wait + // up to 500ms because the target may take some time to reset. + i = 0; + flowf(DEBUG, "(ROM/fluid-delay = %d/%d, ", + arg_boot_delay_rom, arg_boot_delay_fluid); + + switch (arg_rom_bootloader) { + case -1: + if ((error = target_driver_baudrate(115200)) < 0) + main_fatal(error); + break; + case +1: + if ((error = target_driver_baudrate(19200)) < 0) + main_fatal(error); + break; + } + while (1) + { + target_recv_reset(); + + // If we are allowed to try fluid bootloader... + if (arg_rom_bootloader != +1) { + // If we should ONLY try fluid bootloader... + flowf(DEBUG, "F"); + if (arg_rom_bootloader == 0) + if ((error = target_driver_baudrate(115200)) < 0) + main_fatal(error); + target_send(sendbuf_fluid, 3); + if (target_wait(1, arg_boot_delay_fluid) > 0 && + target_getchar() == PROTO_HELLO) { + bootloader_is_rom = 0; + bootloader_is_secure_rom = 0; // Secure Calypso Plus + break; + } + } + // If we are allowed to try ROM bootloader... + if (arg_rom_bootloader != -1) { + flowf(DEBUG, "R"); + if (arg_rom_bootloader == 0) + if ((error = target_driver_baudrate(19200)) < 0) + main_fatal(error); + target_send(sendbuf_rom, 3); + + if (target_wait(1, arg_boot_delay_rom) >= 1) { + ch1 = target_getchar(); + if (ch1 == '>') { + if (target_wait(1, arg_boot_delay_rom) >= 1) { + ch2 = target_getchar(); + if (ch2 == 'i') { + bootloader_is_rom = 1; + + // Secure Calypso Plus + if (target_wait(2, arg_boot_delay_rom) < 2) + flowf(DEBUG, ", Non-secure boot ROM code"); + else { + flowf(DEBUG, ", Secure Calypso Plus ROM)"); + ch1 = target_getchar(); + ch2 = target_getchar(); + d_ram_loader.d_romcode_version = (UWORD16)(ch1) & 0xFF; + d_ram_loader.d_romcode_version |= ((UWORD16)(ch2 & 0xFF)) << 8; + //d_ram_loader.d_romcode_version |= (((UWORD16)ch2) << 8) & 0xFF00; + + if (d_ram_loader.d_romcode_version == 0x0410 || d_ram_loader.d_romcode_version == 0x0411) { + bootloader_is_secure_rom = 1; + + if (target_wait((C_WORD32LGB * C_MD5HASHLG), TARGET_RECV_DELAY) < (C_WORD32LGB * C_MD5HASHLG)) + main_fatal(E_RECV_TIMEOUT); + + for (d_j = 0 ; d_j < (C_WORD32LGB * C_MD5HASHLG) ; d_j++) + d_ram_loader.a_hash_man_pub_key[d_j] = target_getchar(); + + if (target_wait((C_WORD32LGB * C_DIE_ID_SIZE), TARGET_RECV_DELAY) < (C_WORD32LGB * C_DIE_ID_SIZE)) + main_fatal(E_RECV_TIMEOUT); + + for (d_j = 0 ; d_j < (C_WORD32LGB * C_DIE_ID_SIZE) ; d_j++) + d_ram_loader.a_die_id[d_j] = target_getchar(); + + // SIGNALLING RESPONSE + f_print_signalling_response(VERBOSE); + + if (*arg_die_id_file_name != 0) { + if ((error = file_write_die_id(&d_ram_loader.a_die_id[0], arg_die_id_file_name)) < 0) { + flowf(NORMAL, "\n"); + main_fatal(error); + } + + flowf(NORMAL, "\nDie id retrieved and written to %s.\n", arg_die_id_file_name); + exit(0); + } + } + else { + flowf(NORMAL, "\nSecure Calypso Plus ROM Code Version 0x%4.4x is not supported by FLUID.\n", d_ram_loader.d_romcode_version); + main_fatal(E_BOOTLOADER); + } + } + // End Secure Calypso Plus + + break; + } + else + flowf(DEBUG, "?"); + } + } + } + } + // If target is still not responding, we could not control the reset + // line, so we ask the user to reset the target + if (i++ == RETRIES_MAX) + flowf (NORMAL, "(reset target) "); + } + if (!bootloader_is_secure_rom) + flowf(DEBUG, ") "); + + // Read the command interpreter image file. + if (bootloader_is_secure_rom) + target_program_size = file_read_cmd(target_program, TARGET_PROGRAM_SIZE_MAX, a_certified_cmd_file_name); + else + target_program_size = file_read_cmd(target_program, TARGET_PROGRAM_SIZE_MAX, "cmd.m0"); + + if (target_program_size == 0) + main_error(E_FILE_EMPTY); + + if (bootloader_is_secure_rom) + bootloader_secure_rom_init(); + else if (bootloader_is_rom) + bootloader_rom_init(); + else + bootloader_fluid_init(); + + flowf(NORMAL, ") ok\n"); +} + +void bootloader_fluid_init(void) +{ + int divider; + char version; + uint8 data[4]; + uint16 chip_id_code; + + flowf(NORMAL, "(fluid"); + + target_clk = 13000000; + + // Now send baudrate to make the target stop sending 'H'ello. + divider = target_uart_baudrate_divider_get(target_clk, 115200); + flowf(DEBUG, ", baudrate = "); + target_putchar(0); + target_putchar((char) divider); + flowf(DEBUG, "%d, ", 115200); + + // Wait a short while before flushing receive buffer. Then make sure + // that the target is indeed silent + target_wait(0, 10); + target_recv_reset(); + if (target_wait(1, 50) > 0) + main_fatal(E_RECV_ANTITIMEOUT); + + // NOTEME: The sequence below to query the Bootloader VERSION *has* to + // have 100ms + 100ms delays. It seems as unnecessarily large delays but + // practice shows that they cannot be shorter. To be investigated... + + // Get version of bootloader + target_putchar(PROTO_VERSION); + if (target_wait(1, TARGET_RECV_DELAY) < 1) + main_fatal(E_RECV_TIMEOUT); + version = target_getchar(); + flowf(NORMAL, ", version %c", version); + + // Bootloader revision 3 and upwards supports generic query + if (version < '3') { + main_fatal(E_BOOTLOADER); + } + + target_trace_enable(1); + target_putchar(PROTO_QUERY); + target_putchar(PROTO_QUERY_CHIP); + if (target_wait(4, TARGET_RECV_DELAY) < 4) + main_fatal(E_RECV_TIMEOUT); + target_recv(data, 4); + chip_id_code = data[0] + (data[1] << 8); + if (target_type_set(chip_id_code) == 0 || arg_verbose >= VERBOSE) { + flowf(VERBOSE, ", chipid = 0x%04X", chip_id_code); + if (target_type_set(chip_id_code) == 0) + main_fatal(E_TARGET_TYPE); + } + flowf(VERBOSE, ", %s", target[target_type].name); +} + +void bootloader_rom_init(void) +{ + int error; + char ch, version = '?'; + + // Initialization: 115200 bps, 39 MHz DPLL, no timeout + uint8 sendbuf[11] = { '<', 'p', 0x00, 0x0D, 0x14, 0x25, + 0x22, 0x00, 0x00, 0x00, 0x00}; + // Initialization: 115200 bps, 13 MHz DPLL, no timeout. + //uint8 sendbuf[11] = { '<', 'p', 0x00, 0x00, 0x1C, 0xE7, + // 0x22, 0x00, 0x00, 0x00, 0x00 }; + + flowf(NORMAL, "(ROM"); + + // Configure/init the ROM bootloader + flowf(VERBOSE, ", baudrate = %d", 115200); + target_send(sendbuf, 11); + + // Wait until DPLL is settled and target responds + if (target_wait(4, 300) < 4) + main_fatal(E_RECV_TIMEOUT); + if ((ch = target_getchar ()) != '>') + error_proto(ch, '>'); + if ((ch = target_getchar ()) != 'p') + error_proto(ch, 'p'); + + // Receive maximum blocksize + bootloader_blocksize_max = target_getchar(); + bootloader_blocksize_max += target_getchar() << 8; + bootloader_blocksize_max -= 10; // Subtract the block header + flowf(DEBUG, ", blocksize = %iB", bootloader_blocksize_max); + + if ((error = target_driver_baudrate (115200)) < 0) + main_fatal(error); + + flowf(NORMAL, ", version %c", version); + + // NOTEME: Can we be sure that it is always a Calypso type? + target_type_set('c'); +} + +// Secure Calypso Plus +void bootloader_secure_rom_init(void) +{ + int error; + UWORD8 d_char; + UWORD16 d_j; + + // cmdp_cert.m0 has been 16 bit aligned using hex470, so the memory width + // parameter is set to 2 bytes. + buffer_endian_convert(target_program, target_program_size, 2); + + // Check if firmware manufacturer certificate stored in flash is requested + if (arg_request_certificate) { + // Clear the request + arg_request_certificate = 0; + d_ram_loader.b_certificate_request = C_FALSE; + + // Certificate Request + d_frame.a_data[0] = '<'; + d_frame.a_data[1] = 'c'; + d_frame.d_max_byte = 2; + + target_send(&d_frame.a_data[0], d_frame.d_max_byte); + + // Certificate Response + target_expect_char('>', arg_boot_delay_rom); + target_expect_char('c', arg_boot_delay_rom); + + if (target_wait(2, TARGET_RECV_DELAY) < 2) + main_fatal(E_RECV_TIMEOUT); + + d_ram_loader.u_firm_cert.a_firm_cert[0] = target_getchar (); + d_ram_loader.u_firm_cert.a_firm_cert[1] = target_getchar (); + + d_certificate_length = (UWORD16)(d_ram_loader.u_firm_cert.a_firm_cert[0]) & 0xFF; + d_certificate_length |= ((UWORD16)(d_ram_loader.u_firm_cert.a_firm_cert[1]) << 8) & 0xFF00; + + // We have already read two bytes of the certificate for the CERT_SIZE + // and the certificate signature is handled later. + for (d_j = 2 ; d_j < d_certificate_length - (C_WORD32LGB * C_MANUF_SIG_SIZE); d_j++) { + if (target_wait(1, arg_boot_delay_rom * 4) > 0) + d_ram_loader.u_firm_cert.a_firm_cert[d_j] = target_getchar (); + else + main_fatal(E_RECV_TIMEOUT); + } + + for (d_j = 0; d_j < (C_WORD32LGB * C_MANUF_SIG_SIZE); d_j++) { + if (target_wait(1, arg_boot_delay_rom * 4) > 0) + d_ram_loader.a_Certsig[d_j] = target_getchar (); + else + main_fatal(E_RECV_TIMEOUT); + + d_ram_loader.u_firm_cert.a_firm_cert[d_j + sizeof(T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA) - (C_WORD32LGB * C_MANUF_SIG_SIZE)] = d_ram_loader.a_Certsig[d_j]; + } + + f_print_certificate_platform_data(NORMAL, &d_ram_loader.u_firm_cert.d_firm_cert); + } + + // Parameter Request + d_ram_loader.d_baud_rate = f_convert_uart_baud_rate(arg_uart_baudrate_during_cmd_download); + d_ram_loader.d_uart_timeout = arg_uart_timeout_configuration; // TODO: Verify that MSB byte is sent in first position. + + d_frame.a_data[0] = '<'; + d_frame.a_data[1] = 'p'; + d_frame.a_data[2] = d_ram_loader.d_baud_rate; + memcpy(&d_frame.a_data[3], &d_ram_loader.d_uart_timeout, sizeof(UWORD32)); + + d_frame.d_max_byte = 3 + sizeof(UWORD32); + + d_certificate_length = (UWORD16)(target_program[0]) & 0xFF; + d_certificate_length |= ((UWORD16)(target_program[1]) & 0xFF) << 8; + + for (d_j = 0 ; d_j < d_certificate_length; d_j++) + d_ram_loader.u_code_certificate.a_code_certificate[d_j] = target_program[d_j]; + + f_print_certificate(DEBUG, &d_ram_loader.u_code_certificate.d_code_certificate); + + // Send the data + target_send(&d_frame.a_data[0], d_frame.d_max_byte); + target_send(&target_program[0], d_certificate_length); + + // Parameter Response + if (target_wait(2, TARGET_RECV_DELAY) < 2) + main_fatal(E_RECV_TIMEOUT); + + if ((d_char = target_getchar ()) != '>') + error_proto(d_char, '>'); + + if ((d_char = target_getchar ()) != 'p') { + if (d_char == 'P') { + // PARAMETER_NACK_RESPONSE + if (target_wait(1, arg_boot_delay_rom) >= 1) { + d_ram_loader.d_param_req_sts = target_getchar(); + f_print_parameter_nack_status(NORMAL, d_ram_loader.d_param_req_sts); + } + } + error_proto(d_char, 'p'); + } + + // PARAMETER_ACK_RESPONSE + + flowf(NORMAL, "\n(Secure ROM"); + + if ((error = target_driver_baudrate (arg_uart_baudrate_during_cmd_download)) < 0) + main_fatal(error); + + // Configure/init the ROM bootloader + flowf(VERBOSE, ", UART baud rate during download of flash programmer, %s = %d Kbps", a_certified_cmd_file_name, arg_uart_baudrate_during_cmd_download); +} +// End Secure Calypso Plus + +/****************************************************************************** + * Command Interpreter Download + ******************************************************************************/ + +int cmd_baudrate(int baudrate); +void cmd_machine_fluid(void); +void cmd_machine_rom(void); +void cmd_machine_secure_rom(void); // Secure Calypso Plus + +void cmd_machine(void) +{ + char ramcs0, ch; + uint8 count = 0; + uint16 chip_id; + + flowf(VERBOSE, "Command Interpreter: ("); + + target_trace_enable(0); + + // Secure Calypso Plus + if (bootloader_is_secure_rom) + cmd_machine_secure_rom(); + else if (bootloader_is_rom) + cmd_machine_rom(); + else + cmd_machine_fluid(); + + // Now send 'H'ello command to target and get the response, such as + // hardware type etc. + while (count < RETRIES_MAX) { + target_putchar(PROTO_HELLO); + if (target_wait(1, TARGET_RECV_DELAY) >= 1) { + ch = target_getchar(); + flowf(DEBUG, ", received %c (0x%2.2x)", ch, ch); + if (ch == PROTO_READY) + break; + } + count++; + } + + if (count == RETRIES_MAX) + main_fatal(E_RECV_TIMEOUT); + + if (target_wait(5, TARGET_RECV_DELAY) < 4) + main_fatal(E_RECV_TIMEOUT); + + chip_id = (target_getchar() & 0xFF); + chip_id |= (target_getchar() & 0xFF) << 8; + ramcs0 = (target_getchar() == 'R'); + ch = target_getchar(); + flowf(BLABBER, ", SRAM = %dk", (1 << ch) / 1024); + target_fifo_size = target_getchar(); + flowf(DEBUG, ", fifo = %d", target_fifo_size); + + if (target_type_set(chip_id) == 0 || arg_verbose >= VERBOSE) { + flowf(BLABBER, ", "); + flowf(VERBOSE, "chipid = 0x%04X", chip_id); + if (target_type_set(chip_id) == 0) + main_fatal(E_TARGET_TYPE); + } + flowf(VERBOSE, ", %s", target[target_type].name); + + if (ramcs0) + flowf(VERBOSE, ", RAM"); + + // Configure target + target_putchar(PROTO_INIT); + target_putchar(target[target_type].type); + target_expect_char(PROTO_READY, TARGET_RECV_DELAY); + + // Change baudrate. First try to change to new baudrate. If this fails, + // try 115.2 Kbps. If this also fails, panic and bail out. + if (arg_uart_baudrate != 115200) { + flowf(VERBOSE, ", baudrate = "); + flowf(VERBOSE, "%d", arg_uart_baudrate); + if (!cmd_baudrate(arg_uart_baudrate)) { + arg_uart_baudrate = 115200; + flowf(VERBOSE, " %d", arg_uart_baudrate); + if (!cmd_baudrate(arg_uart_baudrate)) + main_fatal(E_RECV_TIMEOUT); + } + } + flowf(VERBOSE, ") "); + flowf(VERBOSE, "ok\n"); + + // Secure Calypso Plus + + // There is a bug in ROM code 0x0410 which means that the secure boot + // loader cannot boot if the firmware certificate size is greater than the + // max size of 0xFFF8. A workaround is to change the memory mapping on CS5 + // by initially setting DIP switches 9 and 10 to ON and thereby exchanging + // the mapping of RAM and flash. While waiting, set the DIP switches back + // to OFF. See SECURITY.txt and BUG03314 in CALPLUS228. + if (arg_delay_for_changing_cs5 != 0) { + flowf(NORMAL, "\nWaiting %d seconds for changing memory mapping on CS5 or connecting via JTAG...\n", arg_delay_for_changing_cs5); + target_wait(0, arg_delay_for_changing_cs5 * 1000); + } +} + +int cmd_baudrate(int baudrate) +{ + int error; + int divider; + char xxo; + + target_putchar(PROTO_BAUDRATE); + if (baudrate == 230400 || baudrate == 460800 || baudrate == 921600) { + // Changing the target clock frequency to 14 MHz + target_clk = 14745600; + // If we are using a 14 MHz compatible baud rate, we should enable the + // eXternal Xtal Oscillator of the target + xxo = PROTO_BAUDRATE_XXO; + } + else { + target_clk = 13000000; + xxo = 0; + } + + divider = target_uart_baudrate_divider_get(target_clk, baudrate); + target_putchar(xxo); + target_putchar((char) divider); + + if ((error = target_driver_baudrate(baudrate)) < 0) + main_fatal(error); + + // Wait for acknowledgement + if (target_wait(1, 2 * TARGET_RECV_DELAY) >= 1 && + target_getchar() == PROTO_READY) { + return 1; + } + else { + if ((error = target_driver_baudrate(115200)) < 0) + main_fatal(error); + return 0; + } +} + +void cmd_machine_fluid(void) +{ + uint8 sendbuf[1+4+2]; + int error; + + // Send 'Download' command header. Then wait for acknowledgement. + buf_put1(&sendbuf[0], PROTO_DOWNLOAD); + buf_put4(&sendbuf[1], target[target_type].cmd_load_addr); + buf_put2(&sendbuf[1+4], (uint16) target_program_size / 2); + target_send(sendbuf, 1+4+2); + flowf(BLABBER, "0x%X", target[target_type].cmd_load_addr); + if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0) + main_fatal(error); + + // Send data. Then wait for acknowledgement. + target_trace_enable(1); + target_send(target_program, target_program_size); + flowf(BLABBER, ", %d", target_program_size); +} + +void cmd_machine_rom(void) +{ + uint8 sendbuf[10], *buf; + int error, i; + int block_addr; + int block_offset = 0; + int block_size; + uint8 ch, blksum, cksum = 0; + + // NOTEME: Can we be sure that it is always a Calypso type? + target_type_set('c'); + + block_addr = target[target_type].cmd_load_addr; + + buffer_endian_convert(target_program, target_program_size, 2); + + flowf(BLABBER, "0x%X, ", target[target_type].cmd_load_addr); + + // Transfer the target program as blocks + while (block_offset < target_program_size) + { + block_size = target_program_size - block_offset; + if (block_size > bootloader_blocksize_max) + block_size = bootloader_blocksize_max; + + // Initialize block transfer + buf = sendbuf; + buf += buf_put1(buf, '<'); + buf += buf_put1(buf, 'w'); + buf += buf_put1(buf, 0x01); // block index - just use #1 - not important + buf += buf_put1(buf, 0x01); // block number - just use #1 - not important + buf += buf_put2no(buf, (uint16) block_size); + buf += buf_put4no(buf, block_addr + block_offset); + target_send(sendbuf, 10); + + // Send the data + target_send(&target_program[block_offset], block_size); + + // Calculate block check-sum + blksum = 5; + blksum += block_size & 0x00ff; + blksum += (((block_addr + block_offset) & 0xff000000) >> 24); + blksum += (((block_addr + block_offset) & 0x00ff0000) >> 16); + blksum += (((block_addr + block_offset) & 0x0000ff00) >> 8); + blksum += ( (block_addr + block_offset) & 0x000000ff); + for (i = block_offset; i < (block_offset + block_size); i++) + blksum += target_program[i]; + cksum += ~blksum; + + block_offset = block_offset + block_size; + + if ((error = target_expect_char ('>', TARGET_RECV_DELAY)) < 0) + main_fatal (error); + if ((error = target_expect_char ('w', TARGET_RECV_DELAY)) < 0) + main_fatal (error); + + flowf(BLABBER, "."); + } + flowf(BLABBER, ", %d", target_program_size); + target_wait(0, 100); + + // Request compare of checksum + target_putchar('<'); + target_putchar('c'); + target_putchar((char) ~cksum); + + if ((error = target_expect_char('>', TARGET_RECV_DELAY)) < 0) + main_fatal(error); + if ((error = target_expect_char('c', TARGET_RECV_DELAY)) < 0) + main_fatal(error); + if ((error = target_wait(1, TARGET_RECV_DELAY)) < 1) + main_fatal(error); + ch = target_getchar(); + flowf(DEBUG, ", cksum = 0x%x (0x%x)", ch, cksum); + if (ch != cksum) + main_fatal(E_SEND_CHECKSUM); + + // Branch to code + buf = sendbuf; + buf += buf_put1(buf, '<'); + buf += buf_put1(buf, 'b'); + buf += buf_put4no(buf, target[target_type].cmd_load_addr); + target_send(sendbuf, 6); + + if (target_wait(2, TARGET_RECV_DELAY) < 2) + main_fatal(E_RECV_TIMEOUT); + if ((ch = target_getchar()) != '>') + error_proto(ch, '>'); + if ((ch = target_getchar()) != 'b') + error_proto(ch, 'b'); + + target_wait(0, 100); +} + +// Secure Calypso Plus +void cmd_machine_secure_rom(void) +{ + UWORD8 d_char; + UWORD16 d_i; + + target_type_set('p'); + flowf(BLABBER, "0x%X", d_ram_loader.u_code_certificate.d_code_certificate.d_Addcode); + flowf(DEBUG, ")"); + + // Prepare the write command + d_ram_loader.d_nb_byte_in_block = (UWORD32) arg_block_size; + d_ram_loader.d_nb_byte_sent = 0; + d_ram_loader.d_block_address = d_ram_loader.u_code_certificate.d_code_certificate.d_Addcode; + + while (d_ram_loader.d_nb_byte_sent < d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize) { + flowf(DEBUG, "\nCurrent write parameters:\n"); + flowf(DEBUG, " Max Number of Bytes in Block: %ld\n", d_ram_loader.d_nb_byte_in_block); + flowf(DEBUG, " Block Address : 0x%8.8lx\n", d_ram_loader.d_block_address); + flowf(DEBUG, " Code Size : %ld\n", d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize); + flowf(DEBUG, " Bytes sent : %ld\n", d_ram_loader.d_nb_byte_sent); + + // Set block size + d_ram_loader.d_block_size = d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize - d_ram_loader.d_nb_byte_sent; + if (d_ram_loader.d_block_size > d_ram_loader.d_nb_byte_in_block) + d_ram_loader.d_block_size = d_ram_loader.d_nb_byte_in_block; + + flowf(DEBUG, " Block Size : %ld\n", d_ram_loader.d_block_size); + + // Write Request + d_frame.a_data[0] = '<'; + d_frame.a_data[1] = 'w'; + + // Send block size + for (d_i = 0; d_i < 32; d_i += 8) + d_frame.a_data[2 + d_i / 8] = (UWORD8)(d_ram_loader.d_block_size >> (24 - d_i)); + + // Send block address + for (d_i = 0; d_i < 32; d_i += 8) + d_frame.a_data[2 + sizeof(UWORD32) + d_i / 8] = (UWORD8)(d_ram_loader.d_block_address >> (24 - d_i)); + + d_frame.d_max_byte = 2 + sizeof(UWORD32) + sizeof(UWORD32); + + // Send the data + target_send(&d_frame.a_data[0], d_frame.d_max_byte); + target_send(&target_program[d_certificate_length + d_ram_loader.d_nb_byte_sent], d_ram_loader.d_block_size); + + // Update next block address + d_ram_loader.d_block_address += d_ram_loader.d_block_size; + d_ram_loader.d_nb_byte_sent += d_ram_loader.d_block_size; + + // Write Response + if (target_wait(2, TARGET_RECV_DELAY) < 2) + main_fatal(E_RECV_TIMEOUT); + + if ((d_char = target_getchar ()) != '>') + error_proto(d_char, '>'); + + if ((d_char = target_getchar ()) != 'w') { + if (d_char == 'W') { + // WRITE_NACK_RESPONSE + if (target_wait(1, arg_boot_delay_rom) >= 1) { + d_ram_loader.d_write_status = target_getchar(); + f_print_write_nack_status(NORMAL, d_ram_loader.d_write_status); + } + } + error_proto(d_char, 'w'); + } + + // WRITE_ACK_RESPONSE + } // End while + if (arg_verbose == BLABBER) + flowf(BLABBER, ", "); + else + flowf(DEBUG, "("); + + flowf(BLABBER, "%d", d_ram_loader.d_nb_byte_sent); + target_wait(0, 100); + + // Abort Request + d_frame.a_data[0] = '<'; + d_frame.a_data[1] = 'a'; + d_frame.d_max_byte = 2; + + target_send(&d_frame.a_data[0], d_frame.d_max_byte); + target_wait(0, 100); +} + +void f_print_signalling_response(int level) { + UWORD16 d_i; + + flowf(level, "\nSignalling Response:\n"); + + flowf(level, " ROM Code Version: 0x%4.4x\n", d_ram_loader.d_romcode_version); + + flowf(level, " Hash (ManPubKey): "); + for (d_i = 0; d_i < (C_WORD32LGB * C_MD5HASHLG); d_i++) { + if (d_i == (C_WORD32LGB * C_MD5HASHLG) / 2) + flowf(level, "\n "); + flowf(level, "0x%2.2x ", d_ram_loader.a_hash_man_pub_key[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Die Id : "); + for (d_i = 0; d_i < (C_WORD32LGB * C_DIE_ID_SIZE); d_i++) + flowf(level, "0x%2.2x ", d_ram_loader.a_die_id[d_i]); + flowf(level, "\n"); +} /* f_print_signalling_response() */ + +void f_print_certificate_platform_data(int level, T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA *p_certificate) { + UWORD16 d_i, d_j, d_max = 4; + + flowf(level, "\nFirmware Manufacturer Certificate:\n"); + flowf(level, "----------------------------------\n"); + + flowf(level, " Size of Certificate: %d bytes\n", p_certificate->d_manufacturer_certificate.d_Certsize); + flowf(level, " Type of Certificate: 0x%2.2x\n", p_certificate->d_manufacturer_certificate.d_Certtype); + flowf(level, " Emulation Request : 0x%2.2x\n", p_certificate->d_manufacturer_certificate.d_Debugrequest); + flowf(level, " Address of Code : 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Addcode); + flowf(level, " Size of Code : %ld bytes\n", p_certificate->d_manufacturer_certificate.d_Codesize); + flowf(level, " Entry Point Address: 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_CodeStartAdd); + + flowf(level, " Manufacturer Public Key:\n"); + flowf(level, " Public Modulus:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.d_Manpubkey.a_Modulus[d_i]); + } + flowf(level, "\n"); + flowf(level, " Public Modulus Length:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Manpubkey.d_ModulusLength); + flowf(level, " Public Exponent:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Manpubkey.d_Exponent); + + flowf(level, " Originator Public Key:\n"); + flowf(level, " Public Modulus:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.d_Origpubkey.a_Modulus[d_i]); + } + flowf(level, "\n"); + flowf(level, " Public Modulus Length:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Origpubkey.d_ModulusLength); + flowf(level, " Public Exponent:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Origpubkey.d_Exponent); + + flowf(level, " Originator Public Key Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSASIGLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_Origpubkeysig[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Software Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSASIGLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_Swsig[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Configuration Parameters:\n"); + flowf(level, " CONF_CS5 register: %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_conf_cs5); + flowf(level, " EXWS_CS5 register: %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_exws_cs5); + flowf(level, " EX_CTRL register : %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_ex_ctrl); + flowf(level, " CS image request : %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_cs_img_req); + flowf(level, " Flash size : %ld bytes\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_flash_size); + flowf(level, " Granularity : %ld words\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_granularity); + + flowf(level, " Die Id: "); + for(d_i = 0; d_i < (C_DIE_ID_SIZE); d_i++) { + flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_die_id[d_i]); + } + flowf(level, "\n"); + + if (p_certificate->d_manufacturer_certificate.d_Certsize > (sizeof(T_MANUFACTURER_CERTIFICATE) + (C_WORD32LGB * C_MANUF_SIG_SIZE))) { + flowf(level, " Platform Data:"); + d_j = d_max; + for(d_i = 0; d_i < (p_certificate->d_manufacturer_certificate.d_Certsize - sizeof(T_MANUFACTURER_CERTIFICATE) - (C_WORD32LGB * C_MANUF_SIG_SIZE)) / sizeof(UWORD32); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->a_platform_data[d_i]); + } + flowf(level, "\n"); + } + + flowf(level, " Certificate Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_MANUF_SIG_SIZE); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->a_Certsig[d_i]); + } + flowf(level, "\n"); +} /* f_print_certificate_platform_data() */ + +void f_print_certificate(int level, T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER *p_certificate) { + UWORD16 d_i, d_j, d_max = 4; + + flowf(level, "\nFlash Programmer Manufacturer Certificate:\n"); + flowf(level, "------------------------------------------\n"); + + flowf(level, " Size of Certificate: %d bytes\n", p_certificate->d_Certsize); + flowf(level, " Type of Certificate: 0x%2.2x\n", p_certificate->d_Certtype); + flowf(level, " Emulation Request : 0x%2.2x\n", p_certificate->d_Debugrequest); + flowf(level, " Address of Code : 0x%8.8lx\n", p_certificate->d_Addcode); + flowf(level, " Size of Code : %ld bytes\n", p_certificate->d_Codesize); + flowf(level, " Entry Point Address: 0x%8.8lx\n", p_certificate->d_CodeStartAdd); + + flowf(level, " Manufacturer Public key:\n"); + flowf(level, " Public Modulus:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_Manpubkey.a_Modulus[d_i]); + } + flowf(level, "\n"); + flowf(level, " Public Modulus Length:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_Manpubkey.d_ModulusLength); + flowf(level, " Public Exponent:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_Manpubkey.d_Exponent); + + flowf(level, " Originator Public key:\n"); + flowf(level, " Public Modulus:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->d_Origpubkey.a_Modulus[d_i]); + } + flowf(level, "\n"); + flowf(level, " Public Modulus Length:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_Origpubkey.d_ModulusLength); + flowf(level, " Public Exponent:\n"); + flowf(level, " 0x%8.8lx\n", p_certificate->d_Origpubkey.d_Exponent); + + flowf(level, " Originator Public Key Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSASIGLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->a_Origpubkeysig[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Software Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_RSASIGLG); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->a_Swsig[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Configuration Parameters:\n"); + flowf(level, " CONF_CS5 register: %4.4x\n",p_certificate->d_Confparam.d_conf_cs5); + flowf(level, " EXWS_CS5 register: %4.4x\n",p_certificate->d_Confparam.d_exws_cs5); + flowf(level, " EX_CTRL register : %4.4x\n",p_certificate->d_Confparam.d_ex_ctrl); + flowf(level, " CS image request : %4.4x\n",p_certificate->d_Confparam.d_cs_img_req); + flowf(level, " Flash size : %ld bytes\n",p_certificate->d_Confparam.d_flash_size); + flowf(level, " Granularity : %ld words\n",p_certificate->d_Confparam.d_granularity); + + flowf(level, " Die Id: "); + for(d_i = 0; d_i < (C_DIE_ID_SIZE); d_i++) { + flowf(level, "0x%8.8lx ", p_certificate->a_die_id[d_i]); + } + flowf(level, "\n"); + + flowf(level, " Certificate Signature:"); + d_j = d_max; + for (d_i = 0; d_i < (C_MANUF_SIG_SIZE); d_i++) { + if (d_j++ == d_max) { + flowf(level, "\n "); + d_j = 1; + } + flowf(level, "0x%8.8lx ", p_certificate->a_Certsig[d_i]); + } + flowf(level, "\n"); +} /* f_print_certificate() */ + +void f_print_parameter_nack_status(int level, UWORD8 d_parameter_nack_sts) { + flowf(level, "\nParameter NAck Response Status:\n"); + flowf(level, " 0x%2.2x", d_parameter_nack_sts); + + switch(d_parameter_nack_sts) { + case 0x01 : { flowf(level, " Incorrect baud rate\n"); break; } + case 0x02 : { flowf(level, " Incorrect certificate\n"); break; } + case 0x03 : { flowf(level, " Incorrect code address\n"); break; } + } + + flowf(level, "\n"); +} /* f_print_parameter_nack_status() */ + +void f_print_write_nack_status(int level, UWORD8 d_write_nack_sts) { + flowf(level, "\nWrite NAck Response Status:\n"); + flowf(level, " 0x%2.2x", d_write_nack_sts); + + switch(d_write_nack_sts) { + case 0x01 : { flowf(level, " Incorrect block address\n"); break; } + case 0x02 : { flowf(level, " Non-64 bytes block size\n"); break; } + case 0x03 : { flowf(level, " First block is not code address\n"); break; } + case 0x04 : { flowf(level, " Error in firmware signature check\n"); break; } + case 0x05 : { flowf(level, " Received code size does not match the code size in certificate\n"); break; } + case 0x06 : { flowf(level, " Error during block hashing\n"); break; } + } + + flowf(level, "\n"); +} /* f_print_write_nack_status() */ + +UWORD8 f_convert_uart_baud_rate(UWORD32 d_baud_rate) { + UWORD8 d_converted_baud_rate; + + switch (d_baud_rate) { + case 0: + case 812: + case 812500: { + d_converted_baud_rate = 0x00; + arg_uart_baudrate_during_cmd_download = 812500; + break; + } + case 1: + case 406: + case 406250: { + d_converted_baud_rate = 0x01; + arg_uart_baudrate_during_cmd_download = 406250; + break; + } + case 2: + case 203: + case 203125: { + d_converted_baud_rate = 0x02; + arg_uart_baudrate_during_cmd_download = 203125; + break; + } + case 3: + case 115: + case 115200: { + d_converted_baud_rate = 0x03; + arg_uart_baudrate_during_cmd_download = 115200; + break; + } + case 4: + case 57: + case 57600: { + d_converted_baud_rate = 0x04; + arg_uart_baudrate_during_cmd_download = 57600; + break; + } + case 5: + case 38: + case 38400: { + d_converted_baud_rate = 0x05; + arg_uart_baudrate_during_cmd_download = 38400; + break; + } + case 6: + case 28: + case 28800: { + d_converted_baud_rate = 0x06; + arg_uart_baudrate_during_cmd_download = 28800; + break; + } + case 7: + case 19: + case 19200: { + d_converted_baud_rate = 0x07; + arg_uart_baudrate_during_cmd_download = 19200; + break; + } + default: { + d_converted_baud_rate = 0x03; + arg_uart_baudrate_during_cmd_download = 115200; + break; + } + } + + return d_converted_baud_rate; +} /* f_convert_uart_baud_rate() */ + +void target_imei_protection(void) +{ + uint8 a_imeisv[C_IMEISV_BYTES]; + uint8 a_platform_cert_addr[C_PLATFORM_CERT_ADDR_BYTES]; + uint8 d_i, d_digit, d_temp; + uint8 d_error; + + flowf(NORMAL, "\nIMEI protection: "); + + if (arg_dry_run) { + flowf(NORMAL, "(dry-run) ok\n"); + return; + } + + target_putchar(PROTO_IMEI_PROTECT); + + // Send IMEI-SV + for (d_i = 0; d_i < C_IMEISV_DIGITS; d_i++) { + sscanf(arg_imeisv++, "%1d", &d_digit); + if (!(d_i & 1)) + d_temp = d_digit << 4; + else { + d_temp |= d_digit; + a_imeisv[d_i / 2] = d_temp; + } + } + + target_send(a_imeisv, C_IMEISV_BYTES); + target_expect_char(PROTO_READY, TARGET_RECV_DELAY); + + // Send platform certificate address + for (d_i = 0; d_i < C_PLATFORM_CERT_ADDR_DIGITS; d_i++) { + sscanf(arg_platform_certificate_addr++, "%1x", &d_digit); + if (!(d_i & 1)) + d_temp = d_digit << 4; + else { + d_temp |= d_digit; + a_platform_cert_addr[d_i / 2] = d_temp; + } + } + + target_send(a_platform_cert_addr, C_PLATFORM_CERT_ADDR_BYTES); + target_expect_char(PROTO_READY, TARGET_RECV_DELAY); + + // Check if address range is erased + if (target_wait(1, TARGET_RECV_DELAY) < 1) + main_fatal(E_RECV_TIMEOUT); + + d_error = target_getchar(); + if (d_error == PROTO_ERROR_VERIFY) { + flowf(NORMAL, "\n The address range for platform certificate and IMEI-SV is not erased.\n"); + main_fatal(E_FLASH_VERIFY); + } + + if (d_error != PROTO_READY) + error_proto(d_error, PROTO_READY); + + // Verify that the binding service call in target has succeeded + if (target_wait(1, TARGET_RECV_DELAY) < 1) + main_fatal(E_RECV_TIMEOUT); + + d_error = target_getchar(); + if (d_error == PROTO_ERROR_ROM_SSERVICE) { + flowf(NORMAL, "\n The Run-Time Loader (Binding) Service failed.\n"); + main_fatal(E_ROM_SSERVICE); + } + + if (d_error != PROTO_FLASH_START) + error_proto(d_error, PROTO_FLASH_START); + + // Receive acknowledgement for programming the platform certificate + if (target_wait(1, TARGET_RECV_DELAY) < 1) + main_fatal(E_RECV_TIMEOUT); + + d_error = target_getchar(); + if (d_error != PROTO_PROGRAM) { + flowf(NORMAL, "\n Platform certificate was not stored correctly in flash.\n"); + error_proto(d_error, PROTO_PROGRAM); + } + + // Receive acknowledgement for programming the IMEI-SV + if (target_wait(1, TARGET_RECV_DELAY) < 1) + main_fatal(E_RECV_TIMEOUT); + + d_error = target_getchar(); + if (d_error != PROTO_PROGRAM) { + flowf(NORMAL, "\n IMEI-SV was not stored correctly in flash.\n"); + error_proto(d_error, PROTO_PROGRAM); + } + + flowf(NORMAL, "Platform certificate and IMEI-SV stored in flash.\n"); +} + +// End Secure Calypso Plus + +/****************************************************************************** + * Flash Detect + ******************************************************************************/ + +void flash_detect_machine(void) +{ + uint8 data[12]; + uint16 m0, d0, m1, d1, d1ex1, d1ex2; + + flowf(NORMAL, "Flash Detect: "); + target_trace_enable(0); + + if (arg_device_id0 != -1 || arg_device_id1 != -1) { + // Device auto-detection is disabled + m0 = m1 = arg_device_id0; + d0 = d1 = arg_device_id1; + flowf(VERBOSE, "(ID override) "); + } + else { + target_putchar(PROTO_DETECT); + if (target_wait(12, TARGET_RECV_DELAY) < 12) + main_fatal(E_RECV_TIMEOUT); + + target_recv(data, 12); + m0 = data[0] + (data[1] << 8); // Intel manufacturer id + d0 = data[2] + (data[3] << 8); // Intel device id + m1 = data[4] + (data[5] << 8); // AMD manufacturer id + d1 = data[6] + (data[7] << 8); // AMD device di + d1ex1 = data[8] + (data[9] << 8); // AMD extended device id + d1ex2 = data[10] + (data[11] << 8); // AMD extended device id + } + + // Lookup multi-id device + if ((m1 == MANUFACT_AMD || m1 == MANUFACT_FUJITSU) && d1 == 0x227E) { + flowf(NORMAL, "Multi-id device detected: (0x%04X, 0x%04X, 0x%04X)\n" + , d1, d1ex1, d1ex2); + d1 = (d1ex1 << 8) | (d1ex2 & 0xFF); + flowf(DEBUG, "Multi-id converted to: 0x%04X\n", d1); + + if ((device = device_lookup_by_id(m1, d1)) == NULL) { + flowf(NORMAL, "Id not found, lookup default multi-id conf.\n"); + // Backward compatible/keep default multi-id configuration + device = device_lookup_by_id(m1, 0x227E); + } + } + + // Lookup device with AMD and Intel ids + else if ((device = device_lookup_by_id(m1, d1)) == NULL) + device = device_lookup_by_id(m0, d0); + + if (device == NULL || arg_verbose >= DEBUG) { + flowf(NORMAL, "(0x%02X, 0x%04X, 0x%02X, 0x%04X) ", m0, d0, m1, d1); + if (device == NULL) + main_fatal(E_FLASH_UNKNOWN); + } + + if (arg_verbose >= NORMAL) { + device_print(device, 's'); + flowf(NORMAL, " ok\n"); + } + + // Note that device_id is only 0x227E if the Multi-id configuration not + // is found in device.txt (else device_id will be the 'converted' id) + if (arg_device_id0 == -1 && arg_device_id1 == -1 && + (device->manufacturer_id == MANUFACT_FUJITSU || + device->manufacturer_id == MANUFACT_AMD ) + && device->device_id == 0x227E) { + flowf(NORMAL, "Warning: Extended device codes are supported when detecting flash devices,\n"); + flowf(NORMAL, " but the detected multi-id configuration is not found in device.txt. \n"); + flowf(NORMAL, " Update the device.txt manually if the default flash device is invalid.\n"); + flowf(NORMAL, " Currently, %s %s is used as default.\n\n", + manufacturer_name_lookup_by_id(device->manufacturer_id), device->name); + } +} + + +/****************************************************************************** + * Method Load + ******************************************************************************/ + +void method_download_machine(void) +{ + char sendbuf[1+2+4]; + int error; + + target_program_size = file_read_method(target_program, + TARGET_PROGRAM_SIZE_MAX, + device); + + flowf(BLABBER, "Method Download: "); + target_trace_enable(0); + + // Send 'Download' command header. Then wait for acknowledgement. + buf_put1(&sendbuf[0], PROTO_DOWNLOAD); + buf_put4(&sendbuf[1], target[target_type].method_load_addr); + buf_put2(&sendbuf[1+4], (uint16) target_program_size / 2); + target_send(sendbuf, 1+4+2); + flowf(BLABBER, "(0x%X", target[target_type].method_load_addr); + if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0) + main_fatal(error); + + // Send data. Then wait for acknowledgement. + target_trace_enable(1); + target_send(target_program, target_program_size); + flowf(BLABBER, ", %d) ", target_program_size); + if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0) + main_fatal(error); + + flowf(BLABBER, "ok\n"); +} + + +/****************************************************************************** + * Flash Checksum + ******************************************************************************/ + +int time_checksum; + +#define CHECKSUMS 8 + +void flash_checksum_machine(void) +{ + unsigned char sendbuf[1+1+4+4*CHECKSUMS], *buf; + uint32 addr, cksum, mycksum; + uint16 word; + uint8 data[4]; + int index = 0, chunks, n, i, j; + int line = -1; + struct { + uint32 index; + uint32 addr; + uint32 mycksum; + } block[CHECKSUMS]; + + chunks = image_map_count_used_chunks(); + flowf(NORMAL, "Checksumming (%d * %dkB = %dkB): ", + chunks, image_chunk_size / 1024, + chunks * image_chunk_size / 1024); + target_trace_enable(0); + + time_checksum = stopwatch_start(); + while (chunks > 0) + { + n = (chunks > CHECKSUMS ? CHECKSUMS : chunks); + + buf = sendbuf; + buf += buf_put1(buf, PROTO_CHECKSUM); + buf += buf_put1(buf, (unsigned char) n); + buf += buf_put4(buf, image_chunk_size); + + for (i = 0; i < n; i++) { + // Find next used entry in image_map + while (image_map[index] != 'x' && index < image_map_size) + index++; + + if (index == image_map_size) + break; + + addr = index * image_chunk_size; + block[i].index = index; + block[i].addr = addr; + + buf += buf_put4(buf, addr); + + index++; + } + target_send(sendbuf, buf - sendbuf); + + // Compute checksums while we wait for reply + for (i = 0; i < n; i++) { + index = block[i].index; + addr = block[i].addr; + for (j = 0, mycksum = 0; j < image_chunk_size; j += 2) { + word = (image[addr + j + 1] << 8) | image[addr + j + 0]; + mycksum += word * ((addr + j) & 0xFFFF); + } + block[i].mycksum = mycksum; + } + + if (target_wait(4 * n, TARGET_RECV_LONG_DELAY) <= 0) + main_fatal(E_RECV_TIMEOUT); + + for (i = 0; i < n; i++) { + target_recv(data, 4); + cksum = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24); + mycksum = block[i].mycksum; + index = block[i].index; + + if (cksum == mycksum) + image_map[index] = 'c'; + + if (arg_checksum_show) { + // This is a far from perfect dump of checksums... We don't know + // the exact block number of each checksum in a line. + if (line != (int) index / 4) { + flowf(NORMAL, "\n%4d:", index); + line = index / 4; + } + if (cksum == mycksum) + flowf(NORMAL, "%08X ", cksum); + else + flowf(NORMAL, "%08X/%08X ", cksum, mycksum); + + } + else if (arg_verbose >= VERBOSE) { + flowf(VERBOSE, "%c", (image_map[index] == 'c' ? 'c' : '.')); + } + } + index++; + chunks -= n; + } + time_checksum = (stopwatch_stop(time_checksum) + 50) / 100; + flowf(BLABBER, " (%d.%ds)", time_checksum / 10, time_checksum % 10); + flowf(NORMAL, " ok\n"); +} + + +/****************************************************************************** + * Flash Program + ******************************************************************************/ + +int time_program; +int programs_recv, programs_send, erasures; +int index, src_size; +uint32 dst; +char *src; + +void flash_erase_machine(void); +int flash_operation_wait(int delay); +int flash_program_next(void); + +void flash_program_machine(void) +{ + uint8 cksum, sendbuf[1+4+4]; + int i, te, tp, tt; + int expected, chunks, total_size, sectors; + int image_chunk_size_old = image_chunk_size; + char ch; + + programs_recv = programs_send = erasures = 0; + index = 0; + + // Prepare erase + erase_list_size = sectors = sector_map_init(); + i = image_map_count_used_chunks(); + + if (arg_skip_erase) + erase_list_size = 0; + + time_compute(device, erase_list_size, + i * image_chunk_size, i, &te, &tp, &tt); + + flowf(BLABBER, "Estimated time (uncompressed) "); + if (te + tp > tt) + flowf(BLABBER, "(erase + program = total): %ds + %ds = %ds\n", + te/1000, tp/1000, te/1000 + tp/1000); + else + flowf(BLABBER, "transfer: %ds\n", tt/1000); + + chunks = image_map_count_used_chunks(); + flowf(NORMAL, "Program: (%d sectors, %d*%dk=%dk) ", + sectors, + chunks, image_chunk_size / 1024, + chunks * image_chunk_size / 1024); + target_trace_enable(1); + + // Expected total number of acknowledgements + expected = erase_list_size + chunks; + + if (arg_dry_run) { + flowf(NORMAL, "(dry-run) "); + if (arg_dry_run == 2) + image_chunk_size = 0; + } + + if (arg_skip_erase) + flowf(NORMAL, "(skip erase) "); + + // Start erase + flash_erase_machine(); + + if (arg_dry_run == 0 || arg_dry_run == 2) + progress_begin(expected); + + // Start the flash state machine in the target + target_putchar(PROTO_FLASH_START); + target_putchar(arg_compress ? PROTO_COMPRESS : 0); + ch = flash_operation_wait(TARGET_RECV_DELAY); + if (ch != PROTO_READY) + error_proto(ch, PROTO_READY); + if (arg_compress) { + compress_init(); + total_size = 0; + // Worst case "compressed" buffer is 9/8 of original data size. + if ((src = malloc(9 * image_chunk_size / 8)) == NULL) + main_fatal(E_MEMORY); + } + + time_program = stopwatch_start(); + + if (flash_program_next() && *arg_erase_override == 0) { + //Nothing to program + target_putchar(PROTO_FLASH_END); + if ((ch = target_expect_char(PROTO_FLASH_END, TARGET_RECV_DELAY)) < 0) + main_fatal(ch); + } + else { + while (programs_recv + erasures < expected) { + total_size += src_size; + + if (arg_progress == 'x') + flowf(NORMAL, "(0x%06X, %d) ", dst, src_size); + + if (src_size > 0 && + (arg_dry_run == 0 || arg_dry_run == 2)) + { + buf_put1(&sendbuf[0], PROTO_PROGRAM); + buf_put4(&sendbuf[1], src_size); + buf_put4(&sendbuf[1+4], dst); + target_send(sendbuf, 1+4+4); + + for (i = 0, cksum = 0; i < src_size; i++) + cksum += src[i]; + cksum = (0x100 - cksum) & 0xFF; + + // Wait for acknowledgement of command start + //while ((ch = flash_operation_wait(4000)) != PROTO_READY) + // ; + + // Make sure that the target FIFO not is full + while (programs_send - programs_recv >= target_fifo_size) + flash_operation_wait(4000); + + // Send data bytes and checksum. + target_send(src, src_size); + target_putchar(cksum); + programs_send++; + + if (arg_verbose >= DEBUG) + progress_update_simple('T'); + } + + // We compress and send next block while sending + // current block to target + if (arg_dry_run == 0 || arg_dry_run == 2) { + if (flash_program_next()) { + // Wait for remaining acknowledgements + flowf(DEBUG, "W%d", expected - (programs_recv + erasures)); + while (programs_recv + erasures < expected) + flash_operation_wait(4000); + target_putchar(PROTO_FLASH_END); + if ((ch = target_expect_char(PROTO_FLASH_END, TARGET_RECV_DELAY)) < 0) + main_fatal(ch); + break; + } + else { + // Wait for acknowledgement of data transfer + while ((ch = flash_operation_wait(4000)) != PROTO_READY) + ; + } + } + else { + if (flash_program_next()) + break; + } + } + } + + if (arg_dry_run == 0 || arg_dry_run == 2) + progress_end(programs_recv + erasures); + flowf(NORMAL, "ok\n"); + + time_program = stopwatch_stop(time_program); + flowf(VERBOSE, "Used time: "); + if (arg_compress && chunks) { + image_chunk_size = image_chunk_size_old; + flowf(VERBOSE, "(compressed to %d%%) ", + 100 * total_size / (chunks * image_chunk_size)); + } + flowf(VERBOSE, "%.1fs ok\n", (double) time_program / 1000); +} + + +/****************************************************************************** + * Flash Program sub functions + ******************************************************************************/ + +void flash_erase_machine(void) +{ + uint8 sendbuf[1+2+4*256]; // NOTEME: static limit! + int i; + char ch; + + if (arg_dry_run) + erase_list_size = 0; + + if (erase_list_size > 0) { + buf_put1(&sendbuf[0], PROTO_ERASE); + buf_put2(&sendbuf[1], (uint16) erase_list_size); + for (i = 0; i < erase_list_size; i++) + buf_put4(&sendbuf[1+2+4*i], erase_list[i]); + target_send(sendbuf, 1+2+4*erase_list_size); + + if ((ch = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0) + main_fatal(ch); + } +} + +// Setup address and size of next block to transfer. Also compress the +// block. Return non-zero if this was the last block. Otherwise return zero. +int flash_program_next(void) +{ + int oldindex; + + // Find next used entry in image_map + while (index < image_map_size && image_map[index] != 'x') + index++; + + oldindex = index; + + if (index < image_map_size) { + dst = index * image_chunk_size; + if (arg_compress) { + src_size = compress(src, &image[dst], image_chunk_size); + } + else { + src = &image[dst]; + src_size = image_chunk_size; + } + index++; + } + else { + dst = 0xFFFFFFFF; + src_size = 0; + } + + return (oldindex >= image_map_size); +} + +int flash_operation_wait(int delay) +{ + int n; + char ch; + + tr(TrMachines, "fow() "); + + if ((n = target_wait(1, delay)) < 1) + main_fatal(E_RECV_TIMEOUT); + + // Minor optimization to avoid waiting for every char... + while (n--) { + ch = target_getchar(); + + if (ch == PROTO_READY) { + if (arg_verbose >= DEBUG) + progress_update_simple('R'); + if (programs_send - programs_recv >= target_fifo_size) + progress_update_simple('W'); // Wait target FIFO is full + break; + } + + switch (ch) { + case PROTO_READY: + break; // just return the char + case PROTO_PROGRAM: + programs_recv++; + progress_update_simple('P'); + progress_update(programs_recv + erasures); + break; // just return the char + case PROTO_ERASE: + erasures++; + progress_update_simple('E'); + progress_update(programs_recv + erasures); + if (arg_progress == 'x') + flowf(NORMAL, "E "); + break; // just return the char + case PROTO_FLASH_END: + progress_update_simple('Z'); + break; + case PROTO_ERROR_CKSUM: + main_fatal(E_SEND_CHECKSUM); + case PROTO_ERROR_MEMORY: + main_fatal(E_MEMORY); + case PROTO_ERROR_VERIFY: + main_fatal(E_FLASH_VERIFY); + case PROTO_ERROR_FLASH_TIMEOUT: + main_fatal(E_FLASH_TIMEOUT); + case PROTO_ERROR_FLASH_COMMAND: + main_fatal(E_FLASH_COMMAND); + case PROTO_ERROR_FLASH_VPP: + main_fatal(E_FLASH_VPPRANGE); + case PROTO_ERROR_FLASH_LOCKED: + main_fatal(E_FLASH_LOCKED); + case PROTO_ERROR_FLASH_UNKNOWN: + main_fatal(E_FLASH_ERROR); + case PROTO_ERROR_INVALID: + main_fatal(E_INVALID); + case PROTO_ERROR_FIFO_OVERFLOW: + main_fatal(E_FIFO_OVERFLOW); + case PROTO_ERROR: + default: + flowf(NORMAL, "flash_operation_wait() got unexpected char '%c' 0x%02X (%d chars waiting)\n", (' ' <= ch && ch < 127 ? ch : '.'), ch, n); +// main_fatal(E_PROTO_ERROR); + } + } + + return ch; +} + +void target_timers_show(void) +{ + int data[8], i; + struct { + double erase; + double program; + double recvonly; + double recv; + double comm; + double setup; + double overhead; + double dezip; + double erase_sector; + double program_word; + } timer; + double tmp, total, resolution = (double) (16 * 32 * 1000 / 13e6); + + // Use only 14 MHz for D-/E-Sample specific rates (not for e.g. 812.5K). + if ((arg_uart_baudrate == 230400) || (arg_uart_baudrate == 460800) || (arg_uart_baudrate == 921600)) + resolution = resolution * 13 / 14.746; + + flowf(NORMAL, + "Target Timers:\n" + " (erase + program + recvonly + recv + comm + setup + overhead + dezip)\n"); + + if (arg_dry_run) + for (i = 0; i < 8; i++) data[i] = 0; + else { + target_putchar(PROTO_TIMERS); + if (target_wait(sizeof(data), TARGET_RECV_DELAY) <= 0) + main_fatal(E_RECV_TIMEOUT); + target_recv(&data, sizeof(data)); + } + + // Convert all timers to milliseconds + timer.erase = resolution * data[0]; + timer.program = resolution * data[1]; + timer.recvonly = resolution * data[2]; + timer.recv = resolution * data[3]; + timer.comm = resolution * data[4]; + timer.setup = resolution * data[5]; + timer.overhead = resolution * data[6]; + timer.dezip = resolution * data[7]; + + // Because we do erase-while-transfer in the target the reported erase + // time has some inherent tolerance, especially at low baudrates. It + // might make sense to adjust the sector erase time by half the chunk + // transfer time, although this is just another approximation!? + +// total = timer.erase + timer.program + timer.recvonly + timer.recv + timer.comm + timer.setup; + flowf(NORMAL, "%8.0f + %7.0f + %8.0f + %6.0f + %5.0f + %5.0f + %8.0f + %5.0f\n", + timer.erase, timer.program, timer.recvonly, timer.recv, + timer.comm, timer.setup, timer.overhead, timer.dezip); + + flowf(DEBUG, "resolution = %f, %d, %d, %d, %d, %d, %d, %d, %d\n", + resolution, data[0], data[1], data[2], data[3], data[4], + data[5], data[6], data[7]); + + if (arg_timers_extended_show) { + int chunks, size_total, not_zero = 1; + flowf(NORMAL, "Target Timers Extended:\n"); + + if (erase_list_size == 0 || arg_dry_run) + flowf(NORMAL, " Erase time = 0.0ms/sector\n"); + else { + timer.erase_sector = timer.erase / erase_list_size / 1000; + flowf(NORMAL, " Erase time = %.1fs / %d sectors = %.0fms/sector\n", + timer.erase / 1000, erase_list_size, timer.erase_sector * 1000); + } + + chunks = image_map_count_used_chunks(); + size_total = chunks * image_chunk_size; + if (size_total == 0 || arg_dry_run) { + size_total = 1; + not_zero = 0; + flowf(NORMAL, " Program time = 0.0us/word = 0ms/MB\n"); + } + else { + timer.program_word = timer.program / 1000 / (size_total / 2); + flowf(NORMAL, " Program time = %.1fs / %dkwords = %.2fus/word = %.0fms/MB\n", + timer.program / 1000, size_total / 1024 / 2, + timer.program_word * 1000000, + timer.program_word * 1000 * 512 * 1024); + } + + flowf(NORMAL, " Receive-only time = %.1fs = %.0fms/MB\n", + timer.recvonly / 1000, + not_zero * timer.recvonly * 1024 * 1024 / size_total); + + flowf(NORMAL, " Overhead time = %.1fs = %.0fms/MB\n", + timer.overhead / 1000, + not_zero * timer.overhead * 1024 * 1024 / size_total); + + flowf(NORMAL, " Setup time = %.1fs = %.0fms/MB\n", + timer.setup / 1000, + not_zero * timer.setup * 1024 * 1024 / size_total); + + total = timer.erase + timer.program + timer.recvonly + timer.overhead + + timer.setup; + flowf(NORMAL, + "Total time: (erase + prog + recvonly + overhead + setup) = %.1fs\n", + total / 1000); + + flowf(NORMAL, " Receive time = %.1fs = %.0fms/MB\n", + timer.recv / 1000, timer.recv * 1024 * 1024 / size_total); + + flowf(NORMAL, " Communication time = %.1fs = %.0fms/MB\n", + timer.comm / 1000, timer.comm * 1024 * 1024 / size_total); + + flowf(NORMAL, " Dezip time = %.1fs = %.0fms/MB\n", + timer.dezip / 1000, timer.dezip * 1024 * 1024 / size_total); + + // Now compute the overall performance. Note that the theoretical + // limit compuation is somewhat flawed in that it assumes 64kB + // sector sizes. + + tmp = (double) not_zero * total / 1000 * 1024 * 1024 / size_total; + flowf(NORMAL, " Performance = %.0fs/MB\n", tmp); +#if 0 + flowf(BLABBER, " (%.1f * min possible, %.1f * theoretical limit)", + time_program / (timer.program + timer.erase), + tmp / (16 * timer.erase_sector + 512 * 1024 * timer.program_word)); + flowf(NORMAL, "\n"); +#endif + } +} + + +/****************************************************************************** + * Flash Read + ******************************************************************************/ + +int time_read; + +void flash_read_machine(void) +{ + int i; + unsigned char sendbuf[1+4+4]; + int size, read_size, done_size = 0; + int read_size_max = image_chunk_size; + uint32 addr, index = 0; + uint8 cksum, mycksum; + + flowf(NORMAL, "Reading Flash: (%dkB) ", read_total_size / 1024); + target_trace_enable(0); + + //read_size_max = 256; + time_read = stopwatch_start(); + progress_begin(read_total_size / read_size_max); + + while (read_list[index].size > 0) + { + // Find next range to read + size = read_list[index].size; + addr = read_list[index].addr; + index++; + + while (size > 0) + { + read_size = (size > read_size_max ? read_size_max : size); + + // Read address interval is [MIN..MAX[ + // If odd MAX address was specified round up to next even + if ((read_size % 2 == 1) && (read_size < read_size_max)) read_size++; + + if (arg_progress == 'x') + flowf(DEBUG, "(0x%06X, %d) ", addr, read_size); + + if (!arg_dry_run) + { + buf_put1(&sendbuf[0], PROTO_READ); + buf_put4(&sendbuf[1] , read_size); + buf_put4(&sendbuf[1+4], addr); + target_send(sendbuf, 1+4+4); + + if (target_wait(read_size, TARGET_RECV_LONG_DELAY) <= 0) + main_fatal(E_RECV_TIMEOUT); + // Note that we wrap/mirror memory each 'image_size' bytes + target_recv(&image[addr & (image_size - 1)], read_size); + for (i = 0, mycksum = 0; i < read_size; i++) + mycksum ^= image[(addr + i) & (image_size - 1)]; + + if (target_wait(1, TARGET_RECV_DELAY) <= 0) + main_fatal(E_RECV_TIMEOUT); + cksum = target_getchar(); + + if (cksum != mycksum) + main_fatal(E_RECV_CHECKSUM); + } + done_size += read_size; + size -= read_size; + addr += read_size; + + progress_update(done_size / read_size_max); + progress_update_simple('0' + read_size / 1024); + } + } + progress_end(done_size / read_size_max); + flowf(NORMAL, " ok\n"); + + time_read = stopwatch_stop(time_read); + flowf(VERBOSE, "Used time: %ds ok\n", time_read); +} + + +/****************************************************************************** + * Flash Reset + ******************************************************************************/ + +void target_reset_machine(void) +{ + int error; + + flowf(VERBOSE, "Resetting target: "); + + if (arg_dry_run) { + flowf(VERBOSE, "(dry-run) "); + } + else { + target_putchar(PROTO_RESET); + target_expect_char(PROTO_READY, TARGET_RECV_DELAY); + } + flowf(VERBOSE, "ok\n"); +} + + +/****************************************************************************** + * Show Functions (dump internal data structures) + ******************************************************************************/ + +void image_map_show(void) +{ + uint32 addr; + int i; + + flowf(ALWAYS, "image map of %d * %dkB chunks (x = used, s = skip, c = checksum ok):", + image_size_in_chunks, image_chunk_size / 1024); + + // For each chunk of the image usage map... + for (i = 0, addr = 0; i < image_size_in_chunks; i++) + { + if ((i % 64) == 0) { + flowf(ALWAYS, "\n%4dkB: ", (int) addr >> 10); + } + putchar(image_map[i] != 0 ? image_map[i] : '.'); + addr += image_chunk_size; + } + putchar('\n'); +} + +void sector_map_show(void) +{ + struct sector_s *sectors = device->memmap->sectors; + int i; + + char n; + uint32 addr = 0; + + flowf(ALWAYS, "sector map (x = used, s = skip, X = force erase):"); + + // For each sector of the device definition... + for (i = 0; i < device->memmap->size; i++) + { + if ((addr & 0xFFFFF) == 0) { + flowf(ALWAYS, "\n%2dMB: ", (int) addr >> 20); + } + n = (sector_map[i] ? sector_map[i] : '.'); + putchar(n); + + addr += sectors[i].size; + } + putchar('\n'); +} + + +/****************************************************************************** + * Utility Functions + ******************************************************************************/ + +int image_is_within(int start, int end) +{ + return !(start < 0 || image_size <= start || + end < 0 || image_size < end || + end < start); +} + +// Set the image usage map in the range [start..end[ as used +int image_map_set(int start, int end) +{ + if (!image_is_within(start, end)) + return -1; + + do { + image_map[start / image_chunk_size] = 'x'; + start += image_chunk_size; + } while (start < end); + + return 0; +} + +int target_type_set(uint16 code) +{ + // If there is an override from the command-line, use that + if (arg_target_type != 0) + code = arg_target_type; + + switch (code) + { + case 'h': // Hercules + case 'u': // Ulysses + case '3': // Chipset 3 + case CHIP_ID_ULYSSES_0: + case CHIP_ID_ULYSSES_A: + case CHIP_ID_HERCULES_A: + case CHIP_ID_HERCULES_B: + target_type = 3; + break; + + case 'c': // Calypso + case '4': // Chipset 4 + // case 's': // Samson + case CHIP_ID_CALYPSO_A: + case CHIP_ID_CALYPSO_B: + case CHIP_ID_CALYPSO_C: + target_type = 4; + break; + + case 'l': // Calypso Lite + case CHIP_ID_CALYPSO_L: + target_type = 5; + break; + + case 'p': // Calypso Plus + case CHIP_ID_CALYPSO_PLUS: + case CHIP_ID_CALYPSO_PLUS_A: + target_type = 6; + break; + + default: + target_type = 0; + } + + return target_type; +} + +int image_map_count_used_chunks(void) +{ + int used, i; + + // For each image chunk + for (i = 0, used = 0; i < image_size_in_chunks; i++) { + if (image_map[i] == 'x') + used++; + } + return used; +} + +// When the sector_map have been changed, we have to update the image_map +// such that we don't attempt to program within sectors that are not going +// to be programmed anyway (due to the erase override). We also have to +// program chunks contained in sectors that *are* going to be erased, even +// though the chunks have been check-summed ok. +int image_map_update(void) +{ + struct sector_s *sectors = device->memmap->sectors; + int changed, chunks, i, j; + int map_index; + + map_index = 0; + changed = 0; + + // For each sector of the device definition... + for (i = 0; i < device->memmap->size; i++) { + chunks = sectors[i].size / image_chunk_size; + // For each image--map-chunk contained in current sector... + for (j = 0; j < chunks; j++) { + if (!(sector_map[i] == 'x' || sector_map[i] == 'X') && + image_map[map_index + j] == 'x') { + image_map[map_index + j] = 's'; // skip + changed++; + } + else if ((sector_map[i] == 'x' || sector_map[i] == 'X') + && image_map[map_index + j] == 'c') { + image_map[map_index + j] = 'x'; // include! + changed++; + } + } + map_index += chunks; + } + return changed; +} + +int sector_map_init(void) +{ + struct sector_s *sectors = device->memmap->sectors; + int map_index; + int used_list_index; + int used, chunks, i, j; + + sector_map_size = SECTOR_MAP_SIZE_MAX; + + memset(sector_map, 0, sector_map_size); + + // Generate the sector_map from the image_map + map_index = 0; + + // For each sector of the device definition... + for (i = 0; i < device->memmap->size; i++) { + + chunks = sectors[i].size / image_chunk_size; + + // For each image-usage-map-chunk contained in current sector... + for (j = 0, used = 0; j < chunks; j++) + if (image_map[map_index + j] == 'x') + used++; + + sector_map[i] = (used ? 'x' : 0); + map_index += chunks; + } + + parse_arg_erase_override(arg_erase_override); + + // Generate the erase_list + // For each sector of the device definition... + used_list_index = 0; + for (i = 0; i < device->memmap->size; i++) { + if (sector_map[i] == 'x' || sector_map[i] == 'X') + erase_list[used_list_index++] = sectors[i].addr; + } + + if (arg_sector_map_show) + sector_map_show(); + + if (arg_sector_list_show) { + flowf(ALWAYS, "sector used list: "); + for (i = 0; i < used_list_index; i++) + flowf(ALWAYS, "0x%06X ", erase_list[i]); + putchar('\n'); + } + + return used_list_index; +} + +int parse_range(char *p, char **p_end, int *n1, int *n2) +{ + char *my_end; + int read_offset_calp = (*arg_read != 0 && target[target_type].type == 'P'); + + *n2 = 0; + + *n1 = strtol(p, &my_end, 0); + if (p == my_end) + return 0; // error: no chars converted + + if (*my_end == 'k' || *my_end == 'K') { + *n1 <<= 10; + if (read_offset_calp) *n1 += CALP_OFFSET; + my_end++; + } + else if (*my_end == 'M') { + *n1 <<= 20; + if (read_offset_calp) *n1 += CALP_OFFSET; + my_end++; + } + + *p_end = my_end; + if (my_end[0] != '.' || my_end[1] != '.') + return 1; + p = my_end + 2; + + *n2 = strtol(p, &my_end, 0); + if (p == my_end) + return 0; // error: no chars converted + + if (*my_end == 'k' || *my_end == 'K') { + *n2 <<= 10; + if (read_offset_calp) *n2 += CALP_OFFSET; + my_end++; + } + else if (*my_end == 'M') { + *n2 <<= 20; + if (read_offset_calp) *n2 += CALP_OFFSET; + my_end++; + } + + *p_end = my_end; + return 2; +} + +// Parse and decode the erase override command line option string. The +// sector_map is updated accordingly. +void parse_arg_erase_override(char *p) +{ + struct sector_s *sectors = device->memmap->sectors; + int sector_bottom, sector_top; + int changed, i; + + tr(TrBegin| TrArgParser, "erase_override:\n"); + while (*p) + { + char *p_end; + int num, sign, n1 = 0, n2 = 0; + + if (*p != '-' && *p != '+') + main_error(E_ERASE_SPEC); + + sign = (*p == '-' ? -1 : +1); + p++; + + if (*p == '*') { + sign = sign * 2; + p++; + } + else { + num = parse_range(p, &p_end, &n1, &n2); + if (num == 0) + main_error(E_ERASE_SPEC); + p = p_end; + } + + switch (sign) { + case -1: + case +1: + if (num == 1) { + // Support for absolute addresses on Calypso Plus + if (n1 >= CALP_OFFSET) n1 -= CALP_OFFSET; + + if (n1 > sector_map_size) { + // For all sectors... + for (i = 0; i < device->memmap->size; i++) { + sector_bottom = sectors[i].addr; + sector_top = sector_bottom + sectors[i].size - 1; + + if (n1 >= sector_bottom && n1 < sector_top) { + sector_map[i] = (sign > 0 ? 'X' : 's'); + break; + } + } + } + else + sector_map[n1] = (sign > 0 ? 'X' : 's'); + tr(TrArgParser, "%c%d\n", sign > 0 ? '+' : '-', n1); + } + else { + // Support for absolute addresses on Calypso Plus + if (n1 >= CALP_OFFSET && n2 >= CALP_OFFSET) { + n1 -= CALP_OFFSET; + n2 -= CALP_OFFSET; + } + + if (n1 > sector_map_size || n2 > sector_map_size) { + // n1 and n2 must respresent an address range + if (n1 >= n2) + main_error(E_ERASE_SPEC); + + // For all sectors... + for (i = 0; i < device->memmap->size; i++) + { + sector_bottom = sectors[i].addr; + sector_top = sector_bottom + sectors[i].size - 1; + + // If either sector bottom or top is contained in + // [n1..n2[ + if ((n1 <= sector_bottom && sector_bottom < n2) || + (n1 <= sector_top && sector_top < n2)) { + sector_map[i] = (sign > 0 ? 'X' : 's'); + } + } + } + else { + // n1 and n2 must respresent a sector range + for (i = n1; i < n2; i++) + sector_map[i] = (sign > 0 ? 'X' : 's'); + } + tr(TrArgParser, + "%c%d..%d\n", sign > 0 ? '+' : '-', n1, n2); + } + break; + case -2: + case +2: + // Fill whole sector_map... + for (i = 0; i < device->memmap->size; i++) + sector_map[i] = (sign > 0 ? 'X' : 's'); + tr(TrArgParser, "%c*\n", sign > 0 ? '+' : '-'); + break; + } + // skip optional comma + if (*p == ',') + p++; + } + tr(TrEnd| TrArgParser, ""); + + changed = image_map_update(); + + // If image map was changed, we trace it again. + if (changed && arg_image_map_show) + image_map_show(); +} + +void parse_arg_read(char *p) +{ + read_total_size = 0; + read_list_size = 0; + + tr(TrArgParser, "parse_arg_read() {\n"); + while (*p) + { + char *p_end; + int num, n1, n2; + + if (*p == '*') { + n1 = 0; + n2 = 0x1000000; // sufficiently large (16MB) + p++; + } + else { + num = parse_range(p, &p_end, &n1, &n2); + tr(TrArgParser, "parse_range('%s', ...)\n" + " { #%d, p_end = '%s', n1 = 0x%x, n2 = 0x%x } %d\n", + p, read_list_size, p_end, n1, n2, num); + if (num != 2 || n1 > n2) + main_error(E_ADDR_RANGE); + p = p_end; + } + read_list[read_list_size].addr = n1; + read_list[read_list_size].size = n2 - n1; + read_total_size += n2 - n1; + read_list_size++; + if (read_list_size >= READ_LIST_SIZE_MAX) + main_error(E_ARG_TOOMANY); + + if (*p == 0) + break; + + if (*p == ',') + p++; + else + main_error(E_READ_SPEC); + } + // Terminate the read_list with zeroes. + read_list[read_list_size].addr = 0; + read_list[read_list_size].size = 0; + + tr(TrArgParser, "}\n"); +} + +void parse_arg_write(char *p) +{ + tr(TrArgParser, "parse_arg_write() {\n"); + + while (*p) + { + char bytes[1024]; + char *p_end; + int num, n1, n2; + int index, value, size, i; + + num = parse_range(p, &p_end, &n1, &n2); + tr(TrArgParser, "parse_range('%s', ...)\n" + " { p_end = '%s', n1 = 0x%x, n2 = 0x%x } %d\n", + p, p_end, n1, n2, num); + + if (num < 1 || num > 2) + main_error(E_ADDR_RANGE); + + p = p_end; + + if (*p++ != '=') + main_error(E_WRITE_SPEC); + + tr(TrArgParser, " { "); + if (*p == 0) + main_error(E_WRITE_SPEC); + + index = 0; + while (*p) { + if (*p == '\"') { + // Collect text string + p++; + tr(TrCont|TrArgParser, "'"); + while (*p) { + if (*p == '\"') + break; + if (p[0] == '\\' && p[1] == '\"') + p++; // skip leading backslash + if (p[0] == '\\' && p[1] == '\\') + p++; // skip leading backslash + tr(TrCont|TrArgParser, "%c", *p); + bytes[index] = *p++; + if (index++ >= sizeof(bytes)) + main_error(E_WRITE_SPEC); + } + if (*p++ != '\"') + main_error(E_WRITE_SPEC); + tr(TrCont|TrArgParser, "' "); + } + else { + // Collect byte string + value = strtol(p, &p_end, 0); + if (p == p_end) + main_error(E_WRITE_SPEC); + if (value < 0 || 255 < value) + main_error(E_WRITE_SPEC); + bytes[index] = value; + if (index++ >= sizeof(bytes)) + main_error(E_WRITE_SPEC); + p = p_end; + + tr(TrCont|TrArgParser, "0x%x ", value); + } + if (*p == ':' || *p == 0) + break; + if (*p == ',') + p++; + } + size = index; + tr(TrArgParser, "} %d\n", size); + + if (num == 1) { + // Support for absolute addresses on Calypso Plus + if (n1 >= CALP_OFFSET) n1 -= CALP_OFFSET; + + n2 = n1 + size; + } + else if (n1 >= CALP_OFFSET && n2 >= CALP_OFFSET) { + n1 -= CALP_OFFSET; + n2 -= CALP_OFFSET; + } + + if (image_map_set(n1, n2) < 0) + main_error(E_ADDR_RANGE); + + index = 0; + for (i = n1; i < n2; i++) { + image[i] = bytes[index++]; + if (index >= size) + index = 0; + } + if (*p == ':') + p++; + } + tr(TrArgParser, "}\n"); +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/misc.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,253 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Miscellaneous Utility Functions + * + * $Id: misc.c 1.14 Fri, 11 Oct 2002 08:40:21 +0200 mmj $ + * + ******************************************************************************/ + +#include "misc.h" +#include "fluid.h" +#include "trace.h" + +#include +#include + +#if defined(MSC) || defined(BCC) +#include "windows.h" +#endif + + +/****************************************************************************** + * File And Path Name Functions + ******************************************************************************/ + +// Return the length of the directory name preceding the leafname. The +// terminating slash is included in the length. Length can be zero, if there +// is no dirname. +int dirname_len(const char *pathname) +{ + char *p; + int len; + + tr(TrUtility, "dirname_len('%s')\n", pathname); + + if ((len = strlen(pathname)) == 0) + return 0; + + p = (char *) (pathname + len - 1); + + tr(TrUtility, "{ %d }\n", len); + + while (*p != '/' && *p != '\\' && len-- > 1) + p--; + + return len; +} + +// Construct a full pathname from and . The full +// pathname is copied in the buffer of size . On success, the +// full length of the pathname is returned. Otherwise, if the buffer is too +// small, -1 is returned. NOTE: The is supposed to end with a +// slash. If not, the leafname part (if present) of the will be +// removed. +int pathname_make(char *buf, int size, const char *dirname, const char *leafname) +{ + int dir_len, leaf_len, result; + + tr(TrBegin|TrUtility, "pathname_make(*, %d, '%s', '%s') {\n", + size, dirname, leafname); + + dir_len = dirname_len(dirname); + leaf_len = strlen(leafname); + + if (dir_len > size - leaf_len - 1) + result = E_BUFFER; + else { + memcpy(buf, dirname, dir_len); + strcpy(buf + dir_len, leafname); + result = dir_len + leaf_len; + } + + tr(TrEnd|TrUtility, "} %d\n", result); + + return result; +} + + +/****************************************************************************** + * Utility Funcions + ******************************************************************************/ + +// Return the base 2 logarithm of . Return -1 if is zero. +unsigned int log2(unsigned int number) +{ + int result = -1; + + while (number > 0) { + number >>= 1; + result++; + } + return result; +} + + +/****************************************************************************** + * Progress and Timer Functions + ******************************************************************************/ + +static int progress_mul; +static int progress_index; +static char progress_string[35] = "(---------------------------------)"; +static char progress_backup[33] = +"\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b"; + +void progress_begin(int n) +{ + tr(TrUtility, "progress_begin(%d)\n", n); + + progress_index = 0; + + switch (arg_progress) { + case 'a': + // We select a progress multiplier that is a power of two. Then we + // generate a progress indicator that is in the range [16..32[ chars + // in length. + progress_mul = n / 32; + progress_mul = 1 << (log2(progress_mul) + 1); + n = (n + progress_mul - 1) / progress_mul; + + progress_string[1 + n] = ')'; + progress_string[1 + n + 1] = 0; + + flowf(NORMAL, "%s\b%s", + progress_string, &progress_backup[32 - n]); + break; + case 'c': + break; + case 'd': + break; + } +} + +void progress_update_simple(int n) +{ + tr(TrUtility, "progress_update_simple(%d)\n", n); + + switch (arg_progress) { + case 'c': + flowf(NORMAL, "%c", n); + break; + } +} + +void progress_update(int n) +{ + char ch; + + tr(TrUtility, "progress_update(%d)\n", n); + + switch (arg_progress) { + case 'a': + if (n / progress_mul > progress_index) { + progress_index++; + flowf(NORMAL, "*"); + } + + n = n % progress_mul; + ch = n + (n <= 9 ? '0' : 'A' - 10); + flowf(NORMAL, "%c\b", ch); + break; + case 'c': + break; + case 'd': + flowf(NORMAL, "."); + break; + } +} + +void progress_end(int n) +{ + switch (arg_progress) { + case 'a': + if (n % progress_mul) + flowf(NORMAL, "*) "); + else + flowf(NORMAL, ") "); + break; + case 'c': + case 'd': + flowf(NORMAL, " "); + break; + } +} + +int stopwatch_start(void) +{ +#if defined(MSC) || defined(BCC) + return GetTickCount(); +#else + return 1000 * time(NULL); +#endif +} + +int stopwatch_stop(int time_start) +{ +#if defined(MSC) || defined(BCC) + return GetTickCount() - time_start; +#else + return 1000 * (time(NULL) - time_start); +#endif +} + + +/****************************************************************************** + * Hexdumping + ******************************************************************************/ + +void hexdump(unsigned char *buf, int size, unsigned int addr, int unitsize) +{ + int n, i; + char string[(8+1+1) + (1+16+1+1) + (3*16) + 1]; + char *s; + + while (size > 0) + { + s = string; + s += sprintf(s, "%8x ", addr); // print offset + + n = (size > 16 ? 16 : size); + + // print the textual representation + for (i = 0; i < n; i++) { + if (buf[i] >= ' ' && buf[i] < 127) + *s++ = buf[i]; + else + *s++ = '.'; + } + // pad textual representation with spaces + for (i = 0; i < 16 - n; i++) { + *s++ = ' '; + } + *s++ = ' '; + + // print hexedecimal representation + for (i = 0; i < n; i += unitsize) { + switch (unitsize) { + case 1: s += sprintf(s, "%02x ", *(uint8 *) (buf+i)); break; + case 2: s += sprintf(s, "%04x ", *(uint16 *) (buf+i)); break; + case 4: + s += sprintf(s, "%08x ", (int) (*(uint32 *) (buf+i))); + break; + } + } + buf += 16; + addr += 16; + size -= 16; + puts(string); + } +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/misc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/misc.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,24 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Miscellaneous Utility Functions + * + * $Id: misc.h 1.4 Tue, 15 Jan 2002 15:19:31 +0100 mmj $ + * + ******************************************************************************/ + +int dirname_len(const char *pathname); +int pathname_make(char *buf, int size, const char *dirname, const char *leafname); + +void progress_begin(int n); +void progress_update_simple(int n); +void progress_update(int n); +void progress_end(int n); + +int stopwatch_start(void); +int stopwatch_stop(int time_start); + +void hexdump(unsigned char *buf, int size, unsigned int address, int unitsize); diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/protocol.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,77 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * (C) Delta Technologies 2001. + * Cleanup, modifications and extensions by Mads Meisner-Jensen, mmj@ti.com. + * + * Target/PC protocol definition + * + * $Id: protocol.h 1.21 Mon, 28 Apr 2003 08:49:16 +0200 tsj $ + * + ******************************************************************************/ + + +enum ProtocolChars { + PROTO_HELLO = 'H', + PROTO_BAUDRATE = 'B', + PROTO_BAUDRATE_XXO = 'X', + PROTO_INIT = 'N', + PROTO_QUERY = 'Q', + PROTO_QUERY_CHIP = 'C', + PROTO_READY = 'R', + PROTO_ISEMPTY = 'I', + PROTO_DOWNLOAD = 'L', + PROTO_DETECT = 'D', + PROTO_ERASE = 'E', + PROTO_COMPRESS = 'Z', + PROTO_PROGRAM = 'P', + PROTO_CKSUM = 'C', + PROTO_READ = 'R', + PROTO_RESET = '0', + PROTO_CHECKSUM = 'C', + PROTO_VERSION = 'V', + PROTO_TIMERS = 'T', + PROTO_FLASH_START = '[', + PROTO_FLASH_END = ']', + PROTO_IMEI_PROTECT = 'I', + + PROTO_ERROR = '?', + PROTO_ERROR_INVALID = '!', // Invalid command parameter + PROTO_ERROR_CKSUM = 'X', + PROTO_ERROR_MEMORY = 'M', + PROTO_ERROR_VERIFY = 'D', + PROTO_ERROR_FLASH_TIMEOUT = 'T', + PROTO_ERROR_FLASH_COMMAND = 'C', + PROTO_ERROR_FLASH_VPP = 'V', + PROTO_ERROR_FLASH_LOCKED = 'L', + PROTO_ERROR_FLASH_UNKNOWN = 'F', + PROTO_ERROR_HARDWARE = 'H', + PROTO_ERROR_FIFO_OVERFLOW = 'O', + PROTO_ERROR_ROM_SSERVICE = 'S', + + PROTO_IS_ERASING = 'I', // Not a real protocol char - for internal use + + PROTO_TRACE = '$' +}; + + + +// Not really part of the protocol but as this header file is included by +// both PC side and target side source code, this is an easy place to put +// these difinitions. +enum ChipIdCodes { + // Ulysses and Hercules + CHIP_ID_ULYSSES_0 = 0xB2B5, + CHIP_ID_ULYSSES_A = 0xB335, + CHIP_ID_HERCULES_A = 0xB334, // Correct revision designation? + CHIP_ID_HERCULES_B = 0xB32C, // Correct revision designation? + + // Samson and Calypso + CHIP_ID_CALYPSO_A = 0xB2AC, + CHIP_ID_CALYPSO_B = 0xB396, + CHIP_ID_CALYPSO_C = 0xB496, + CHIP_ID_CALYPSO_L = 0xB4FB, + + CHIP_ID_CALYPSO_PLUS = 0xB512, + CHIP_ID_CALYPSO_PLUS_A = 0xB608 +}; diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/serial.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/serial.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,334 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Serial/UART driver + * + * $Id: serial.c 1.23 Fri, 18 Oct 2002 08:53:12 +0200 mmj $ + * + ******************************************************************************/ + +#include "fluid.h" +#include "serial.h" +#include "trace.h" + +#include +#include + +#if defined(MSC) || defined(BCC) + #include // for Sleep() +#else +// #error Not compiling for MSC or BCC? +#endif + + +extern void target_recv_push(char *buf, int size); + + +/****************************************************************************** + * OS Independent + ******************************************************************************/ + +static void serial_listener(void); + +#if (OS == WIN32) + +/****************************************************************************** + * Win32 Driver + ******************************************************************************/ + +#include + +static HANDLE hCom; +static HANDLE thread_handle = NULL; +static DWORD thread_id; +static OVERLAPPED read_overlapped; +static OVERLAPPED write_overlapped; +static DCB dcb; + +const char PORT_NAME_PRE[] = "COM"; +// A special syntax is required when accessing com ports greater than 9, e.g., "\\.\COM10" +const char PORT_NAME_PREFIX[] = "\\\\.\\COM"; + +int serial_init(int uart, int bps, char *flowcontrol) +{ + int error; + COMMTIMEOUTS timeouts; + char pc_comport[32]; + + sprintf(pc_comport, "%s%d", PORT_NAME_PREFIX, uart); + + hCom = CreateFile(pc_comport, + GENERIC_READ | GENERIC_WRITE, + 0, // comm devices must be opened w/exclusive-access + NULL, // no security attributes + OPEN_EXISTING, // comm devices must use OPEN_EXISTING + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL // hTemplate must be NULL for comm devices + ); + if (hCom == INVALID_HANDLE_VALUE) + return E_OS + E_UART_INIT; + + // We will build on the current configuration, and skip setting the size + // of the input and output buffers with SetupComm. + if (!GetCommState(hCom, &dcb)) + return E_OS + E_UART_INIT; + + dcb.fAbortOnError = FALSE; // Hmm? (Dont't remember exactly what this is) + dcb.ByteSize = 8; // Data size, xmit, and rcv + dcb.Parity = NOPARITY; // No parity bit + dcb.StopBits = ONESTOPBIT; // One stop bit + dcb.fOutxCtsFlow = 0; // Disable CTS HW handshaking! + dcb.fOutxDsrFlow = 0; // Disable DSR HW handshaking! + dcb.fDsrSensitivity = 0; // Disable DSR HW handshaking! + + // Note the DTR = +12V and RTS = -12V is needed to power the serial + // level converter! + + switch (flowcontrol[0]) { + case 'n': dcb.fDtrControl = DTR_CONTROL_DISABLE; break; + case 'h': dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; break; + case 'p': + default: + dcb.fDtrControl = DTR_CONTROL_ENABLE; break; + } + switch (flowcontrol[1]) { + case 'p': dcb.fRtsControl = RTS_CONTROL_ENABLE; break; + case 'h': dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break; + case 'n': + default: + dcb.fRtsControl = RTS_CONTROL_DISABLE; break; + } + + if (!SetCommState(hCom, &dcb)) + return E_OS + E_UART_INIT; + + if ((error = serial_baudrate_set(bps)) < 0) + return error; + + timeouts.ReadIntervalTimeout = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + assert(SetCommTimeouts (hCom, &timeouts)); + assert(SetCommMask (hCom, EV_RXCHAR)); + //assert(SetupComm (hCom, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE)); + + sprintf(pc_comport, "read%s%d", PORT_NAME_PRE, uart); + read_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport); + + sprintf(pc_comport, "write%s%d", PORT_NAME_PRE, uart); + write_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport); + + thread_handle = + CreateThread (NULL, + 0, + (LPTHREAD_START_ROUTINE) serial_listener, + NULL, + 0, + &thread_id); + + if (thread_handle == NULL) + return E_OS + E_UART_INIT; + + serial_reset(); + + return 0; +} + +int serial_is_baudrate(int bps) +{ + int i; + const struct rate_s { + int bps; + int baudrate; + } rates[] = { + { 9600, 9600 }, { 9, 9600 }, + { 14400, 14400 }, { 14, 14400 }, + { 19200, 19200 }, { 19, 19200 }, + { 38400, 38400 }, { 38, 38400 }, + { 57600, 57600 }, { 57, 57600 }, + { 115200, 115200 }, { 115, 115200 }, + { 203125, 203125 }, { 203, 203125 }, // 13MHz clock + { 230400, 230400 }, { 230, 230400 }, + { 406250, 406250 }, { 406, 406250 }, // 13MHz clock + { 460800, 460800 }, { 460, 460800 }, + { 812500, 812500 }, { 812, 812500 }, // 13MHz clock + { 921600, 921600 }, { 921, 921600 }, + { 0, 0 } // terminator + }; + + for (i = 0; i < sizeof(rates) / sizeof(struct rate_s) - 1; i++) + if (rates[i].bps == bps) + break; + + tr(TrTargetDrv, "serial_is_baudrate(%d) %d\n", bps, rates[i].baudrate); + + return rates[i].baudrate; +} + +int serial_baudrate_set(int bps) +{ +#if 0 + if (!GetCommState(hCom, &dcb)) + return E_OS + E_UART_PARAM; +#endif + + bps = serial_is_baudrate(bps); + if (bps == 0) + return E_OS + E_UART_PARAM; + + /* Replace 812K with 827K. Otherwise, the chip will automatically select 800K. */ + /* 800K is OK, but we might as well gain the extra 3% speed :-) */ + if (bps == 812500) + dcb.BaudRate = 827586; + else + dcb.BaudRate = bps; + + if (!SetCommState(hCom, &dcb)) + return E_OS + E_UART_PARAM; + + return bps; +} + +int serial_baudrate_get(void) +{ + return dcb.BaudRate; +} + +void serial_exit(void) +{ + DWORD exit_code; + + serial_reset(); + + (void) GetExitCodeThread (thread_handle, &exit_code); + (void) TerminateThread (thread_handle, exit_code); + + (void) CloseHandle (hCom); + (void) CloseHandle (read_overlapped.hEvent); + (void) CloseHandle (write_overlapped.hEvent); +} + +// Clear buffers and transactions. +void serial_reset(void) +{ + PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); +} + +// Return the number of milli-seconds it takes to transfer bytes. +int serial_transfer_time(int size) +{ + return 1000 * 10 * size / serial_baudrate_get(); +} + + +/*************************************** + * Send + ***************************************/ + +int serial_send(char *buf, int size) +{ + DWORD written; + + ResetEvent(write_overlapped.hEvent); // why? + + if (!WriteFile(hCom, buf, size, &written, &write_overlapped)) { + if (GetLastError() == ERROR_IO_PENDING) { + if (GetOverlappedResult(hCom, &write_overlapped, + &written, TRUE) == FALSE) + written = E_OS + E_UART_DRV_SEND; + } + } + + return written; +} + + +/*************************************** + * Receive + ***************************************/ + +void serial_recv_reset(void) +{ + PurgeComm(hCom, PURGE_RXABORT|PURGE_RXCLEAR); +} + +static void serial_listener(void) +{ + DWORD event_mask; + char buf[64]; + DWORD size; + + while (1) + { + // Wait the event signalling characters received. + if (WaitCommEvent (hCom, &event_mask, NULL) != TRUE) { + main_msg("WaitCommEvent(): error %d\n", GetLastError()); + return; + } + tr(TrTargetDrv, "|"); + + // Read all characters received in the buffer. Mysteriously, it + // does NOT work with a buffer size greater than one! + do { + if (!ReadFile(hCom, buf, 1, &size, &read_overlapped)) + { + if (GetLastError() == ERROR_IO_PENDING) { + GetOverlappedResult(hCom, &read_overlapped, &size, TRUE); + } + else { + main_msg("ReadFile(): error %d\n", GetLastError()); + serial_recv_reset(); + break; + } + } + // Push the data to upper layer + target_recv_push(buf, size); + + } while (size); + } +} + + +/****************************************************************************** + * Control of Delta cable special outputs + ******************************************************************************/ + +void serial_rts(char state) +{ + if (state) + EscapeCommFunction(hCom, SETRTS); + else + EscapeCommFunction(hCom, CLRRTS); +} + +void serial_dtr(char state) +{ + if (state) + EscapeCommFunction(hCom, SETDTR); + else + EscapeCommFunction(hCom, CLRDTR); +} + +void serial_break(char state) +{ + if (state) + SetCommBreak(hCom); + else + ClearCommBreak(hCom); +} + +#else // (OS == WIN32) + + +/****************************************************************************** + * Unix driver + ******************************************************************************/ + + +#endif // (OS == WIN32) diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/serial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/serial.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,30 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Serial/UART driver + * + * $Id: serial.h 1.8 Wed, 04 Sep 2002 16:32:18 +0200 mmj $ + * + ******************************************************************************/ + +int serial_init(int uart, int baudrate, char *flowcontrol); +int serial_is_baudrate(int bps); +int serial_baudrate_set(int baudrate); +int serial_baudrate_get(void); +void serial_exit(void); +void serial_reset(void); + +int serial_transfer_time(int size); + +int serial_send(char *buf, int size); +int serial_putchar(unsigned char ch); +int serial_recv(char *buf, int size); +void serial_recv_reset(void); + +void serial_rts(char state); +void serial_dtr(char state); +void serial_break(char state); + diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/target.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/target.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,425 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Target Connection and Control + * + * $Id: target.c 1.20 Mon, 21 Oct 2002 18:39:13 +0200 mmj $ + * + ******************************************************************************/ + +#include "serial.h" +#include "fluid.h" +#include "trace.h" + +#include + +#if defined(MSC) || defined(BCC) + #include "windows.h" +#endif + +int target_trace(unsigned char ch); + + +/****************************************************************************** + * Globals + ******************************************************************************/ + +HANDLE hEvent; + +#define RECVBUF_SIZE (65536) + +static unsigned char recvbuf[RECVBUF_SIZE]; +static int recvbuf_size_target; +static int recvbuf_put; +static int recvbuf_get; + +#define recvbuf_size() (recvbuf_put - recvbuf_get + \ + ((recvbuf_put - recvbuf_get) < 0 ? RECVBUF_SIZE : 0)) + + +/****************************************************************************** + * Error Functions + ******************************************************************************/ + +void error_proto(char ch, char chx) +{ + char chd, chxd; + + chd = (' ' <= ch && ch < 127 ? ch : '.'); + chxd = (' ' <= chx && chx < 127 ? chx : '.'); + + flowf(NORMAL, "(protocol error: got '%c' 0x%02X, expected '%c' 0x%02X)\n", + chd, ch, chxd, chx); + + main_fatal(E_PROTO_ERROR); +} + + +/****************************************************************************** + * Target Dependencies + ******************************************************************************/ + +// is the target's clock frequency +int target_uart_baudrate_divider_get(int clk, int bps) +{ + int divider = clk / bps / 16; + + tr(TrTargetDrv, "target_uart_baudrate_divider_get(%d, %d) %d\n", + clk, bps, divider); + + return divider; +} + + +/****************************************************************************** + * Target Init and Send + ******************************************************************************/ + +static int target_trace_timer; + +void target_recv_reset(void) +{ + tr(TrTargetDrv, "recv_reset()\n"); + + recvbuf_get = recvbuf_put = 0; + + memset(recvbuf, 0x77, RECVBUF_SIZE); + + serial_recv_reset(); +} + +int target_driver_init(int uart, int baudrate, char *flowcontrol) +{ + int error; + + target_recv_reset(); + + hEvent = CreateEvent(NULL, // lpEventAttributes + FALSE, // bManualReset (OFF) + FALSE, // bInitialstate (OFF) + NULL); // lpName + + if (hEvent == NULL) { + error = E_DRIVER_INIT + E_OS; + } + else { + error = serial_init(uart, baudrate, flowcontrol); + } + return error; +} + +int target_driver_baudrate(int baudrate) +{ + return serial_baudrate_set(baudrate); +} + +int target_putchar(char ch) +{ + char trch; + + trch = (ch < ' ' || ch == 127 ? '.' : ch); + tr(TrPutChar, "s '%c'/0x%02X\n", trch, ch & 0xFF); + + return serial_send(&ch, 1); +} + +int target_send(char *buf, int size) +{ + tr(TrPutChar, "s (%d bytes)\n", size); + + return serial_send(buf, size); +} + + +/****************************************************************************** + * Target Wait and Receive + ******************************************************************************/ + +void target_recv_signal(void) +{ + // Notify waiting thread when we have received the requested number of + // bytes. Note that we use auto-resetting events, so you have to be VERY + // careful to wait for the exact number of bytes you want. Otherwise you + // might trigger the event twice in quick succession and this will + // result in the next call of target_wait()'s to return immediately + // without waiting! + + if (recvbuf_size() >= recvbuf_size_target && recvbuf_size_target > 0) { + // When we have triggered the event, disable further triggering + // until next call of target_wait() + recvbuf_size_target = 0; + tr(TrDriverGet, "!"); + if (SetEvent(hEvent) == 0) + fprintf(stderr, "FATAL: recv_push_tm(): SetEvent() failed with Win32 error %d\n", GetLastError()); + } +} + +void target_recv_push(char *buf, int size) +{ + if (size == 0) { + tr(TrDriverGet, " G?"); + return; + } + + while (size--) { + recvbuf[recvbuf_put++] = *buf++; + recvbuf_put &= (RECVBUF_SIZE - 1); + } + tr(TrDriverGet, " G%d", recvbuf_size()); + + target_recv_signal(); +} + +// Wait maximum milli-seconds for bytes to arrive. If +// is zero, we unconditionally wait for milli-seconds +// (quite simply a delay). The transfer time is automatically added to the +// total waiting time. +int target_wait(int size, int timeout) +{ + int result = 0; + + tr(TrTargetWait, "target_wait(%d, %d)\n", size, timeout); + + if (size > 0) + timeout += serial_transfer_time(size); + + recvbuf_size_target = size; + target_trace_timer = timeout; + + if (size == 0) { + Sleep(timeout); + } + else { + target_recv_signal(); + + switch (WaitForSingleObject(hEvent, timeout)) { + case WAIT_OBJECT_0: result = recvbuf_size(); break; + case WAIT_TIMEOUT: result = E_RECV_TIMEOUT; break; + default: result = E_OS + E_DRIVER_WAIT; break; + } + } + recvbuf_size_target = 0; + + return result; +} + +int target_recv(void *outbuf, int size) +{ + int i, bufsize; + char *buf = (char *) outbuf; + + bufsize = recvbuf_size(); + if (bufsize < size) + size = bufsize; + + for (i = 0; i < size; i++) { + *buf++ = recvbuf[recvbuf_get++]; + recvbuf_get &= (RECVBUF_SIZE - 1); + } + + tr(TrGetChar, "r (%d bytes)\n", size); + return size; +} + +int target_getchar(void) +{ + int trace_in_progress; + char ch; + + do { + ch = recvbuf[recvbuf_get++]; + recvbuf_get &= (RECVBUF_SIZE - 1); + tr(TrGetChar, "r '%c' %02X\n", + (ch >= ' ' && ch <= 126 ? ch : '.'), ch & 0xFF); + + if ((trace_in_progress = target_trace((char) ch)) != 0) { + if (target_wait(1, target_trace_timer) < 1) + main_fatal(E_RECV_TIMEOUT); + } + } while (trace_in_progress); + + return (ch & 0xFF); +} + +int target_expect_char(char ch, int timeout) +{ + char mych; + + if (target_wait(1, timeout) < 1) { + flowf(NORMAL, "(Waited for '%c' 0x%02X)\n", ch, ch); + main_fatal(E_RECV_TIMEOUT); + } + + if ((mych = target_getchar()) != ch) + error_proto(mych, ch); + + return ch; +} + + +/****************************************************************************** + * Target Buffer Put + ******************************************************************************/ + +int buf_put1(char *buf, unsigned char data) +{ + tr(TrPutChar, "buf_put1(0x%02X) '%c'\n", data, data); + + *buf = (data ) & 0xFF; + return 1; +} + +int buf_put2(char *buf, unsigned short data) +{ + tr(TrPutChar, "buf_put2(0x%04X)\n", data); + + *buf++ = (data ) & 0xFF; + *buf = (data >> 8) & 0xFF; + return 2; +} + +int buf_put4(char *buf, unsigned int data) +{ + tr(TrPutChar, "buf_put4(0x%08X)\n", data); + + *buf++ = (data ) & 0xFF; + *buf++ = (data >> 8) & 0xFF; + *buf++ = (data >> 16) & 0xFF; + *buf = (data >> 24) & 0xFF; + return 4; +} + +// Put 2-byte integer in network order +int buf_put2no(char *buf, unsigned short data) +{ + tr(TrPutChar, "buf_put2no(0x%04X)\n", data); + + *buf++ = (data >> 8) & 0xFF; + *buf = (data ) & 0xFF; + return 2; +} + +// Put 4-byte integer in network order +int buf_put4no(char *buf, unsigned int data) +{ + tr(TrPutChar, "buf_put4no(0x%08X)\n", data); + + *buf++ = (data >> 24) & 0xFF; + *buf++ = (data >> 16) & 0xFF; + *buf++ = (data >> 8) & 0xFF; + *buf = (data ) & 0xFF; + return 4; +} + + +/****************************************************************************** + * Special Target Control Functions + ******************************************************************************/ + +// Control target power. Works *only* with special cable! If is +// non-zero, the power is on. Otherwise, it is off. +void target_power(char state) +{ + if (arg_uart_level_convert) + return; + + if (state) { + serial_rts(0); + } + else { + serial_rts(1); + serial_dtr(1); + serial_break(1); + serial_break(0); + } +} + +// Control target reset line. Works *only* with special cable! If +// is non-zero, the reset line is asserted. Otherwise, it is negated. +void target_reset(char state) +{ + if (arg_uart_level_convert) + return; + + if (state) { + serial_rts(1); + serial_dtr(0); + serial_rts(0); + serial_break(0); + } + else { + serial_break(1); + serial_rts(1); + serial_dtr(1); + serial_rts(0); + } +} + + +/****************************************************************************** + * Target Trace/Debug Functions + ******************************************************************************/ + +static int target_trace_enable_flag = 0; + +int target_trace_enable(int flag) +{ + int old = target_trace_enable_flag; + + target_trace_enable_flag = flag; + + if (arg_target_trace_enable) + flowf(DEBUG, "{%s}", (flag ? "enable" : "disable")); + + return old; +} + +// Interpret and display target trace message. Return zero if was not +// intercepted. Otherwise, if it was intercepted, return non-zero. +int target_trace(unsigned char ch) +{ + int i; + unsigned int number = 0; + char buf[80], *p; + + // If target is not supposed to transmit any tracing at this point in + // the state machine(s), the flag will be zero and thus we return. + if (target_trace_enable_flag && ch == '$') { + if (target_wait(1, 100) < 0) + main_fatal(E_RECV_TIMEOUT); + ch = target_getchar(); + switch (ch) { + case 'S': + p = buf; + while (ch != 0) { + if (target_wait(1, 100) < 0) + main_fatal(E_RECV_TIMEOUT); + ch = target_getchar(); + *p++ = ch; + } + *p = 0; + if (arg_target_trace_enable) + printf("{'%s'} ", buf); + break; + case 'N': + for (i = 0; i < 4; i++) { + if (target_wait(1, 100) < 0) + main_fatal(E_RECV_TIMEOUT); + ch = target_getchar(); + number = (number >> 8) + (ch << 24); + } + if (arg_target_trace_enable) + printf("{0x%X/%dd} ", number, number); + break; + default: + fprintf(stderr, "WARNING: Bad TargetTrace char received! (0x%X)\n", + ch & 0xFF); + break; + } + return 1; + } + return 0; +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/target.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/target.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,40 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * Copyright Texas Instruments, 2001. + * Mads Meisner-Jensen, mmj@ti.com. + * + * Target Connection and Control + * + * $Id: target.h 1.8 Thu, 01 Aug 2002 11:17:20 +0200 mmj $ + * + ******************************************************************************/ + + +int target_uart_baudrate_divider_get(int clk, int bps); + +int target_driver_init(int uart, int baudrate, char *flowcontrol); +int target_driver_baudrate(int baudrate); + +int target_send(char *buf, int size); +int target_putchar(char ch); + +int target_wait(int size, int time); +int target_recv(void *buf, int size); +int target_getchar(void); +int target_expect_char(char ch, int time); +void target_recv_reset(void); + +int buf_put1(char *buf, unsigned char); +int buf_put2(char *buf, unsigned short data); +int buf_put4(char *buf, unsigned int data); +int buf_put2no(char *buf, unsigned short data); +int buf_put4no(char *buf, unsigned int data); + +void error_proto(char ch, char chx); + +void target_power(char state); +void target_reset(char state); + +int target_trace_enable(int flag); +int target_trace(unsigned char ch); diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/trace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/trace.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,134 @@ +/****************************************************************************** + * Generic tracing library + * + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * $Id: trace.c 1.5 Fri, 11 Oct 2002 08:40:21 +0200 mmj $ + * + ******************************************************************************/ + +#include "trace.h" + +#include +#include +#include + + +#define TRACE_MODS 2 + + +/****************************************************************************** + * + *****************************************************************************/ + +static struct trace_s { + int spaces; // number of spaces to indent per level + int level; // current indentation level (private) + int enable; // global trace enable/disable flag + FILE *fp; // file descriptor of file to write traces to + int mask[TRACE_MODS]; // bitmask for each module +} trace; + +int tr_init(int spaces, char *filename) +{ + trace.spaces = spaces; + trace.level = 0; + trace.enable = 1; + trace.fp = stdout; + memset(trace.mask, 0, sizeof(trace.mask)); + + if (filename != NULL && (trace.fp = fopen(filename, "w")) == NULL) { + return -1; + } + return 0; +} + +int tr_mask(int mask) +{ + int module, old; + + module = ((mask & TrModMask) >> 24) - 1; + if (module < 0 || module >= TRACE_MODS) + return -1; + + old = trace.mask[module]; + trace.mask[module] = mask & TrBitMask; + + return old; +} + +void tr_enable(int onoff) +{ + trace.enable = onoff; +} + +// return current indentation if this trace type is enabled, otherwise +// return zero. +int tr_query(int mask) +{ + int module; + + module = (mask & TrModMask) >> 24; + if (module < 0 || module >= TRACE_MODS) + return 0; + + return (trace.mask[module] & (mask & TrBitMask) ? + trace.level * trace.spaces : 0); +} + +extern void hexdump(const char *p, int size, unsigned int address, int unitsize); + +void tr_hexdump(int mask, const void *p, int size) +{ + unsigned int module; + + module = mask & TrModMask; + mask = mask & TrBitMask; + + if ((mask & trace.mask[module >> 24]) == 0) + return; + + hexdump(p, size, 0, 1); +} + +void tr(int mask, char *format, ...) +{ + va_list args; + unsigned int type, module; + int indent; + static char buf[256]; + const char spaces[160 + 1] = + " " + " " + " " + " "; + + if (!trace.enable) + return; + + type = mask & TrTypeMask; + module = mask & TrModMask; + mask = mask & TrBitMask; + + if ((mask & trace.mask[(module >> 24) - 1]) == 0) + return; + + if (type == TrEnd) + trace.level--; + + indent = (type == TrCont ? 0 : trace.level); + + if (indent < 0 || indent > 40) { + indent = trace.level = 0; + fprintf(stderr, "WARNING: trace indent out of range!\n"); + } + if (strlen(format) > 0) { + va_start(args, format); + vsprintf(buf, format, args); + indent *= trace.spaces; + fprintf(trace.fp, "%s%s", &spaces[sizeof(spaces) - 1 - indent], buf); + fflush(trace.fp); + } + if (type == TrBegin) + trace.level++; +} diff -r ae39d76d5b7a -r 9cecc930d78f fluid-mnf/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/trace.h Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,58 @@ +/****************************************************************************** + * Generic tracing library + * + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * $Id: trace.h 1.4 Fri, 11 Oct 2002 08:40:21 +0200 mmj $ + * + ******************************************************************************/ + +#ifndef _TRACE_H_ +#define _TRACE_H_ + + +/****************************************************************************** + * Common + *****************************************************************************/ + +enum { + TrF = 0x00000000, + TrC = 0x40000000, + TrB = 0x80000000, + TrE = 0xC0000000, + TrTypeMask = 0xC0000000, + + TrFunc = TrF, + TrCont = TrC, // Tracing continue + TrBegin = TrB, + TrEnd = TrE, + + // Trace Module + TrAny = 0x3F000000, + TrModMask = 0x3F000000, + + // Trace Mask + TrAll = 0x00FFFFFF, + TrBitMask = 0x00FFFFFF +}; + +typedef void (* pf_tr_t) (int, char *, ...); +typedef void (* pf_tr_hexdump_t) (int, const void *, int); + +typedef struct tr_functions_s { + pf_tr_t tr; + pf_tr_hexdump_t hexdump; //Fixme tr_hexdump? +} tr_functions_t; + + +// Trace Wrapper. Used for quickly removing tracing from output code. +#define tw(wrapping) wrapping +//#define tw(wrapping) + +int tr_init(int spaces, char *filename); +void tr_enable(int onoff); +int tr_mask(int mask); +void tr(int mask, char *format, ...); +void tr_hexdump(int mask, const void *p, int size); + +#endif // _TRACE_H_