Skip to content

Commit

Permalink
Various display improvements for STM32 debug probing
Browse files Browse the repository at this point in the history
  • Loading branch information
azonenberg committed Jul 20, 2018
1 parent 17e36e2 commit cec088b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 32 deletions.
3 changes: 1 addition & 2 deletions ARMv7MProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,9 @@ void ARMv7MProcessor::DumpRegisters()
CTRL
};

LogNotice("Dumping registers...\n");
LogIndenter li;
for(auto reg : all_regs)
LogNotice("%8s: %08x\n", GetRegisterName(reg), ReadCPURegister(reg));
LogNotice("%10s: %08x\n", GetRegisterName(reg), ReadCPURegister(reg));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions ARMv7MProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class ARMv7MProcessor : public DebuggableDevice

bool HaltedDueToUnrecoverableException();

void DumpRegisters();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Memory access via the default (AHB) MEM-AP

Expand All @@ -152,8 +154,6 @@ class ARMv7MProcessor : public DebuggableDevice
void EnterDebugState();
void ExitDebugState();

void DumpRegisters();

/*
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ID register state etc
Expand Down
15 changes: 8 additions & 7 deletions JtagInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,14 @@ void JtagInterface::LeaveExit1DR()
*/
void JtagInterface::PrintChainFaultMessage()
{
LogNotice("Failed to initialize the JTAG chain. Possible causes:\n");
LogNotice("* Target is not powered\n");
LogNotice("* Target has JTAG disabled\n");
LogNotice("* Target is connected incorrectly\n");
LogNotice("* JTAG adapter is not working correctly\n");
LogNotice("Failed to initialize the JTAG chain. Recommended actions:\n");
LogNotice("\n");
LogNotice("1) Confirm that the target board is powered on.\n");
LogNotice("2) Check the connection from the JTAG adapter to the target board to see if anything is loose\n");
LogNotice("3) Make sure that TDI, TDO, TMS, TCK, power, and ground are connected to the right pins\n");
LogNotice("4) Test the JTAG adapter on a known-good board to make sure it's working.\n");
LogNotice("\n");
LogNotice("If you still see this message, the target board may be malfunctioning or have JTAG disabled by security bits.\n");
}

