44#include < cstring>
55#include < cstdlib>
66#include < thread>
7+ #include < sddl.h>
8+
9+ #pragma comment(lib, "Advapi32.lib")
710
811namespace firmware
912{
1013 namespace
1114 {
15+ void WriteBits (std::uint8_t *dst, std::size_t dstBits, std::size_t offset, std::size_t width, std::uint64_t value)
16+ {
17+ if (!dst || width == 0 )
18+ return ;
19+ if (offset + width > dstBits)
20+ return ;
21+ for (std::size_t bit = 0 ; bit < width; ++bit)
22+ {
23+ std::size_t target = offset + bit;
24+ std::size_t byteIndex = target / 8 ;
25+ std::size_t bitIndex = target % 8 ;
26+ if ((value >> bit) & 0x1u )
27+ {
28+ dst[byteIndex] = static_cast <std::uint8_t >(dst[byteIndex] | (1u << bitIndex));
29+ }
30+ }
31+ }
32+
33+ void WriteDebugBits (std::uint8_t *dst, std::size_t dstBytes, const OutputDebugState &debug)
34+ {
35+ if (!dst || dstBytes < kDebugBitBytes )
36+ return ;
37+ std::memset (dst, 0 , dstBytes);
38+ const std::size_t dstBits = dstBytes * 8 ;
39+ WriteBits (dst, dstBits, kDbgBitPc , 16 , debug.pc );
40+ WriteBits (dst, dstBits, kDbgBitSp , 16 , debug.sp );
41+ WriteBits (dst, dstBits, kDbgBitSreg , 8 , debug.sreg );
42+ WriteBits (dst, dstBits, kDbgBitFlashBytes , 32 , debug.flashBytes );
43+ WriteBits (dst, dstBits, kDbgBitSramBytes , 32 , debug.sramBytes );
44+ WriteBits (dst, dstBits, kDbgBitEepromBytes , 32 , debug.eepromBytes );
45+ WriteBits (dst, dstBits, kDbgBitIoBytes , 32 , debug.ioBytes );
46+ WriteBits (dst, dstBits, kDbgBitCpuHz , 32 , debug.cpuHz );
47+ WriteBits (dst, dstBits, kDbgBitStackHighWater , 16 , debug.stackHighWater );
48+ WriteBits (dst, dstBits, kDbgBitHeapTop , 16 , debug.heapTopAddress );
49+ WriteBits (dst, dstBits, kDbgBitStackMin , 16 , debug.stackMinAddress );
50+ WriteBits (dst, dstBits, kDbgBitDataSegmentEnd , 16 , debug.dataSegmentEnd );
51+ WriteBits (dst, dstBits, kDbgBitStackOverflows , 32 , static_cast <std::uint32_t >(debug.stackOverflows ));
52+ WriteBits (dst, dstBits, kDbgBitInvalidMem , 32 , static_cast <std::uint32_t >(debug.invalidMemoryAccesses ));
53+ WriteBits (dst, dstBits, kDbgBitInterruptCount , 32 , static_cast <std::uint32_t >(debug.interruptCount ));
54+ WriteBits (dst, dstBits, kDbgBitInterruptLatencyMax , 32 , static_cast <std::uint32_t >(debug.interruptLatencyMax ));
55+ WriteBits (dst, dstBits, kDbgBitTimingViolations , 32 , static_cast <std::uint32_t >(debug.timingViolations ));
56+ WriteBits (dst, dstBits, kDbgBitCriticalSectionCycles , 32 , static_cast <std::uint32_t >(debug.criticalSectionCycles ));
57+ WriteBits (dst, dstBits, kDbgBitSleepCycles , 32 , static_cast <std::uint32_t >(debug.sleepCycles ));
58+ WriteBits (dst, dstBits, kDbgBitFlashAccessCycles , 32 , static_cast <std::uint32_t >(debug.flashAccessCycles ));
59+ WriteBits (dst, dstBits, kDbgBitUartOverflows , 32 , static_cast <std::uint32_t >(debug.uartOverflows ));
60+ WriteBits (dst, dstBits, kDbgBitTimerOverflows , 32 , static_cast <std::uint32_t >(debug.timerOverflows ));
61+ WriteBits (dst, dstBits, kDbgBitBrownOutResets , 32 , static_cast <std::uint32_t >(debug.brownOutResets ));
62+ WriteBits (dst, dstBits, kDbgBitGpioStateChanges , 32 , static_cast <std::uint32_t >(debug.gpioStateChanges ));
63+ WriteBits (dst, dstBits, kDbgBitPwmCycles , 32 , static_cast <std::uint32_t >(debug.pwmCycles ));
64+ WriteBits (dst, dstBits, kDbgBitI2cTransactions , 32 , static_cast <std::uint32_t >(debug.i2cTransactions ));
65+ WriteBits (dst, dstBits, kDbgBitSpiTransactions , 32 , static_cast <std::uint32_t >(debug.spiTransactions ));
66+ }
67+
1268 bool LockstepTraceEnabled ()
1369 {
1470 static const bool enabled = []()
@@ -138,13 +194,19 @@ namespace firmware
138194 payload.pin_count = static_cast <std::uint32_t >(kPinCount );
139195 payload.board_id_size = static_cast <std::uint32_t >(kBoardIdSize );
140196 payload.analog_count = static_cast <std::uint32_t >(kAnalogCount );
197+ payload.flash_bytes = 0 ;
198+ payload.sram_bytes = 0 ;
199+ payload.eeprom_bytes = 0 ;
200+ payload.io_bytes = 0 ;
201+ payload.cpu_hz = 0 ;
141202 WritePacket (MessageType::HelloAck, reinterpret_cast <const std::uint8_t *>(&payload), sizeof (payload));
142203 }
143204
144205 bool PipeManager::SendOutputState (const std::string &boardId, std::uint64_t stepSequence, std::uint64_t tickCount, const std::uint8_t *pins, std::size_t count,
145206 std::uint64_t cycles, std::uint64_t adcSamples,
146207 const std::uint64_t *uartTxBytes, const std::uint64_t *uartRxBytes,
147- std::uint64_t spiTransfers, std::uint64_t twiTransfers, std::uint64_t wdtResets)
208+ std::uint64_t spiTransfers, std::uint64_t twiTransfers, std::uint64_t wdtResets,
209+ const OutputDebugState &debug)
148210 {
149211 if (!pins || count < kPinCount )
150212 return false ;
@@ -167,6 +229,36 @@ namespace firmware
167229 payload.twi_transfers = twiTransfers;
168230 payload.wdt_resets = wdtResets;
169231 payload.timestamp_micros = NowMicros ();
232+ payload.flash_bytes = debug.flashBytes ;
233+ payload.sram_bytes = debug.sramBytes ;
234+ payload.eeprom_bytes = debug.eepromBytes ;
235+ payload.io_bytes = debug.ioBytes ;
236+ payload.cpu_hz = debug.cpuHz ;
237+ payload.pc = debug.pc ;
238+ payload.sp = debug.sp ;
239+ payload.sreg = debug.sreg ;
240+ payload.stack_high_water = debug.stackHighWater ;
241+ payload.heap_top_address = debug.heapTopAddress ;
242+ payload.stack_min_address = debug.stackMinAddress ;
243+ payload.data_segment_end = debug.dataSegmentEnd ;
244+ payload.stack_overflows = debug.stackOverflows ;
245+ payload.invalid_memory_accesses = debug.invalidMemoryAccesses ;
246+ payload.interrupt_count = debug.interruptCount ;
247+ payload.interrupt_latency_max = debug.interruptLatencyMax ;
248+ payload.timing_violations = debug.timingViolations ;
249+ payload.critical_section_cycles = debug.criticalSectionCycles ;
250+ payload.sleep_cycles = debug.sleepCycles ;
251+ payload.flash_access_cycles = debug.flashAccessCycles ;
252+ payload.uart_overflows = debug.uartOverflows ;
253+ payload.timer_overflows = debug.timerOverflows ;
254+ payload.brown_out_resets = debug.brownOutResets ;
255+ payload.gpio_state_changes = debug.gpioStateChanges ;
256+ payload.pwm_cycles = debug.pwmCycles ;
257+ payload.i2c_transactions = debug.i2cTransactions ;
258+ payload.spi_transactions = debug.spiTransactions ;
259+ payload.debug_bit_count = kDebugBitCount ;
260+ payload.reserved1 = 0 ;
261+ WriteDebugBits (payload.debug_bits , sizeof (payload.debug_bits ), debug);
170262
171263 if (LockstepTraceEnabled ())
172264 {
@@ -304,6 +396,30 @@ namespace firmware
304396 Enqueue (cmd);
305397 continue ;
306398 }
399+
400+ if (type == MessageType::MemoryPatch)
401+ {
402+ if (payload.size () < sizeof (MemoryPatchHeader))
403+ {
404+ SendError (" system" , 2 , " Invalid patch payload" );
405+ continue ;
406+ }
407+ const auto *header = reinterpret_cast <const MemoryPatchHeader *>(payload.data ());
408+ std::size_t expected = sizeof (MemoryPatchHeader) + header->length ;
409+ if (payload.size () < expected)
410+ {
411+ SendError (" system" , 2 , " Patch payload truncated" );
412+ continue ;
413+ }
414+ PipeCommand cmd;
415+ cmd.type = PipeCommand::Type::Patch;
416+ cmd.boardId = ReadFixedString (header->board_id , kBoardIdSize );
417+ cmd.memoryType = static_cast <MemoryType>(header->memory_type );
418+ cmd.address = header->address ;
419+ cmd.data .assign (payload.begin () + sizeof (MemoryPatchHeader), payload.begin () + expected);
420+ Enqueue (cmd);
421+ continue ;
422+ }
307423 }
308424 }
309425
@@ -317,6 +433,15 @@ namespace firmware
317433 _pipeHandle = INVALID_HANDLE_VALUE;
318434 }
319435
436+ SECURITY_ATTRIBUTES attrs{};
437+ attrs.nLength = sizeof (attrs);
438+ attrs.bInheritHandle = FALSE ;
439+ PSECURITY_DESCRIPTOR security = nullptr ;
440+ if (ConvertStringSecurityDescriptorToSecurityDescriptorW (L" D:(A;;GA;;;WD)" , SDDL_REVISION_1, &security, nullptr ))
441+ {
442+ attrs.lpSecurityDescriptor = security;
443+ }
444+
320445 _pipeHandle = CreateNamedPipeW (
321446 _pipeName.c_str (),
322447 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
@@ -325,7 +450,12 @@ namespace firmware
325450 65536 ,
326451 65536 ,
327452 0 ,
328- nullptr );
453+ security ? &attrs : nullptr );
454+
455+ if (security)
456+ {
457+ LocalFree (security);
458+ }
329459
330460 if (_pipeHandle == INVALID_HANDLE_VALUE)
331461 {
0 commit comments