123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- /*====================================================================*
- *
- * Copyright (c) 2013 Qualcomm Atheros, Inc.
- *
- * All rights reserved.
- *
- *====================================================================*/
- /*====================================================================*
- *
- * CPLFirmware.cpp - CPLFirmware class definition;
- *
- * read/write a parameter block image from/to a device/file;
- *
- * Contributor(s):
- * Charles Maier <charles.maier@intellon.com>
- *
- *--------------------------------------------------------------------*/
- #ifndef CPLFIRMWARE_SOURCE
- #define CPLFIRMWARE_SOURCE
- /*====================================================================*
- * system header files;
- *--------------------------------------------------------------------*/
- #include <cstring>
- #include <fstream>
- /*====================================================================*
- * custom header files;
- *--------------------------------------------------------------------*/
- #include "../classes/CPLFirmware.hpp"
- #include "../classes/ohomeplug.hpp"
- #include "../classes/omemory.hpp"
- #include "../classes/oerror.hpp"
- #include "../tools/endian.h"
- /*====================================================================*
- *
- * void * Data () const;
- *
- * return firmware image sequence address as a void pointer; this
- * property can be used to perform image sequence operations that
- * have not been implemented by this class;
- *
- *--------------------------------------------------------------------*/
- void * CPLFirmware::Data () const
- {
- return ((void *)(this->mbuffer));
- }
- /*====================================================================*
- *
- * size_t Size () const;
- *
- * return firmware image sequence extent (length) in bytes;
- *
- *--------------------------------------------------------------------*/
- size_t CPLFirmware::Size () const
- {
- return (this->mextent);
- }
- /*====================================================================*
- *
- * bool IsValid () const;
- *
- * return true of the firmware image sequence is valid; check the
- *
- * this method may be expanded to include other parameter block
- * validity tests;
- *
- *--------------------------------------------------------------------*/
- bool CPLFirmware::IsValid () const
- {
- CPLFirmware::Header const * header;
- byte const * offset = (byte const *)(this->mbuffer);
- signed extent = this->mextent;
- signed image = 0;
- if ((!this->mbuffer) || (!this->mextent))
- {
- // oerror::error (0, ECANCELED, "No Firmware Image Available");
- return (false);
- }
- do
- {
- std::cout << "start " << image << std::endl;
- header = (CPLFirmware::Header const *)(offset);
- #if 1
- CPLFirmware::Peek (header);
- #endif
- if (LE32TOH (header->HEADERVERSION) != NVM_HEADER_VERSION)
- {
- oerror::error (1, 0, "Bad header version");
- return (false);
- }
- if (omemory::checksum32 (header, sizeof (CPLFirmware::Header), 0))
- {
- oerror::error (1, 0, "Bad header checksum");
- return (false);
- }
- offset += sizeof (CPLFirmware::Header);
- extent -= sizeof (CPLFirmware::Header);
- if (omemory::checksum32 (offset, LE32TOH (header->IMAGELENGTH), header->IMAGECHECKSUM))
- {
- oerror::error (1, 0, "Bad image checksum");
- return (false);
- }
- offset += header->IMAGELENGTH;
- extent -= header->IMAGELENGTH;
- image++;
- std::cout << "end " << image << std::endl;
- }
- while (header->NEXTHEADER);
- std::cout << "exit" << std::endl;
- return (!extent);
- }
- /*====================================================================*
- *
- * signed CPLFirmware::Read (char const * filename);
- *
- * read firmware image sequence from the named file;
- *
- *--------------------------------------------------------------------*/
- signed CPLFirmware::Read (char const * filename)
- {
- if (this->mbuffer)
- {
- delete [] this->mbuffer;
- }
- this->mextent = 0;
- if ((filename) && (*filename))
- {
- std::ifstream stream;
- stream.open (filename, std::ios::binary);
- if (stream.good ())
- {
- stream.seekg (0, std::ios::end);
- this->mextent = stream.tellg ();
- stream.seekg (0, std::ios::beg);
- this->mbuffer = new uint8_t [this->mextent];
- stream.read ((char *)(this->mbuffer), this->mextent);
- }
- stream.close ();
- }
- return (0);
- }
- /*====================================================================*
- *
- * signed Write (char const * filename);
- *
- * write firmware image sequence to the named file;
- *
- *--------------------------------------------------------------------*/
- signed CPLFirmware::Write (char const * filename)
- {
- std::ofstream stream;
- stream.open (filename, std::ios::binary);
- if (stream.good ())
- {
- stream.write ((char *)(this->mbuffer), this->mextent);
- }
- stream.close ();
- return (0);
- }
- /*====================================================================*
- *
- * signed Read (CPLCHannel * channel)
- *
- * read a firmware image sequence from the local powerline device
- * into memory using as many VS_RD_MOD messages as needed;
- *
- * return 0 on success or -1 on failure;
- *
- *--------------------------------------------------------------------*/
- #if 0
- signed CPLFirmware::Read (CPLChannel * channel)
- {
- ointellon intellon;
- uint8_t message [ETHER_MAX_LEN];
- #ifndef __GNUC__
- #pragma pack (push,1)
- #endif
- struct __packed vs_rd_mod_request
- {
- struct header_eth ethernet;
- struct header_int intellon;
- uint8_t MODULEID;
- uint8_t MACCESS;
- uint16_t MLENGTH;
- uint32_t MOFFSET;
- uint8_t MSECRET [16];
- }
- * request = (struct vs_rd_mod_request *) (message);
- struct __packed vs_rd_mod_confirm
- {
- struct header_eth ethernet;
- struct header_int intellon;
- uint8_t MSTATUS;
- uint8_t RES [3];
- uint8_t MODULEID;
- uint8_t RESERVED;
- uint16_t MLENGTH;
- uint32_t MOFFSET;
- uint32_t CHKSUM;
- uint8_t BUFFER [INT6K_BLOCKSIZE];
- }
- * confirm = (struct vs_rd_mod_confirm *) (message);
- #ifndef __GNUC__
- #pragma pack (pop)
- #endif
- uint16_t extent = 0;
- uint16_t length = oINTELLON_BLOCKSIZE;
- uint32_t offset = 0;
- intellon.ImportPeerAddress (channel->PeerAddress ());
- intellon.ImportHostAddress (channel->HostAddress ());
- intellon.SetMessageType (VS_RD_MOD | MMTYPE_REQ);
- do
- {
- std::memset (message, 0, sizeof (message));
- request = (struct vs_rd_mod_request *)(intellon.ExportHeader (message));
- confirm = (struct vs_rd_mod_confirm *)(request);
- request->MODULEID = VS_MODULE_MAC;
- request->MLENGTH = HTOLE16 (length);
- request->MOFFSET = HTOLE32 (offset);
- if (channel->SendMessage (message, ETHER_MIN_LEN) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTSEND);
- return (-1);
- }
- if (channel->ReadMessage (message, sizeof (message)) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTREAD);
- return (-1);
- }
- if (confirm->MSTATUS)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_WONTDOIT);
- return (-1);
- }
- #if 1
- if (LE16TOH (confirm->MLENGTH) != length)
- {
- oerror::error (0, ECANCELED, oINTELLON_BAD_LENGTH);
- return (-1);
- }
- if (LE32TOH (confirm->MOFFSET) != offset)
- {
- oerror::error (0, ECANCELED, oINTELLON_BAD_LENGTH);
- return (-1);
- }
- #else
- if (LE16TOH (confirm->MLENGTH) != length)
- {
- oerror::error (0, EIO, oINTELLON_BAD_LENGTH);
- this->mlength = INT6K_BLOCKSIZE;
- this->moffset = 0;
- continue;
- }
- if (LE32TOH (confirm->MOFFSET) != this->moffset)
- {
- oerror::error (0, EIO, oINTELLON_BAD_OFFSET);
- this->mlength = INT6K_BLOCKSIZE;
- this->moffset = 0;
- continue;
- }
- #endif
- length = LE16TOH (confirm->MLENGTH);
- offset = LE32TOH (confirm->MOFFSET);
- if (omemory::checksum32 (confirm->MBUFFER, length, confirm->MCHKSUM))
- {
- oerror::error (0, ECANCELED, "Bad Message Checksum");
- return (-1);
- }
- if (offset == extent)
- {
- CPLFirmware::Header * header = (CPLFirmware::Header *)(confirm->BUFFER);
- if (checksum_32 (header, sizeof (CPLFirmware::Header), 0))
- {
- oerror::error (0, ECANCELED, "Bad Header Checksum");
- return (-1);
- }
- if (header_nvm->HEADERVERSION != NVM_HEADER_VERSION)
- {
- oerror::error (0, ECANCELED, "Bad Header Version");
- return (-1);
- }
- extent += sizeof (CPLFirmware::Header);
- extent += LE32TOH (header_nvm->IMAGELENGTH);
- header = LE16TOH (header_nvm->NEXTHEADER);
- }
- if ((offset + length) > extent)
- {
- length = extent - offset;
- }
- std::memcpy (this->mbuffer + offset, confirm->MBUFFER, length);
- offset += length;
- extent -= length;
- }
- while ((header) || (offset < extent));
- return (0);
- }
- #endif
- /*====================================================================*
- *
- * signed Write (CPLChannel * channel);
- *
- * write the firmware image sequence from memory to any powerline
- * device using as many VS_WR_MOD messages as needed;
- *
- * the runtime firmware must be running for this to work;
- *
- * return 0 on success or -1 on failure;
- *
- *--------------------------------------------------------------------*/
- signed CPLFirmware::Write (CPLChannel * channel)
- {
- ointellon intellon;
- uint8_t message [ETHER_MAX_LEN];
- #ifndef __GNUC__
- #pragma pack (push,1)
- #endif
- struct __packed vs_wr_mod_request
- {
- uint8_t MODULEID;
- uint8_t RESERVED;
- uint16_t MLENGTH;
- uint32_t MOFFSET;
- uint32_t MCHKSUM;
- uint8_t MBUFFER [oINTELLON_BLOCKSIZE];
- }
- * request;
- struct __packed vs_wr_mod_confirm
- {
- uint8_t MSTATUS;
- uint8_t MODULEID;
- uint8_t RESERVED;
- uint16_t MLENGTH;
- uint32_t MOFFSET;
- }
- * confirm;
- #ifndef __GNUC__
- #pragma pack (pop)
- #endif
- uint16_t length = oINTELLON_BLOCKSIZE;
- uint16_t extent = this->mextent;
- uint32_t offset = 0;
- intellon.ImportPeerAddress (channel->PeerAddress ());
- intellon.ImportHostAddress (channel->HostAddress ());
- intellon.SetMessageType (VS_WR_MOD | MMTYPE_REQ);
- while (extent)
- {
- if (length > extent)
- {
- length = extent;
- }
- std::memset (message, 0, sizeof (message));
- request = (struct vs_wr_mod_request *) (intellon.ExportHeader (message));
- confirm = (struct vs_wr_mod_confirm *) (request);
- std::memcpy (request->MBUFFER, this->mbuffer + offset, length);
- request->MODULEID = VS_MODULE_MAC;
- request->RESERVED = 0;
- request->MLENGTH = HTOLE16 (length);
- request->MOFFSET = HTOLE32 (offset);
- request->MCHKSUM = omemory::checksum32 (request->MBUFFER, length, 0);
- if (channel->SendMessage (message, intellon.BufferLength (sizeof (struct vs_wr_mod_request))) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTSEND);
- return (-1);
- }
- if (channel->ReadMessage (message, sizeof (message)) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTREAD);
- return (-1);
- }
- if (confirm->MSTATUS)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_WONTDOIT);
- return (-1);
- }
- #if 1
- if (LE16TOH (confirm->MLENGTH) != length)
- {
- oerror::error (0, ECANCELED, oINTELLON_BAD_LENGTH);
- return (-1);
- }
- if (LE32TOH (confirm->MOFFSET) != offset)
- {
- oerror::error (0, ECANCELED, oINTELLON_BAD_OFFSET);
- return (-1);
- }
- #else
- if (LE16TOH (confirm->MLENGTH) != length)
- {
- oerror::error (0, EIO, oINTELLON_BAD_LENGTH);
- length = oINTELLON_BLOCKSIZE;
- offset = 0;
- continue;
- }
- if (LE32TOH (confirm->MOFFSET) != offset)
- {
- oerror::error (0, EIO, oINTELLON_BAD_OFFSET);
- length = oINTELLON_BLOCKSIZE;
- offset = 0;
- continue;
- }
- #endif
- offset += length;
- extent -= length;
- }
- return (0);
- }
- /*====================================================================*
- *
- * signed Flash (CPLChannel *channel);
- *
- * commit downloaded firmware image sequence to flash memory;
- *
- *--------------------------------------------------------------------*/
- signed CPLFirmware::Flash (CPLChannel *channel)
- {
- ointellon intellon;
- uint8_t message [ETHER_MAX_LEN];
- #ifndef __GNUC__
- #pragma pack (push,1)
- #endif
- struct __packed vs_wr_mod_nvm_request
- {
- uint8_t MODULEID;
- uint8_t RESERVED;
- }
- * request;
- struct __packed vs_wr_mod_nvm_confirm
- {
- uint8_t MSTATUS;
- uint8_t MODULEID;
- }
- * confirm;
- #ifndef __GNUC__
- #pragma pack (pop)
- #endif
- intellon.ImportPeerAddress (channel->PeerAddress ());
- intellon.ImportHostAddress (channel->HostAddress ());
- intellon.SetMessageType (VS_MOD_NVM | MMTYPE_REQ);
- request = (struct vs_wr_mod_nvm_request *) (intellon.ExportHeader (message));
- confirm = (struct vs_wr_mod_nvm_confirm *) (request);
- request->MODULEID = VS_MODULE_MAC;
- request->RESERVED = 0;
- if (channel->SendMessage (message, ETHER_MIN_LEN) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTSEND);
- return (-1);
- }
- if (channel->ReadMessage (message, sizeof (message)) <= 0)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_CANTREAD);
- return (-1);
- }
- if (confirm->MSTATUS)
- {
- oerror::error (0, ECANCELED, CPLCHANNEL_WONTDOIT);
- return (-1);
- }
- return (0);
- }
- /*====================================================================*
- *
- * CPLFirmware & CPLFirmware::Peek (void const * memory);
- *
- *--------------------------------------------------------------------*/
- void CPLFirmware::Peek (void const * memory) const
- {
- CPLFirmware::Header const * header = (CPLFirmware::Header const *)(memory);
- static char const * platforms [] =
- {
- "INT6000",
- "INT6300",
- "INT6400",
- "AR7400",
- (char const *)(0)
- };
- static char const * functions []=
- {
- "Generic Image",
- "Synopsis Configuration",
- "Denali Configuration",
- "Denali Applet",
- "Firmware Image",
- "OAS Client",
- "Custom Image",
- "Memory Control",
- };
- std::printf ("\tHeader Version = 0x%08X-%02X\n", LE32TOH (header->HEADERVERSION), header->HEADERMINORVERSION);
- std::printf ("\tHeader Checksum = 0x%08X\n", LE32TOH (header->HEADERCHECKSUM));
- std::printf ("\tHeader Next = 0x%08X\n", LE32TOH (header->NEXTHEADER));
- std::printf ("\tFlash Address = 0x%08X\n", LE32TOH (header->IMAGEROMADDR));
- std::printf ("\tImage Address = 0x%08X\n", LE32TOH (header->IMAGEADDR));
- std::printf ("\tEntry Address = 0x%08X\n", LE32TOH (header->ENTRYPOINT));
- std::printf ("\tImage Checksum = 0x%08X\n", LE32TOH (header->IMAGECHECKSUM));
- std::printf ("\tImage Size = 0x%08X (%d)\n", LE32TOH (header->IMAGELENGTH), LE32TOH (header->IMAGELENGTH));
- if (header->IMAGETYPE < (sizeof (functions) / sizeof (char const *)))
- {
- std::printf ("\tImage Type = %s\n", functions [header->IMAGETYPE]);
- }
- else
- {
- std::cout << "\tImage Type = Unknown" << std::endl;
- }
- std::cout << "\tImage Omit = ";
- CPLFirmware::bitmap (platforms, LE16TOH (header->IGNOREMASK));
- std::cout << std::endl;
- std::cout << std::endl;
- return;
- }
- /*====================================================================*
- *
- * void bitmap (char const *operands [], unsigned flagword) const;
- *
- *--------------------------------------------------------------------*/
- void CPLFirmware::bitmap (char const * operands [], unsigned flagword) const
- {
- char const * separator = "";
- while ((*operands) && (flagword))
- {
- if (flagword & 1)
- {
- std::cout << separator << *operands;
- separator = "|";
- }
- flagword >>= 1;
- operands++;
- }
- return;
- }
- /*====================================================================*
- *
- * CPLFirmware & CPLFirmware::Init ();
- *
- * initialize instance variable;
- *
- *--------------------------------------------------------------------*/
- CPLFirmware & CPLFirmware::Init ()
- {
- this->mbuffer = (uint8_t *)(0);
- this->mextent = 0;
- return (*this);
- }
- /*====================================================================*
- *
- * CPLFirmware (CPLChannel * channel)
- *
- *--------------------------------------------------------------------*/
- #if 0
- CPLFirmware::CPLFirmware (CPLChannel * channel)
- {
- this->Init ().Read (channel);
- return;
- }
- #endif
- /*====================================================================*
- *
- * CPLFirmware (char const * filename)
- *
- *--------------------------------------------------------------------*/
- CPLFirmware::CPLFirmware (char const * filename)
- {
- this->Init ().Read (filename);
- return;
- }
- /*====================================================================*
- *
- * ~CPLFirmware ()
- *
- *--------------------------------------------------------------------*/
- CPLFirmware::~CPLFirmware ()
- {
- std::cout << "delete mbuffer" << std::endl;
- delete [] this->mbuffer;
- std::cout << "delete mbuffer" << std::endl;
- return;
- }
- /*====================================================================*
- * end definition;
- *--------------------------------------------------------------------*/
- #endif
|