/*************************************************************************** * Copyright (C) 2005-2007 Nicolas Hadacek * * * * 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 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "pic_protection.h" #include "pic_config.h" #include bool Pic::Protection::isNoneProtectedValueName(const QString &name) const { if ( name=="Off" ) return true; if ( _data.architecture()==Architecture::P17C ) return !isAllProtectedValueName(name); return false; } bool Pic::Protection::isAllProtectedValueName(const QString &name) const { if ( name=="All" ) return true; if ( _data.architecture()==Architecture::P17C ) return ( name=="Code-protected microcontroller" ); return false; } Pic::Protection::Family Pic::Protection::family() const { if ( _config.findMask("WRTBS") ) return CodeGuard; QString mask = maskName(ProgramProtected, MemoryRangeType::Code); if ( _config.findMask(QString("%1_%2").arg(mask).arg(0)) ) return BlockProtection; if ( _config.findMask(mask) ) return BasicProtection; return NoProtection; } QString Pic::Protection::securityValueName(Type type) const { if ( type==StandardSecurity ) return "Standard Security"; if ( type==HighSecurity ) return "High Security"; Q_ASSERT( type==Nb_Types ); return "Off"; } QString Pic::Protection::bootSizeMaskName() const { return (family()==CodeGuard ? "BSSIZ" : "BBSIZ"); } QString Pic::Protection::bootMaskName(Type type) const { Q_ASSERT( type!=Nb_Types ); if ( family()==CodeGuard ) { if ( type==WriteProtected ) return "WRTBS"; if ( type==StandardSecurity || type==HighSecurity ) return "BSSEC"; } else { if ( type==ProgramProtected ) return "CPB"; if ( type==WriteProtected ) return "WRTB"; if ( type==ReadProtected ) return "EBTRB"; } return QString::null; } QString Pic::Protection::blockSizeMaskName(uint block) const { if ( family()==CodeGuard ) { Q_ASSERT( block==0 ); return "SSSIZ"; } return blockMaskName(ProgramProtected, block); } QString Pic::Protection::blockMaskName(Type type, uint block) const { Q_ASSERT( type!=Nb_Types ); if ( family()==CodeGuard ) { if ( type==WriteProtected ) return (block==0 ? "WRTSS" : "WRTGS"); if ( type==StandardSecurity || type==HighSecurity ) return (block==0 ? "SSSEC" : "GSSEC"); return QString::null; } return QString("%1_%2").arg(maskName(type, MemoryRangeType::Code)).arg(block); } QString Pic::Protection::maskName(Type type, MemoryRangeType mtype) const { Q_ASSERT( type!=Nb_Types ); switch (mtype.type()) { case MemoryRangeType::Code: if ( type==ProgramProtected ) { if ( _data.architecture()==Architecture::P17C ) return "PM"; if ( _data.architecture()==Architecture::P30F || _data.architecture()==Architecture::P24F ) return "GCP"; return "CP"; } if ( type==WriteProtected ) { if ( _data.architecture()==Architecture::P30F || _data.architecture()==Architecture::P24F ) return "GWRP"; return "WRT"; } if ( type==ReadProtected ) return "EBTR"; break; case MemoryRangeType::Eeprom: if ( type==ProgramProtected ) return "CPD"; if ( type==WriteProtected ) return "WRTD"; break; case MemoryRangeType::Cal: if ( type==ProgramProtected ) return "CPC"; break; case MemoryRangeType::Config: if ( type==WriteProtected ) return "WRTC"; if ( type==ReadProtected ) return "EBTRC"; break; case MemoryRangeType::Nb_Types: Q_ASSERT(false); break; default: break; } return QString::null; } bool Pic::Protection::extractRanges(const QString &name, QValueVector
&starts, Address &end, bool &ok) { ok = false; QRegExp regexp("([A-F0-9]+)(/[A-F0-9]+)?(/[A-F0-9]+)?:([A-F0-9]+)"); if ( !regexp.exactMatch(name) ) return false; bool ok1; end = fromHex(regexp.cap(regexp.numCaptures()), &ok1); if ( !ok1 ) { qDebug("Malformed end address"); return true; } starts.clear(); for (int i=1; i=end && (starts.count()==0 || starts[starts.count()-1] starts; Address end; bool ok2 = extractRanges(name, starts, end, ok1); Q_ASSERT(ok1); Q_ASSERT(ok2); Q_UNUSED(ok2); AddressRangeVector rv; for (uint i=0; ivalues.count()); k++) { bool ok1; uint size = bsmask->values[k].name.toUInt(&ok1); if ( !ok1 ) { qDebug("Could not recognize boot size value"); return pr; } if ( size==0 ) { qDebug("Boot size cannot be zero"); return pr; } Address end = 2 * size - 1; // instruction words if ( pr.ends.count()!=0 && end==pr.ends[pr.ends.count()-1] ) continue; pr.ends.append(end); qHeapSort(pr.ends); } } else { pr.starts.append(rdata.start); pr.ends.append(rdata.end); } ok = true; return pr; } if ( isBootBlock && bsmask ) { qDebug("Protected range should not be explicit when boot size is present"); return pr; } // extract start and end Address end; bool ok1; if ( !extractRanges(name, pr.starts, end, ok1) ) { qDebug("Could not recognized explicit range"); return pr; } if ( !ok1 ) return pr; if ( end>rdata.end ) { qDebug("End is beyond memory range"); return pr; } if ( (rtype!=MemoryRangeType::Code || isBootBlock) && (pr.starts.count()>1 || !rexp.cap(2).isEmpty() || bmask==0) ) { qDebug("Only code with blocks and boot can have multiple protected ranges"); return pr; } if ( isBootBlock && pr.starts[0]!=0 ) { qDebug("Boot block start should be zero"); return pr; } pr.ends.append(end); // check with boot block if ( pr.starts.count()>1 ) { if ( bmask==0 ) { qDebug("No boot mask"); return pr; } for (uint i=0; ivalues.count()); i++) { if ( bmask->values[i].name=="Off" ) continue; bool ok1; ProtectedRange bpr = extractRange(bmask->name, bmask->values[i].name, ok1); if ( !ok1 ) return pr; if ( bpr.ends.count()!=pr.starts.count() ) { qDebug("Boot number of ends (%i) should be the same as code number of starts (%i)", int(bpr.ends.count()), int(pr.starts.count())); return pr; } for (uint k=0; k