Dawn Framework 1.0
Universal data acquisition framework for embedded systems
descriptor.cxx
1// dawn/src/common/descriptor.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/common/descriptor.hxx"
7
8#include <cstring>
9
10#include "dawn/debug.hxx"
11#include "dawn/porting/crc.hxx"
12
13using namespace dawn;
14
15#if defined(CONFIG_DAWN_DESC_SLOTS) && CONFIG_DAWN_DESC_SLOTS > 1
16# define DAWN_DESC_CRC_REQUIRED 1
17#elif defined(CONFIG_DAWN_DESC_VALID_CRC32)
18# define DAWN_DESC_CRC_REQUIRED 1
19#else
20# define DAWN_DESC_CRC_REQUIRED 0
21#endif
22
23static int binValidateDtypes(const uint32_t *bin, size_t len)
24{
25 size_t i;
26 size_t words;
27 size_t count;
28
29 if (bin == nullptr || len < 8 || len % sizeof(uint32_t))
30 {
31 return -EINVAL;
32 }
33
34 words = len / sizeof(uint32_t);
35 i = 2;
36 count = bin[1] & 0xffff;
37
38 for (size_t obj = 0; obj < count; obj++)
39 {
41 size_t objsize;
42 uint8_t dtype;
43
44 if ((i + 2) > words)
45 {
46 DAWNERR("(i + 2) > words\n");
47 return -EINVAL;
48 }
49
50 objid = bin[i++];
51 dtype = SObjectId::objectIdGetDtype(objid);
53 {
54 DAWNERR("unsupported object dtype %u (%s)\n", dtype, SObjectId::dtypeToString(dtype));
55 return -ENOTSUP;
56 }
57
58 objsize = bin[i++];
59
60 for (size_t cfg = 0; cfg < objsize; cfg++)
61 {
63 size_t cfgsize;
64
65 if (i >= words)
66 {
67 DAWNERR("i >= words\n");
68 return -EINVAL;
69 }
70
71 cfgid = bin[i++];
72 dtype = SObjectCfg::objectCfgGetDtype(cfgid);
74 {
75 DAWNERR("unsupported config dtype %u (%s)\n", dtype, SObjectId::dtypeToString(dtype));
76 return -ENOTSUP;
77 }
78
79 cfgsize = SObjectCfg::objectCfgGetSize(cfgid);
80 if ((i + cfgsize) > words)
81 {
82 DAWNERR("(i + cfgsize) > words\n");
83 return -EINVAL;
84 }
85
86 i += cfgsize;
87 }
88 }
89
90 if (i != words)
91 {
92 DAWNERR("i != words\n");
93 return -EINVAL;
94 }
95
96 return OK;
97}
98
99void CDescriptor::binDump(const uint32_t *bin, size_t len)
100{
102 SObjectId::ObjectId tmp = 0;
103 size_t i = 0;
104
105 // Ignore warnings
106 UNUSED(tmp);
107
108 DAWNINFO("\n");
109 DAWNINFO("\n");
110 DAWNINFO("BINDUMP ptr:%p len:%zu:\n\n", bin, len);
111 tmp = bin[i++];
112 UNUSED(tmp);
113 DAWNINFO("\tMAGIC: 0x%" PRIx32 "\n", tmp);
114 tmp = bin[i++];
115 UNUSED(tmp);
116 DAWNINFO("\tObjects: 0x%" PRIx32 "\n", tmp);
117
118 // Ignore check sum for now
119
120 len -= (2 * sizeof(SObjectId::ObjectId));
121
122 while (i < len / 4)
123 {
124 size_t objsize;
125
126 DAWNINFO("\n");
127 tmp = bin[i++];
128 UNUSED(tmp);
129 DAWNINFO("\tObjectID: 0x%" PRIx32 "\n", tmp);
130 objsize = bin[i++];
131 DAWNINFO("\t size: 0x%zx\n", objsize);
132
133 // Print config items
134
135 for (size_t j = 0; j < objsize; j++)
136 {
137 objcfg.v = bin[i++];
138 DAWNINFO("\t objcfg: 0x%" PRIx32 "\n", objcfg.v);
139
140 for (size_t k = 0; k < objcfg.s.size; k++)
141 {
142 tmp = bin[i++];
143 UNUSED(tmp);
144 DAWNINFO("\t data: 0x%" PRIx32 "\n", tmp);
145 }
146 }
147 }
148
149 tmp = bin[i++];
150 UNUSED(tmp);
151 DAWNINFO("\tLAST: 0x%" PRIx32 "\n", tmp);
152 tmp = bin[i++];
153 UNUSED(tmp);
154 DAWNINFO("\tCHECK: 0x%" PRIx32 "\n", tmp);
155
156 DAWNINFO("\n");
157 DAWNINFO("\n");
158}
159
160int CDescriptor::binValid(const uint32_t *bin, size_t len)
161{
162 size_t i = 0;
163 int dret;
164
165 // No magic
166
167 if (bin[i++] != DAWN_DESCRIPTOR_HDR)
168 {
169 return -EINVAL;
170 }
171
172 // No objects - no valid config
173
174 if (bin[i++] == 0)
175 {
176 return -EINVAL;
177 }
178
179#if DAWN_DESC_CRC_REQUIRED
180 // Validate check sum
181 if (CDescriptor::binCheckValid(bin, len) == false)
182 {
183 return -EINVAL;
184 }
185#endif
186
187 // If sum is valid - remove 8 bytes from lenght
188
189 len -= 2 * sizeof(SObjectId::ObjectId);
190
191 dret = binValidateDtypes(bin, len);
192 if (dret != OK)
193 {
194 return dret;
195 }
196
197 // Validate descriptor
198
199 return CObject::validateDesc(&bin[i], len - i * sizeof(SObjectId::ObjectId));
200}
201
202bool CDescriptor::binCheckValid(const uint32_t *bin, size_t len)
203{
204 SObjectId::ObjectId sum = crc32(reinterpret_cast<const uint8_t *>(bin), len);
205
206 return (sum == 0);
207}
208
209int CDescriptor::binCheckFill(uint32_t *bin, size_t len)
210{
211 // Check LAST marker
212
213 if (bin[(len / 4) - 2] != CDescriptor::DAWN_DESCRIPTOR_FOOT)
214 {
215 return -EINVAL;
216 }
217
218 bin[(len / 4) - 1] = crc32(reinterpret_cast<const uint8_t *>(bin), len - 4);
219
220 return 0;
221}
222
227
228void CDescriptor::parseMeta()
229{
230 size_t words = objectWords();
231 uint32_t word;
232
233 if (!bindesc || bindesc->hdr.size == 0)
234 {
235 return;
236 }
237
238 if (words < 2)
239 {
240 return;
241 }
242
243 if (!objectWordAt(0, &word) || SObjectId::objectIdGetType(word) != SObjectId::OBJTYPE_ANY)
244 {
245 return;
246 }
247
248 if (!objectWordAt(1, &word))
249 {
250 return;
251 }
252
253 size_t numItems = word;
254 size_t off = 2; // Start after objectId + numItems
255
256 for (size_t i = 0; i < numItems; i++)
257 {
258 uint32_t cfgid;
259
260 if (off >= words)
261 {
262 return;
263 }
264
265 if (!objectWordAt(off, &cfgid))
266 {
267 return;
268 }
269
270 uint32_t size = (cfgid >> 5) & 0x3FF;
271 uint32_t id = cfgid & 0x1F;
272
273 ++off; // Point to first data word
274 if (off + size > words)
275 {
276 return;
277 }
278
279 switch (id)
280 {
281 case DESC_CFG_NO_IDLE_QUIT:
282 if (size > 0)
283 {
284 if (!objectWordAt(off, &word))
285 {
286 return;
287 }
288 noIdleQuit = (word != 0);
289 }
290 break;
291
292 case DESC_CFG_VERSION:
293 case DESC_CFG_STRING:
294 default:
295 // not yet implemented.
296 break;
297 }
298
299 off += size;
300 }
301}
302
304{
305 for (CDescObject *obj : vobjcfg)
306 {
307 DAWNINFO("delete desc for 0x%" PRIx32 "\n", obj->getObjectIdV());
308 delete obj;
309 }
310
311 vobjcfg.clear();
312 bindesc = nullptr;
313 bindescLen = 0;
314 noIdleQuit = false;
315}
316
317int CDescriptor::loadBin(uint32_t *bin, size_t len, bool force_valid, bool dump)
318{
319 reset();
320
321 // Dump config
322
323 if (dump)
324 {
325 binDump(bin, len);
326 }
327
328 if (force_valid)
329 {
330 // Make sure that footer is reserved
331
332 if (bin[(len / 4) - 2] != CDescriptor::DAWN_DESCRIPTOR_FOOT)
333 {
334 return -EINVAL;
335 }
336
337 // Fill with checksum
338
339 binCheckFill(bin, len);
340 }
341
342 // Validate input data
343
344 if (binValid(bin, len) != OK)
345 {
346 return -EINVAL;
347 }
348
349 bindesc = reinterpret_cast<SDescriptorBin *>(bin);
350 bindescLen = len;
351
352 // Parse metadata config items.
353
354 parseMeta();
355
356 return OK;
357}
358
360{
361 return bindesc;
362}
363
365{
366 return bindescLen;
367}
368
369size_t CDescriptor::objectWords() const
370{
371 if (bindesc == nullptr || bindescLen < sizeof(SDescriptorBinHdr) + sizeof(SDescriptorBinFtr))
372 {
373 return 0;
374 }
375
376 return (bindescLen - sizeof(SDescriptorBinHdr) - sizeof(SDescriptorBinFtr)) / sizeof(uint32_t);
377}
378
379bool CDescriptor::objectWordAt(size_t offset, uint32_t *value) const
380{
381 if (value == nullptr || bindesc == nullptr || offset >= objectWords())
382 {
383 return false;
384 }
385
386 const uint8_t *objects = reinterpret_cast<const uint8_t *>(bindesc) + sizeof(SDescriptorBinHdr);
387 std::memcpy(value, objects + offset * sizeof(uint32_t), sizeof(*value));
388 return true;
389}
390
392{
393 if (bindesc == nullptr || offset + 2 > objectWords())
394 {
395 return nullptr;
396 }
397
398 return reinterpret_cast<SObjectCfg::SObjectCfgData *>(
399 reinterpret_cast<uint32_t *>(&bindesc->objects) + offset);
400};
401
403{
404 if (bindesc == nullptr || offset >= objectWords())
405 {
406 return nullptr;
407 }
408
409 return reinterpret_cast<SObjectCfg::UObjectCfgId *>(
410 reinterpret_cast<uint32_t *>(&bindesc->objects) + offset);
411};
412
413void CDescriptor::alloc_objects(CHandler &h, const allocobj_func_t &func)
414{
415 CDescriptor::SDescriptorBin *cfg = bindesc;
416 size_t offset = 0;
417
418 DAWNASSERT(cfg != nullptr, "invalid input");
419
420 // Start from object 0
421
422 for (size_t i = 0; i < cfg->hdr.size; i++)
423 {
425
426 // Get object configuration
427
428 ocfg = objectCfgAtOffset(offset);
429 if (ocfg == nullptr)
430 {
431 return;
432 }
433
434 // Check if object is for this handler
435
436 if (h.isObjectValid(ocfg->objid))
437 {
438 // Check for duplicates
439
440 for (const CDescObject *x : vobjcfg)
441 {
442 SObjectId::ObjectId tmp1 = x->getObjectIdV();
443 SObjectId::ObjectId tmp2 = ocfg->objid.v;
444
445 if (tmp1 == tmp2)
446 {
447 DAWNERR("duplicate 0x%" PRIx32 " 0x%" PRIx32 " \n", tmp1, tmp2);
448 }
449 }
450
451 // New configuration object
452
453 CDescObject *desc = new CDescObject(*ocfg);
454 vobjcfg.push_back(desc);
455
456 // Call implementation
457
458 func(h, *desc);
459 }
460
461 // Objid + size
462
463 offset += (sizeof(SObjectId::UObjectId) + 4) / 4;
464
465 // Go to next object
466
467 for (size_t j = 0; j < ocfg->size; j++)
468 {
469 uint32_t objcfg;
470 if (!objectWordAt(offset, &objcfg))
471 {
472 return;
473 }
474
475 // ObjectCfgId + cfg items
476
477 offset += 1 + SObjectCfg::objectCfgGetSize(objcfg);
478 }
479 }
480}
Descriptor wrapper for individual object configuration.
void reset()
Clear currently loaded descriptor state.
static uint32_t DAWN_DESCRIPTOR_FOOT
Footer magic number (0x02030a0d).
~CDescriptor()
Destructor - release loaded descriptor resources.
SObjectCfg::UObjectCfgId * objectCfgIdAtOffset(size_t offset)
Get configuration ID at offset.
static uint32_t DAWN_DESCRIPTOR_HDR
Header magic number (0x0d0a0302).
SObjectCfg::SObjectCfgData * objectCfgAtOffset(size_t offset)
Get object configuration at offset.
static void binDump(const uint32_t *bin, size_t len)
Print descriptor contents to console (debug).
static int binCheckFill(uint32_t *bin, size_t len)
Calculate and store descriptor CRC32 checksum.
int loadBin(uint32_t *bin, size_t len, bool force_valid=false, bool dump=false)
Load binary descriptor from memory.
size_t getBinLen()
Get loaded descriptor size in bytes.
static int binValid(const uint32_t *bin, size_t len)
Validate binary descriptor integrity.
static bool binCheckValid(const uint32_t *bin, size_t len)
Validate descriptor CRC32 checksum.
SDescriptorBin * getBin()
Get loaded descriptor binary structure.
Base implementation of IHandler interface.
Definition handler.hxx:110
static int validateDesc(const uint32_t *desc, size_t len)
Validate entire descriptor.
Definition object.cxx:123
virtual bool isObjectValid(SObjectId::UObjectId &obj) const =0
Validate if object ID is valid for this handler.
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
Definition objectcfg.hxx:60
static uint16_t objectCfgGetSize(const ObjectCfgId objcfg)
Extract configuration data size from ConfigID.
static uint8_t objectCfgGetDtype(const ObjectCfgId objcfg)
Extract data type from ConfigID.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Complete binary descriptor container.
Object configuration data container.
SObjectId::UObjectId objid
Object identifier (type, class, dtype, instance).
uint32_t size
Number of configuration items for this object (0-32).
@ OBJTYPE_ANY
Wildcard/metadata object type.
Definition objectid.hxx:176
static const char * dtypeToString(uint8_t dtype)
Convert data type to human-readable string.
Definition objectid.cxx:167
static uint8_t objectIdGetType(const ObjectId objid)
Extract object type from ObjectID.
Definition objectid.hxx:361
static uint8_t objectIdGetDtype(const ObjectId objid)
Extract data type field from ObjectID.
Definition objectid.hxx:337
static bool isDtypeSupported(uint8_t dtype)
Check if a data type is enabled in build configuration.
Definition objectid.cxx:95
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
32-bit encoded configuration identifier (union with bit field).
Definition objectcfg.hxx:79
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.
32-bit encoded object identifier (union with bit field).
Definition objectid.hxx:218
ObjectId v
Raw 32-bit ObjectID value (for comparison, hashing, storage).
Definition objectid.hxx:221