/**
Expand All @@ -190,8 +193,6 @@ void JtagInterface::PrintChainFaultMessage()
*/
void JtagInterface::InitializeChain()
{
LogIndenter li;

unsigned char lots_of_ones[128];
memset(lots_of_ones, 0xff, sizeof(lots_of_ones));
unsigned char lots_of_zeros[128];
Expand Down
4 changes: 2 additions & 2 deletions LockableDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ class LockableDevice
virtual void ProbeLocksDestructive() =0;

/**
@brief Checks if a given physical address range has a given protection applied.
@brief Checks if a given physical address has a given protection applied.
*/
virtual UncertainBoolean CheckMemoryAccess(uint32_t start, uint32_t end, unsigned int access) =0;
virtual UncertainBoolean CheckMemoryAccess(uint32_t ptr, unsigned int access) =0;

/**
@brief Checks if the device is globally read protected or not
Expand Down
62 changes: 44 additions & 18 deletions STM32Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,33 +252,40 @@ void STM32Device::PrintLockProbeDetails()
{
auto cpu = GetCPU();

LogNotice("[+] Able to enumerate JTAG chain and see device IDs\n");
const char* table[]=
{
"completely unlocked",
"boundary scan enabled, memory access and debug disabled",
"JTAG completely disabled"
};
LogNotice("STM32 read protection level appears to be: %d (%s)\nDetails:\n", m_protectionLevel, table[m_protectionLevel]);

if(!cpu)
LogNotice("[-] Unable to find CPU on ARM DAP. Can't do most other probes\n");
else
{
LogNotice("[+] Detected CPU on ARM DAP: %s\n", cpu->GetDescription().c_str());
LogIndenter li;

if(!cpu)
return;

try
{
cpu->ReadCPURegister(ARMv7MProcessor::R0);
LogNotice("[+] Able to read CPU registers\n");
LogNotice("CPU registers: unlocked\n");
cpu->DumpRegisters();
}
catch(const JtagException& e)
{
LogNotice("[-] Unable to read CPU registers\n");
LogNotice("CPU registers: locked\n");
}

try
{
cpu->ReadMemory(m_flashMemoryBase);
LogNotice("[+] Able to read Flash memory. Dumping first few words as proof\n");
LogNotice("Flash: unlocked, dumping first few bytes\n");
LogIndenter li;
for(int i=0; i<4; i++)
{
uint32_t addr = m_flashMemoryBase + 16*i;
LogNotice("0x%08x: %08x %08x %08x %08x\n",
LogVerbose("0x%08x: %08x %08x %08x %08x\n",
addr,
cpu->ReadMemory(addr),
cpu->ReadMemory(addr + 0x4),
Expand All @@ -290,18 +297,18 @@ void STM32Device::PrintLockProbeDetails()
}
catch(const JtagException& e)
{
LogNotice("[-] Unable to read Flash memory\n");
LogNotice("Flash: locked\n");
}

try
{
cpu->ReadMemory(m_sramMemoryBase);
LogNotice("[+] Able to read SRAM memory. Dumping first few words as proof\n");
LogNotice("SRAM: unlocked, dumping first few bytes\n");
LogIndenter li;
for(int i=0; i<4; i++)
{
uint32_t addr = m_sramMemoryBase + 16*i;
LogNotice("0x%08x: %08x %08x %08x %08x\n",
LogVerbose("0x%08x: %08x %08x %08x %08x\n",
addr,
cpu->ReadMemory(addr),
cpu->ReadMemory(addr + 0x4),
Expand All @@ -313,11 +320,9 @@ void STM32Device::PrintLockProbeDetails()
}
catch(const JtagException& e)
{
LogNotice("[-] Unable to read SRAM memory\n");
LogNotice("SRAM: locked\n");
}
}

LogNotice("STM32 read protection level appears to be: level %d\n", m_protectionLevel);
}

void STM32Device::ProbeLocksNondestructive()
Expand Down Expand Up @@ -377,10 +382,31 @@ void STM32Device::ProbeLocksDestructive()
return ProbeLocksNondestructive();
}

UncertainBoolean STM32Device::CheckMemoryAccess(uint32_t /*start*/, uint32_t /*end*/, unsigned int /*access*/)
UncertainBoolean STM32Device::CheckMemoryAccess(uint32_t ptr, unsigned int access)
{
//Not yet implemented
return UncertainBoolean(false, UncertainBoolean::USELESS);
if(access != ACCESS_READ)
{
throw JtagExceptionWrapper(
"STM32Device write/execute testing not supported",
"");
}

try
{
//If we get a value other than 0 or FF, it's definitely good
uint32_t retval = m_dap->ReadMemory(ptr);
if( (retval != 0x00000000) && (retval != 0xffffffff) )
return UncertainBoolean(true, UncertainBoolean::CERTAIN);

//These values might be returned by some protection schemes if the chip is locked
//so give a slightly lower confidence
else
return UncertainBoolean(true, UncertainBoolean::VERY_LIKELY);
}
catch(const JtagException& e)
{
return UncertainBoolean(false, UncertainBoolean::VERY_LIKELY);
}
}

UncertainBoolean STM32Device::IsDeviceReadLocked()
Expand Down
8 changes: 7 additions & 1 deletion STM32Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,18 @@ class STM32Device

virtual void ProbeLocksNondestructive();
virtual void ProbeLocksDestructive();
virtual UncertainBoolean CheckMemoryAccess(uint32_t start, uint32_t end, unsigned int access);
virtual UncertainBoolean CheckMemoryAccess(uint32_t ptr, unsigned int access);
virtual UncertainBoolean IsDeviceReadLocked();
virtual void SetReadLock();
virtual void ClearReadLock();
virtual void PrintLockProbeDetails();

int GetProtectionLevel()
{
ProbeLocksNondestructive();
return m_protectionLevel;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Find our CPU

Expand Down

0 comments on commit cec088b

Please sign in to comment.