19
19
#include < diagnostic-logs-provider-delegate-impl.h>
20
20
#include < lib/support/SafeInt.h>
21
21
22
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
23
+ #include < esp_core_dump.h>
24
+ #include < esp_flash_encrypt.h>
25
+ // Its a bit hackish but we need this in order to pull in the sizeof(core_dump_header_t)
26
+ // we can even use the static 20 but, what if that gets chagned?
27
+ #include " ../include_core_dump/esp_core_dump_types.h"
28
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
29
+
22
30
using namespace chip ;
23
31
using namespace chip ::app::Clusters::DiagnosticLogs;
24
32
25
33
LogProvider LogProvider::sInstance ;
34
+ LogProvider::CrashLogContext LogProvider::sCrashLogContext ;
26
35
27
36
namespace {
28
37
bool IsValidIntent (IntentEnum intent)
29
38
{
30
39
return intent != IntentEnum::kUnknownEnumValue ;
31
40
}
32
41
33
- // end_user_support.log, network_diag.log, and crash .log files are embedded in the firmware
42
+ // end_user_support.log and network_diag .log files are embedded in the firmware
34
43
extern const uint8_t endUserSupportLogStart[] asm (" _binary_end_user_support_log_start" );
35
44
extern const uint8_t endUserSupportLogEnd[] asm (" _binary_end_user_support_log_end" );
36
45
37
46
extern const uint8_t networkDiagnosticLogStart[] asm (" _binary_network_diag_log_start" );
38
47
extern const uint8_t networkDiagnosticLogEnd[] asm (" _binary_network_diag_log_end" );
39
-
40
- extern const uint8_t crashLogStart[] asm (" _binary_crash_log_start" );
41
- extern const uint8_t crashLogEnd[] asm (" _binary_crash_log_end" );
42
48
} // namespace
43
49
44
50
LogProvider::~LogProvider ()
45
51
{
46
- for (auto sessionSpan : mSessionSpanMap )
52
+ for (auto sessionSpan : mSessionContextMap )
47
53
{
48
54
Platform::MemoryFree (sessionSpan.second );
49
55
}
50
- mSessionSpanMap .clear ();
56
+ mSessionContextMap .clear ();
51
57
}
52
58
53
59
CHIP_ERROR LogProvider::GetLogForIntent (IntentEnum intent, MutableByteSpan & outBuffer, Optional<uint64_t > & outTimeStamp,
@@ -69,93 +75,233 @@ CHIP_ERROR LogProvider::GetLogForIntent(IntentEnum intent, MutableByteSpan & out
69
75
return CHIP_NO_ERROR;
70
76
}
71
77
72
- const uint8_t * LogProvider::GetDataStartForIntent (IntentEnum intent)
78
+ size_t LogProvider::GetSizeForIntent (IntentEnum intent)
73
79
{
74
80
switch (intent)
75
81
{
76
82
case IntentEnum::kEndUserSupport :
77
- return & endUserSupportLogStart[ 0 ] ;
83
+ return static_cast < size_t >(endUserSupportLogEnd - endUserSupportLogStart) ;
78
84
case IntentEnum::kNetworkDiag :
79
- return & networkDiagnosticLogStart[ 0 ] ;
85
+ return static_cast < size_t >(networkDiagnosticLogEnd - networkDiagnosticLogStart) ;
80
86
case IntentEnum::kCrashLogs :
81
- return &crashLogStart[ 0 ] ;
87
+ return GetCrashSize () ;
82
88
default :
83
- return nullptr ;
89
+ return 0 ;
84
90
}
85
91
}
86
92
87
- size_t LogProvider::GetSizeForIntent (IntentEnum intent )
93
+ size_t LogProvider::GetCrashSize ( )
88
94
{
95
+ size_t outSize = 0 ;
96
+
97
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
98
+ size_t unusedOutAddr;
99
+ esp_err_t esp_err = esp_core_dump_image_get (&unusedOutAddr, &outSize);
100
+ VerifyOrReturnValue (esp_err == ESP_OK, 0 , ChipLogError (DeviceLayer, " Failed to get core dump image, esp_err:%d" , esp_err));
101
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
102
+
103
+ return outSize;
104
+ }
105
+
106
+ CHIP_ERROR LogProvider::MapCrashPartition (CrashLogContext * context)
107
+ {
108
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
109
+ size_t outAddr, outSize;
110
+ esp_err_t esp_err = esp_core_dump_image_get (&outAddr, &outSize);
111
+ VerifyOrReturnError (esp_err == ESP_OK, CHIP_ERROR (ChipError::Range::kPlatform , esp_err),
112
+ ChipLogError (DeviceLayer, " Failed to get core dump image, esp_err:%d" , esp_err));
113
+
114
+ /* map the full core dump parition, including the checksum. */
115
+ esp_err = spi_flash_mmap (outAddr, outSize, SPI_FLASH_MMAP_DATA, &context->mappedAddress , &context->mappedHandle );
116
+ VerifyOrReturnError (esp_err == ESP_OK, CHIP_ERROR (ChipError::Range::kPlatform , esp_err),
117
+ ChipLogError (DeviceLayer, " Failed to mmap the crash partition, esp_err:%d" , esp_err));
118
+
119
+ context->crashSize = static_cast <uint32_t >(outSize);
120
+ return CHIP_NO_ERROR;
121
+ #else
122
+ return CHIP_ERROR_NOT_FOUND;
123
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
124
+ }
125
+
126
+ CHIP_ERROR LogProvider::PrepareLogContextForIntent (LogContext * context, IntentEnum intent)
127
+ {
128
+ context->intent = intent;
129
+
89
130
switch (intent)
90
131
{
132
+ case IntentEnum::kEndUserSupport : {
133
+ context->EndUserSupport .span =
134
+ ByteSpan (&endUserSupportLogStart[0 ], static_cast <size_t >(endUserSupportLogEnd - endUserSupportLogStart));
135
+ }
136
+ break ;
137
+
138
+ case IntentEnum::kNetworkDiag : {
139
+ context->NetworkDiag .span =
140
+ ByteSpan (&networkDiagnosticLogStart[0 ], static_cast <size_t >(networkDiagnosticLogEnd - networkDiagnosticLogStart));
141
+ }
142
+ break ;
143
+
144
+ case IntentEnum::kCrashLogs : {
145
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
146
+ sCrashLogContext .Reset ();
147
+ context->Crash .logContext = &sCrashLogContext ;
148
+
149
+ CHIP_ERROR err = MapCrashPartition (context->Crash .logContext );
150
+ VerifyOrReturnError (err == CHIP_NO_ERROR, err, context->Crash .logContext = nullptr );
151
+
152
+ context->Crash .logContext ->readOffset = sizeof (core_dump_header_t );
153
+ context->Crash .logContext ->isMapped = true ;
154
+ #else
155
+ return CHIP_ERROR_NOT_FOUND;
156
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
157
+ }
158
+ break ;
159
+
160
+ default :
161
+ return CHIP_ERROR_INVALID_ARGUMENT;
162
+ }
163
+
164
+ return CHIP_NO_ERROR;
165
+ }
166
+
167
+ void LogProvider::CleanupLogContextForIntent (LogContext * context)
168
+ {
169
+ switch (context->intent )
170
+ {
91
171
case IntentEnum::kEndUserSupport :
92
- return static_cast <size_t >(endUserSupportLogEnd - endUserSupportLogStart);
172
+ break ;
173
+
93
174
case IntentEnum::kNetworkDiag :
94
- return static_cast <size_t >(networkDiagnosticLogEnd - networkDiagnosticLogStart);
95
- case IntentEnum::kCrashLogs :
96
- return static_cast <size_t >(crashLogEnd - crashLogStart);
175
+ break ;
176
+
177
+ case IntentEnum::kCrashLogs : {
178
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
179
+ CrashLogContext * logContext = context->Crash .logContext ;
180
+ spi_flash_munmap (logContext->mappedHandle );
181
+ logContext->Reset ();
182
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
183
+ }
184
+ break ;
185
+
97
186
default :
98
- return 0 ;
187
+ break ;
99
188
}
100
189
}
101
190
191
+ CHIP_ERROR LogProvider::GetDataForIntent (LogContext * context, MutableByteSpan & outBuffer, bool & outIsEndOfLog)
192
+ {
193
+ switch (context->intent )
194
+ {
195
+ case IntentEnum::kEndUserSupport : {
196
+ auto dataSize = context->EndUserSupport .span .size ();
197
+ auto count = std::min (dataSize, outBuffer.size ());
198
+
199
+ VerifyOrReturnError (CanCastTo<off_t >(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size (0 ));
200
+ ReturnErrorOnFailure (CopySpanToMutableSpan (ByteSpan (context->EndUserSupport .span .data (), count), outBuffer));
201
+
202
+ outIsEndOfLog = dataSize == count;
203
+ if (!outIsEndOfLog)
204
+ {
205
+ // reduce the span after reading count bytes
206
+ context->EndUserSupport .span = context->EndUserSupport .span .SubSpan (count);
207
+ }
208
+ }
209
+ break ;
210
+
211
+ case IntentEnum::kNetworkDiag : {
212
+ auto dataSize = context->NetworkDiag .span .size ();
213
+ auto count = std::min (dataSize, outBuffer.size ());
214
+
215
+ VerifyOrReturnError (CanCastTo<off_t >(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size (0 ));
216
+ ReturnErrorOnFailure (CopySpanToMutableSpan (ByteSpan (context->NetworkDiag .span .data (), count), outBuffer));
217
+
218
+ outIsEndOfLog = dataSize == count;
219
+ if (!outIsEndOfLog)
220
+ {
221
+ // reduce the span after reading count bytes
222
+ context->NetworkDiag .span = context->NetworkDiag .span .SubSpan (count);
223
+ }
224
+ }
225
+ break ;
226
+
227
+ case IntentEnum::kCrashLogs : {
228
+ #if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
229
+ CrashLogContext * logContext = context->Crash .logContext ;
230
+ size_t dataSize = logContext->crashSize - logContext->readOffset ;
231
+ auto count = std::min (dataSize, outBuffer.size ());
232
+
233
+ VerifyOrReturnError (CanCastTo<off_t >(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size (0 ));
234
+
235
+ const uint8_t * readAddr = reinterpret_cast <const uint8_t *>(logContext->mappedAddress ) + logContext->readOffset ;
236
+ memcpy (outBuffer.data (), readAddr, count);
237
+ outBuffer.reduce_size (count);
238
+
239
+ logContext->readOffset += count;
240
+ outIsEndOfLog = dataSize == count;
241
+ #else
242
+ outBuffer.reduce_size (0 );
243
+ return CHIP_ERROR_NOT_FOUND;
244
+ #endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
245
+ }
246
+ break ;
247
+
248
+ default :
249
+ return CHIP_ERROR_INVALID_ARGUMENT;
250
+ }
251
+
252
+ return CHIP_NO_ERROR;
253
+ }
254
+
102
255
CHIP_ERROR LogProvider::StartLogCollection (IntentEnum intent, LogSessionHandle & outHandle, Optional<uint64_t > & outTimeStamp,
103
256
Optional<uint64_t > & outTimeSinceBoot)
104
257
{
105
258
VerifyOrReturnValue (IsValidIntent (intent), CHIP_ERROR_INVALID_ARGUMENT);
106
259
107
- const uint8_t * dataStart = GetDataStartForIntent (intent);
108
- VerifyOrReturnError (dataStart, CHIP_ERROR_NOT_FOUND);
109
-
110
- size_t dataSize = GetSizeForIntent (intent);
111
- VerifyOrReturnError (dataSize, CHIP_ERROR_NOT_FOUND);
260
+ // In case of crash logs we can only mmap at max once, so check before doing anything
261
+ if (intent == IntentEnum::kCrashLogs )
262
+ {
263
+ VerifyOrReturnError (sCrashLogContext .isMapped == false , CHIP_ERROR_INCORRECT_STATE,
264
+ ChipLogError (DeviceLayer, " Crash partition already mapped" ));
265
+ }
112
266
113
- ByteSpan * span = reinterpret_cast <ByteSpan *>(Platform::MemoryCalloc (1 , sizeof (ByteSpan )));
114
- VerifyOrReturnValue (span , CHIP_ERROR_NO_MEMORY);
267
+ LogContext * context = reinterpret_cast <LogContext *>(Platform::MemoryCalloc (1 , sizeof (LogContext )));
268
+ VerifyOrReturnValue (context != nullptr , CHIP_ERROR_NO_MEMORY);
115
269
116
- *span = ByteSpan (dataStart, dataSize);
270
+ CHIP_ERROR err = PrepareLogContextForIntent (context, intent);
271
+ VerifyOrReturnError (err == CHIP_NO_ERROR, err, Platform::MemoryFree (context));
117
272
118
273
mLogSessionHandle ++;
119
274
// If the session handle rolls over to UINT16_MAX which is invalid, reset to 0.
120
275
VerifyOrDo (mLogSessionHandle != kInvalidLogSessionHandle , mLogSessionHandle = 0 );
121
276
122
- outHandle = mLogSessionHandle ;
123
- mSessionSpanMap [mLogSessionHandle ] = span;
277
+ outHandle = mLogSessionHandle ;
278
+ mSessionContextMap [mLogSessionHandle ] = context;
279
+
124
280
return CHIP_NO_ERROR;
125
281
}
126
282
127
283
CHIP_ERROR LogProvider::EndLogCollection (LogSessionHandle sessionHandle)
128
284
{
129
285
VerifyOrReturnValue (sessionHandle != kInvalidLogSessionHandle , CHIP_ERROR_INVALID_ARGUMENT);
130
- VerifyOrReturnValue (mSessionSpanMap .count (sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);
286
+ VerifyOrReturnValue (mSessionContextMap .count (sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);
131
287
132
- ByteSpan * span = mSessionSpanMap [sessionHandle];
133
- mSessionSpanMap .erase (sessionHandle);
288
+ LogContext * context = mSessionContextMap [sessionHandle];
289
+ VerifyOrReturnError (context, CHIP_ERROR_INCORRECT_STATE);
290
+
291
+ CleanupLogContextForIntent (context);
292
+ Platform::MemoryFree (context);
293
+ mSessionContextMap .erase (sessionHandle);
134
294
135
- Platform::MemoryFree (span);
136
295
return CHIP_NO_ERROR;
137
296
}
138
297
139
298
CHIP_ERROR LogProvider::CollectLog (LogSessionHandle sessionHandle, MutableByteSpan & outBuffer, bool & outIsEndOfLog)
140
299
{
141
300
VerifyOrReturnValue (sessionHandle != kInvalidLogSessionHandle , CHIP_ERROR_INVALID_ARGUMENT);
142
- VerifyOrReturnValue (mSessionSpanMap .count (sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);
143
-
144
- ByteSpan * span = mSessionSpanMap [sessionHandle];
145
- auto dataSize = span->size ();
146
- auto count = std::min (dataSize, outBuffer.size ());
147
-
148
- VerifyOrReturnError (CanCastTo<off_t >(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size (0 ));
149
-
150
- ReturnErrorOnFailure (CopySpanToMutableSpan (ByteSpan (span->data (), count), outBuffer));
301
+ VerifyOrReturnValue (mSessionContextMap .count (sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);
151
302
152
- outIsEndOfLog = dataSize == count;
303
+ LogContext * context = mSessionContextMap [sessionHandle];
304
+ VerifyOrReturnError (context, CHIP_ERROR_INCORRECT_STATE);
153
305
154
- if (!outIsEndOfLog)
155
- {
156
- // reduce the span after reading count bytes
157
- *span = span->SubSpan (count);
158
- }
159
-
160
- return CHIP_NO_ERROR;
306
+ return GetDataForIntent (context, outBuffer, outIsEndOfLog);
161
307
}
0 commit comments