Changeset 1011

Show
Ignore:
Timestamp:
04/23/08 10:10:02 (13 years ago)
Author:
ppalmers
Message:

finish ECHO firmware tools

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/fireworks/efc/efc_avc_cmd.cpp

    r969 r1011  
    8080    result &= de.read(&m_dummy_2); 
    8181 
     82    if(!result) { 
     83        debugWarning("AV/C deserialization failed\n"); 
     84        return false; 
     85    } 
     86 
    8287    result &= m_cmd->deserialize( de ); 
    8388     
  • trunk/libffado/src/fireworks/efc/efc_cmds_flash.cpp

    r1010 r1011  
    5959 
    6060    result &= EfcCmd::deserialize ( de ); 
    61  
    62     EFC_DESERIALIZE_AND_SWAP(de, &m_address, result); 
    6361 
    6462    return result; 
     
    112110    } 
    113111    for (unsigned int i=0; i < m_nb_quadlets; i++) { 
    114         // FIXME: do we have to swap? 
    115112        EFC_DESERIALIZE_AND_SWAP(de, &m_data[i], result); 
    116         // or not? 
    117         //result &= de.read(&m_data[i]); 
    118113    } 
    119114    return result; 
     
    161156 
    162157    for (unsigned int i=0; i < m_nb_quadlets; i++) { 
    163         // FIXME: do we have to swap? 
    164         // or not? 
    165         result &= se.write(m_data[i], "Data"); 
     158        result &= se.write(htonl(m_data[i]), "Data"); 
    166159    } 
    167160    return result; 
  • trunk/libffado/src/fireworks/fireworks_device.cpp

    r1010 r1011  
    501501 
    502502bool 
    503 Device::readFlash(uint32_t start, uint32_t len, uint32_t* buffer) { 
     503Device::lockFlash(bool lock) { 
     504    EfcFlashLockCmd cmd; 
     505    cmd.m_lock = lock; 
     506 
     507    if(!doEfcOverAVC(cmd)) { 
     508        debugError("Flash lock failed\n"); 
     509        return false; 
     510    } 
     511    return true; 
     512
     513 
     514bool 
     515Device::writeFlash(uint32_t start, uint32_t len, uint32_t* buffer) { 
    504516 
    505517    if(len <= 0 || 0xFFFFFFFF - len*4 < start) { 
     
    516528    uint32_t *target_buffer = buffer; 
    517529 
     530    EfcFlashWriteCmd cmd; 
     531    // write EFC_FLASH_SIZE_BYTES at a time 
     532    for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) { 
     533        cmd.m_address = start_addr; 
     534        unsigned int quads_to_write = (stop_addr - start_addr)/4; 
     535        if (quads_to_write > EFC_FLASH_SIZE_QUADS) { 
     536            quads_to_write = EFC_FLASH_SIZE_QUADS; 
     537        } 
     538        cmd.m_nb_quadlets = quads_to_write; 
     539        for(unsigned int i=0; i<quads_to_write; i++) { 
     540            cmd.m_data[i] = *target_buffer; 
     541            target_buffer++; 
     542        } 
     543        if(!doEfcOverAVC(cmd)) { 
     544            debugError("Flash write failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_write); 
     545            return false; 
     546        } 
     547    } 
     548    return true; 
     549} 
     550 
     551bool 
     552Device::readFlash(uint32_t start, uint32_t len, uint32_t* buffer) { 
     553 
     554    if(len <= 0 || 0xFFFFFFFF - len*4 < start) { 
     555        debugError("bogus start/len: 0x%08X / %u\n", start, len); 
     556        return false; 
     557    } 
     558    if(start & 0x03) { 
     559        debugError("start address not quadlet aligned: 0x%08X\n", start); 
     560        return false; 
     561    } 
     562 
     563    uint32_t start_addr = start; 
     564    uint32_t stop_addr = start + len*4; 
     565    uint32_t *target_buffer = buffer; 
     566 
    518567    EfcFlashReadCmd cmd; 
    519568    // read EFC_FLASH_SIZE_BYTES at a time 
    520569    for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) { 
    521         cmd.m_address = start_addr; 
    522570        unsigned int quads_to_read = (stop_addr - start_addr)/4; 
    523571        if (quads_to_read > EFC_FLASH_SIZE_QUADS) { 
    524572            quads_to_read = EFC_FLASH_SIZE_QUADS; 
    525573        } 
    526         cmd.m_nb_quadlets = quads_to_read; 
    527         if(!doEfcOverAVC(cmd)) { 
    528             debugError("Flash read failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_read); 
     574        uint32_t quadlets_read = 0; 
     575        int ntries = 10000; 
     576        do { 
     577            cmd.m_address = start_addr + quadlets_read*4; 
     578            unsigned int new_to_read = quads_to_read - quadlets_read; 
     579            cmd.m_nb_quadlets = new_to_read; 
     580            if(!doEfcOverAVC(cmd)) { 
     581                debugError("Flash read failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_read); 
     582                return false; 
     583            } 
     584            if(cmd.m_nb_quadlets != new_to_read) { 
     585                debugOutput(DEBUG_LEVEL_VERBOSE, 
     586                            "Flash read didn't return enough data (%u/%u) \n", 
     587                            cmd.m_nb_quadlets, new_to_read); 
     588                // continue trying 
     589            } 
     590            quadlets_read += cmd.m_nb_quadlets; 
     591 
     592            // copy content 
     593            for(unsigned int i=0; i<cmd.m_nb_quadlets; i++) { 
     594                *target_buffer = cmd.m_data[i]; 
     595                target_buffer++; 
     596            } 
     597        } while(quadlets_read < quads_to_read && ntries--); 
     598        if(ntries==0) { 
     599            debugError("deadlock while reading flash\n"); 
    529600            return false; 
    530601        } 
    531         if(cmd.m_nb_quadlets != quads_to_read) { 
    532             debugError("Flash read didn't return enough data (%u/%u) \n", cmd.m_nb_quadlets, quads_to_read); 
     602    } 
     603    return true; 
     604
     605 
     606bool 
     607Device::eraseFlash(uint32_t addr) { 
     608    if(addr & 0x03) { 
     609        debugError("start address not quadlet aligned: 0x%08X\n", addr); 
     610        return false; 
     611    } 
     612    EfcFlashEraseCmd cmd; 
     613    cmd.m_address = addr; 
     614    if(!doEfcOverAVC(cmd)) { 
     615        if (cmd.m_header.retval == EfcCmd::eERV_FlashBusy) { 
     616            return true; 
     617        } 
     618        debugError("Flash erase failed for block 0x%08X\n", addr); 
     619        return false; 
     620    } 
     621    return true; 
     622
     623 
     624bool 
     625Device::waitForFlash(unsigned int msecs) 
     626
     627    bool ready; 
     628 
     629    EfcFlashGetStatusCmd statusCmd; 
     630    const unsigned int time_to_sleep_usecs = 10000; 
     631    int wait_cycles = msecs * 1000 / time_to_sleep_usecs; 
     632 
     633    do { 
     634        if (!doEfcOverAVC(statusCmd)) { 
     635            debugError("Could not read flash status\n"); 
    533636            return false; 
    534637        } 
    535         if(cmd.m_data == NULL) { 
    536             debugError("No data block in EFC cmd\n"); 
    537             return false; 
    538         } 
    539         for(unsigned int i=0; i<quads_to_read; i++) { 
    540             *target_buffer = cmd.m_data[i]; 
    541             target_buffer++; 
    542         } 
    543     } 
    544     return true; 
     638        if (statusCmd.m_header.retval == EfcCmd::eERV_FlashBusy) { 
     639            ready = false; 
     640        } else { 
     641            ready = statusCmd.m_ready; 
     642        } 
     643        usleep(time_to_sleep_usecs); 
     644    } while (!ready && wait_cycles--); 
     645 
     646    if(wait_cycles == 0) { 
     647        debugError("Timeout while waiting for flash\n"); 
     648        return false; 
     649    } 
     650 
     651    return ready; 
    545652} 
    546653 
  • trunk/libffado/src/fireworks/fireworks_device.h

    r1010 r1011  
    7373    bool readFlash(uint32_t start, uint32_t len, uint32_t* buffer); 
    7474 
     75    /** 
     76     * @brief Write flash 
     77     * @param start start address 
     78     * @param len length in quadlets (4 bytes) 
     79     * @param buffer target buffer (should be 'len*4' bytes long) 
     80     * @return true if successful 
     81     */ 
     82    bool writeFlash(uint32_t start, uint32_t len, uint32_t* buffer); 
     83 
     84    /** 
     85     * @brief (un)lock the flash 
     86     * @param lock true=locked, false=unlocked 
     87     * @return true if successful 
     88     */ 
     89    bool lockFlash(bool lock); 
     90    /** 
     91     * @brief erase flash block 
     92     * @param addr address of block to erase 
     93     * @return true if successful 
     94     */ 
     95    bool eraseFlash(uint32_t addr); 
     96 
     97    /** 
     98     * @brief wait until the device indicates the flash memory is ready 
     99     * @param msecs time to wait before timeout 
     100     * @return true if the flash is ready, false if timeout 
     101     */ 
     102    bool waitForFlash(unsigned int msecs); 
     103 
    75104// Echo specific stuff 
    76105private: 
  • trunk/libffado/src/fireworks/fireworks_firmware.cpp

    r1010 r1011  
    2828#include "efc/efc_cmds_flash.h" 
    2929 
     30#include "libieee1394/configrom.h" 
     31#include "libieee1394/vendor_model_ids.h" 
     32 
    3033#include <string> 
    3134#include <sstream> 
     
    3336#include <fstream> 
    3437 
    35 #define ECHO_FLASH_TIMEOUT_MILLISECS 2000 
     38#define ECHO_FLASH_ERASE_TIMEOUT_MILLISECS 2000 
     39 
     40#define DAT_EXTENSION "dat" 
     41 
     42// device id's 
     43#define AUDIOFIRE2                      0x000af2 
     44#define AUDIOFIRE4                      0x000af4 
     45#define AUDIOFIRE8                      0x000af8 
     46#define AUDIOFIRE12                     0x00af12 
     47#define AUDIOFIRE12HD           0x0af12d 
     48#define FWHDMI                          0x00afd1 
     49#define ONYX400F                        0x00400f  
     50#define ONYX1200F                       0x01200f 
     51#define FIREWORKS8                      0x0000f8 
    3652 
    3753using namespace std; 
     
    362378} 
    363379 
     380uint32_t 
     381Firmware::getWriteDataLen() { 
     382    uint32_t retval = 0; 
     383    if((m_append_crc != 0) && (m_length_quads < m_footprint_quads)) { 
     384        retval += m_footprint_quads; 
     385    } else { 
     386        retval += m_length_quads; 
     387    } 
     388    return retval; 
     389} 
     390 
     391bool 
     392Firmware::getWriteData(uint32_t *buff) { 
     393    // copy the payload data 
     394    memcpy(buff, m_data, m_length_quads*4); 
     395    // if necessary, add crc/version 
     396    if((m_append_crc != 0) && (m_length_quads < m_footprint_quads)) { 
     397        debugOutput(DEBUG_LEVEL_VERBOSE, "appending CRC and version\n"); 
     398        buff[m_footprint_quads - 1] = m_CRC32; 
     399        buff[m_footprint_quads - 2] = m_version; 
     400    } 
     401    return true; 
     402} 
     403 
    364404void 
    365405Firmware::dumpData() 
     
    367407    debugWarning("-- char dump --"); 
    368408    hexDump((unsigned char*)m_data, m_length_quads*4); 
    369      
     409/*     
    370410    debugWarning("-- quadlet dump --"); 
    371     hexDumpQuadlets(m_data, m_length_quads); 
    372  
    373 
     411    hexDumpQuadlets(m_data, m_length_quads);*/ 
     412 
     413
     414 
    374415 
    375416// the firmware loader helper class 
     417char *Af2Dats[] =  
     418{ 
     419        "Fireworks3" 
     420}; 
     421 
     422char *Af4Dats[] =  
     423{ 
     424        "Fireworks3" 
     425}; 
     426 
     427char *Af8Dats[] =  
     428{ 
     429        "bootstrap", 
     430        "audiofire8", 
     431        "audiofire8_E", 
     432        "FireworksARM" 
     433}; 
     434 
     435char *Af12Dats[] =  
     436{ 
     437        "bootstrap", 
     438        "audiofire12", 
     439        "audiofire12_E", 
     440        "FireworksARM" 
     441}; 
     442 
    376443FirmwareUtil::FirmwareUtil(FireWorks::Device& p) 
    377444: m_Parent(p) 
    378445{ 
     446 
     447    struct dat_list datlists[4] = 
     448    { 
     449            { FW_VENDORID_ECHO, AUDIOFIRE2,     0x04010000, 1, Af2Dats }, 
     450            { FW_VENDORID_ECHO, AUDIOFIRE4,     0x04010000, 1, Af4Dats }, 
     451            { FW_VENDORID_ECHO, AUDIOFIRE8,     0x04010000, 4, Af8Dats }, 
     452            { FW_VENDORID_ECHO, AUDIOFIRE12,    0x04010000, 4, Af12Dats } 
     453    }; 
     454 
     455    assert(sizeof(datlists) <= sizeof(m_datlists)); 
     456    memset(&m_datlists, 0, sizeof(m_datlists)); 
     457    memcpy(&m_datlists, &datlists, sizeof(datlists)); 
    379458} 
    380459 
    381460FirmwareUtil::~FirmwareUtil() 
    382461{ 
     462} 
     463 
     464bool 
     465FirmwareUtil::isValidForDevice(Firmware f) 
     466{ 
     467    std::string src = f.getSourceString(); 
     468 
     469    uint32_t vendor = m_Parent.getConfigRom().getNodeVendorId(); 
     470    uint32_t model = m_Parent.getConfigRom().getModelId(); 
     471 
     472    for (unsigned int i=0; i<ECHO_FIRMWARE_NUM_BOXTYPES; i++) { 
     473        if(m_datlists[i].boxtype == model 
     474           && m_datlists[i].vendorid == vendor) 
     475        { 
     476            for(int j=0; j<m_datlists[i].count; j++) { 
     477                std::string cmpstring = m_datlists[i].filenames[j]; 
     478                cmpstring += ".dat"; 
     479                std::string::size_type loc = src.find( cmpstring, 0 ); 
     480                if( loc != std::string::npos ) { 
     481                    debugOutput(DEBUG_LEVEL_VERBOSE, "found filename\n"); 
     482                    return true; 
     483                    break; 
     484                 } 
     485            } 
     486        } 
     487    } 
     488    debugOutput(DEBUG_LEVEL_VERBOSE, "file not for this device\n"); 
     489    return false; 
    383490} 
    384491 
     
    407514 
    408515bool 
    409 FirmwareUtil::waitForFlash() 
    410 
    411     bool ready; 
    412  
    413     EfcFlashGetStatusCmd statusCmd; 
    414     const unsigned int time_to_sleep_usecs = 10000; 
    415     int wait_cycles = ECHO_FLASH_TIMEOUT_MILLISECS * 1000 / time_to_sleep_usecs; 
    416  
    417     do { 
    418         if (!m_Parent.doEfcOverAVC(statusCmd)) { 
    419             debugError("Could not read flash status\n"); 
    420             return false; 
    421         } 
    422         if (statusCmd.m_header.retval == EfcCmd::eERV_FlashBusy) { 
    423             ready = false; 
    424         } else { 
    425             ready = statusCmd.m_ready; 
    426         } 
    427         usleep(time_to_sleep_usecs); 
    428     } while (!ready && wait_cycles--); 
    429  
    430     if(wait_cycles == 0) { 
    431         debugError("Timeout while waiting for flash\n"); 
    432         return false; 
    433     } 
    434  
    435     return ready; 
     516FirmwareUtil::writeFirmwareToDevice(Firmware f) 
     517
     518    uint32_t start_addr = f.getAddress(); 
     519    uint32_t writelen = f.getWriteDataLen(); 
     520    uint32_t buff[writelen * 4]; 
     521    if (!f.getWriteData(buff)) { 
     522        debugError("Could not prepare data for writing to the device\n"); 
     523        return false; 
     524    } 
     525    if(!m_Parent.writeFlash(start_addr, writelen, buff)) { 
     526        debugError("Writing to flash failed.\n"); 
     527        return false; 
     528    } 
     529    return true; 
    436530} 
    437531 
     
    439533FirmwareUtil::eraseBlocks(uint32_t start_address, unsigned int nb_quads) 
    440534{ 
    441     EfcFlashEraseCmd eraseCmd; 
    442535    uint32_t blocksize_bytes; 
    443536    uint32_t blocksize_quads; 
     
    458551        blocksize_quads = blocksize_bytes / 4; 
    459552 
     553        uint32_t verify[blocksize_quads]; 
     554 
    460555        // corner case: requested to erase less than one block 
    461556        if (blocksize_quads > quads_left) { 
     
    464559 
    465560        // do the actual erase 
    466         eraseCmd.m_address = start_address; 
    467         if (!m_Parent.doEfcOverAVC(eraseCmd)) { 
     561        if (!m_Parent.eraseFlash(start_address)) { 
    468562            debugWarning("Could not erase flash block at 0x%08X\n", start_address); 
    469563            success = false; 
    470564        } else { 
     565            // wait for the flash to become ready again 
     566            if (!m_Parent.waitForFlash(ECHO_FLASH_ERASE_TIMEOUT_MILLISECS)) { 
     567                debugError("Wait for flash timed out at address 0x%08X\n", start_address); 
     568                return false; 
     569            } 
     570 
    471571            // verify that the block is empty as an extra precaution 
    472             EfcFlashReadCmd readCmd; 
    473             readCmd.m_address = start_address; 
    474             readCmd.m_nb_quadlets = blocksize_quads; 
    475             uint32_t verify_quadlets_read = 0; 
    476             do { 
    477                 if (!m_Parent.doEfcOverAVC(readCmd)) { 
    478                     debugError("Could not read flash block at 0x%08X\n", start_address); 
    479                     return false; 
     572            if (!m_Parent.readFlash(start_address, blocksize_quads, verify)) { 
     573                debugError("Could not read flash block at 0x%08X\n", start_address); 
     574                return false; 
     575            } 
     576 
     577            // everything should be 0xFFFFFFFF if the erase was successful 
     578            for (unsigned int i = 0; i < blocksize_quads; i++) { 
     579                if (0xFFFFFFFF != verify[i]) { 
     580                    debugWarning("Flash erase verification failed.\n"); 
     581                    success = false; 
     582                    break; 
    480583                } 
    481  
    482                 // everything should be 0xFFFFFFFF if the erase was successful 
    483                 for (unsigned int i = 0; i < readCmd.m_nb_quadlets; i++) { 
    484                     if (0xFFFFFFFF != readCmd.m_data[i]) { 
    485                         debugWarning("Flash erase verification failed.\n"); 
    486                         success = false; 
    487                         break; 
    488                     } 
    489                 } 
    490   
    491                 // maybe not everything was read at once 
    492                 verify_quadlets_read += readCmd.m_nb_quadlets; 
    493                 readCmd.m_address += start_address + verify_quadlets_read * 4; 
    494                 readCmd.m_nb_quadlets = blocksize_quads - verify_quadlets_read; 
    495             } while(verify_quadlets_read < blocksize_quads); 
     584            } 
    496585        } 
    497586 
     
    504593        } 
    505594        if (nb_tries > max_nb_tries) { 
    506             debugError("Needed too many tries to erase flash at 0x%08X", start_address); 
     595            debugError("Needed too many tries to erase flash at 0x%08X\n", start_address); 
    507596            return false; 
    508597        } 
     
    511600    return true; 
    512601} 
    513  
    514602 
    515603void 
  • trunk/libffado/src/fireworks/fireworks_firmware.h

    r1010 r1011  
    5151#define ECHO_FIRMWARE_FILE_MAX_LENGTH_QUADLETS  ((384 * 1024) / 4) 
    5252#define ECHO_FIRMWARE_FILE_MAX_LENGTH_BYTES     (ECHO_FIRMWARE_FILE_MAX_LENGTH_QUADLETS * 12 + ECHO_FIRMWARE_HEADER_LENGTH_BYTES) 
     53 
     54#define ECHO_FIRMWARE_NUM_BOXTYPES  4 
    5355 
    5456class Firmware 
     
    7678    virtual bool isValid() {return m_valid;}; 
    7779 
     80    virtual std::string getSourceString() {return m_source;}; 
     81 
    7882    /** 
    7983     * @brief compare two firmwares 
     
    9498     */ 
    9599    virtual uint32_t getLength() {return m_length_quads;}; 
     100 
     101    /** 
     102     * @brief get length of data to be written to the device (in quadlets) 
     103     * @return length (in quadlets) 
     104     */ 
     105    virtual uint32_t getWriteDataLen(); 
     106    /** 
     107     * @brief prepares data to be written to the device 
     108     * @param buff buffer to copy data into. should be at least getWriteDataLen() quadlets. 
     109     * @return true if successful 
     110     */ 
     111    virtual bool getWriteData(uint32_t *buff); 
    96112 
    97113    virtual void show(); 
     
    143159    Firmware getFirmwareFromDevice(uint32_t start, uint32_t length); 
    144160 
    145     /** 
    146      * @brief wait until the device indicates the flash memory is ready 
    147      * @return true if the flash is ready, false if not (or timeout) 
    148      */ 
    149     bool waitForFlash(); 
     161 
     162    /** 
     163     * @brief writes a firmware to the device 
     164     * @param f firmware to write 
     165     * @return true if successful 
     166     */ 
     167    bool writeFirmwareToDevice(Firmware f); 
    150168 
    151169    /** 
     
    157175    bool eraseBlocks(unsigned int address, unsigned int nb_quads); 
    158176 
     177    /** 
     178     * @brief checks whether a firmware is valid for this device 
     179     * @param f firmware to check 
     180     * @return true if valid, false if not 
     181     */ 
     182    bool isValidForDevice(Firmware f); 
     183 
    159184protected: 
    160185    FireWorks::Device&          m_Parent; 
     186 
     187private: 
     188    struct dat_list 
     189    { 
     190        uint32_t    vendorid; 
     191        uint32_t    boxtype; 
     192        uint32_t    minversion; 
     193        int         count; 
     194        char        **filenames; 
     195    }; 
     196 
     197    struct dat_list m_datlists[ECHO_FIRMWARE_NUM_BOXTYPES]; 
     198 
    161199private: 
    162200    DECLARE_DEBUG_MODULE; 
  • trunk/libffado/support/firmware/downloader.cpp

    r1009 r1011  
    11/* 
    22 * Copyright (C) 2005-2008 by Daniel Wagner 
     3 * Copyright (C) 2005-2008 by Pieter Palmers 
    34 * 
    45 * This file is part of FFADO 
     
    7980        } 
    8081        break; 
     82    case 'm': 
     83        errno = 0; 
     84        arguments->magic = strtoll(arg, &tail, 0); 
     85        if (errno) { 
     86            debugError("argument parsing failed: %s\n", 
     87                       strerror(errno)); 
     88            return errno; 
     89        } 
     90        break; 
    8191    case 'f': 
    8292        arguments->force = 1; 
  • trunk/libffado/support/firmware/downloader.h

    r1009 r1011  
    11/* 
    22 * Copyright (C) 2005-2008 by Daniel Wagner 
     3 * Copyright (C) 2005-2008 by Pieter Palmers 
    34 * 
    45 * This file is part of FFADO 
     
    4546    int   no_bootloader_restart; 
    4647    uint64_t guid; 
     48    uint64_t magic; 
    4749}; 
    4850 
  • trunk/libffado/support/firmware/fireworks-downloader.cpp

    r1010 r1011  
    3939#include <string.h> 
    4040#include <string> 
     41 
     42#define MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING 0x001807198000LL 
    4143 
    4244using namespace FireWorks; 
     
    7173    {"guid",      'g', "GUID",      0,  "GUID of the target device" }, 
    7274    {"port",      'p', "PORT",      0,  "Port to use" }, 
     75    {"magic",     'm', "MAGIC",     0,  "A magic number you have to obtain before this code will work."  
     76                                        "Specifying it means that you accept the risks that come with this tool."}, 
    7377    { 0 } 
    7478}; 
     
    9599        argp_help(argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC, argv[0]); 
    96100        exit(-1); 
     101    } 
     102 
     103    if(args->magic != MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING) { 
     104        printMessage("Magic number not correct. Please specify the correct magic using the '-m' option.\n"); 
     105        printMessage("Manipulating firmware can cause your device to magically stop working (a.k.a. 'bricking').\n"); 
     106        printMessage("Specifying the magic number indicates that you accept the risks involved\n"); 
     107        printMessage("with using this tool. The magic number can be found in the source code.\n"); 
     108        return -1; 
     109    } else { 
     110        printMessage("YOU HAVE SPECIFIED THE CORRECT MAGIC NUMBER.\n"); 
     111        printMessage("HENCE YOU ACCEPT THE RISKS INVOLVED.\n"); 
    97112    } 
    98113 
     
    194209        return -1; 
    195210    } 
     211    dev->setVerboseLevel(args->verbose); 
    196212 
    197213    if ( strcmp( args->args[0], "display" ) == 0 ) { 
     
    227243        f.setVerboseLevel( args->verbose ); 
    228244        f.show(); 
     245        f.dumpData(); 
    229246        printMessage("Saving to file not yet supported.\n"); 
    230247    } else if (strcmp( args->args[0], "verify" ) == 0) { 
     
    272289            printMessage(" => Verify successful. Device content identical to file content.\n"); 
    273290        } 
    274  
    275     } else if (false) { 
     291    } else if (strcmp( args->args[0], "upload" ) == 0) { 
     292        if (!args->args[1] ) { 
     293            printMessage("FILE argument is missing\n"); 
     294            delete dev; 
     295            return -1; 
     296        } 
     297        std::string str( args->args[1] ); 
     298 
    276299        // create the firmware util class 
    277300        FirmwareUtil util = FirmwareUtil(*dev); 
    278301        util.setVerboseLevel( args->verbose ); 
    279302 
     303        printMessage("Uploading %s to device\n", str.c_str()); 
     304 
     305        printMessage(" loading file...\n"); 
     306        // load the file 
     307        Firmware ref = Firmware(); 
     308        ref.setVerboseLevel( args->verbose ); 
     309         
     310        if (!ref.loadFile(str)) { 
     311            printMessage("  Could not load firmware from file\n"); 
     312            delete dev; 
     313            return -1; 
     314        } 
     315 
     316        printMessage(" checking file...\n"); 
     317        if(!ref.isValid()) { 
     318            printMessage("  Firmware not valid\n"); 
     319            delete dev; 
     320            return -1; 
     321        } 
     322 
     323        if(!util.isValidForDevice(ref)) { 
     324            printMessage("  Firmware not valid for this device\n"); 
     325            delete dev; 
     326            return -1; 
     327        } 
     328        printMessage("  seems to be valid firmware for this device...\n"); 
     329 
     330        // get the flash position from the loaded file 
     331        uint32_t start_addr = ref.getAddress(); 
     332        uint32_t len = ref.getLength(); 
     333 
     334        printMessage(" lock flash...\n"); 
     335        if (!dev->lockFlash(true)) { 
     336            printMessage("  Could not lock flash\n"); 
     337            delete dev; 
     338            return -1; 
     339        } 
     340 
     341        printMessage(" erasing memory...\n"); 
     342        if (!util.eraseBlocks(start_addr, len)) { 
     343            printMessage("  Could not erase memory\n"); 
     344            delete dev; 
     345            return -1; 
     346        } 
     347 
     348        printMessage(" uploading to device...\n"); 
     349        if (!util.writeFirmwareToDevice(ref)) { 
     350            printMessage("  Could not write firmware to device\n"); 
     351            delete dev; 
     352            return -1; 
     353        } 
     354 
     355        printMessage(" unlock flash...\n"); 
     356        if (!dev->lockFlash(false)) { 
     357            printMessage("  Could not unlock flash\n"); 
     358            delete dev; 
     359            return -1; 
     360        } 
     361 
     362        // now verify 
     363        printMessage(" verify...\n"); 
     364 
     365 
     366        printMessage("  reading device...\n"); 
     367        // read the corresponding part of the device 
     368        Firmware f = util.getFirmwareFromDevice(start_addr, len); 
     369        f.setVerboseLevel( args->verbose ); 
     370        f.show(); 
     371         
     372        printMessage("  comparing...\n"); 
     373        // compare the two images 
     374        if(!(f == ref)) { 
     375            printMessage(" => Verify failed. Firmware upload failed.\n"); 
     376            delete dev; 
     377            return -1; 
     378        } else { 
     379            printMessage(" => Verify successful. Firmware upload successful.\n"); 
     380        } 
    280381    }  else { 
    281382        printMessage("Unknown operation\n");