Object.h
Go to the documentation of this file.
1 
73 #pragma once
74 
75 #include "../TimeStamp.h"
76 #include "../FileAttributes.h"
77 #include "../Compression.h"
78 #include "../UserRole.h"
79 
80 namespace IFS
81 {
82 namespace FWFS
83 {
84 /*
85  * Helper template function to get the next object pointer at (current + offset)
86  * casting as required for the given return type.
87  */
88 template <typename T> static T at_offset(const void* current, int offset)
89 {
90  auto p = reinterpret_cast<const uint8_t*>(current) + offset;
91  return reinterpret_cast<T>(p);
92 }
93 
94 template <typename T> static T at_offset(void* current, int offset)
95 {
96  auto p = reinterpret_cast<uint8_t*>(current) + offset;
97  return reinterpret_cast<T>(p);
98 }
99 
100 // First object located immediately after start marker in image
101 constexpr size_t FWFS_BASE_OFFSET{sizeof(uint32_t)};
102 
103 // Images start with a single word to identify this as a Firmware Filesystem image
104 constexpr uint32_t FWFILESYS_START_MARKER{0x53465746}; // "FWFS"
105 
106 // Image end marker (reverse of magic)
107 constexpr uint32_t FWFILESYS_END_MARKER{0x46574653}; // "SFWF"
108 
109 // Everything in this header must be portable (at least, with other little-endian systems) so byte-align and pack it
110 #pragma pack(1)
111 
119 #define FWFS_OBJTYPE_MAP(XX) \
120  XX(0, End, "The system image footer") \
121  XX(1, Data8, "Data, max 255 bytes") \
122  XX(2, ID32, "32-bit identifier") \
123  XX(3, ObjAttr, "Object attributes") \
124  XX(4, Compression, "Compression descriptor") \
125  XX(5, ReadACE, "minimum UserRole for read access") \
126  XX(6, WriteACE, "minimum UserRole for write access") \
127  XX(7, VolumeIndex, "Volume index number") \
128  XX(8, Md5Hash, "MD5 Hash Value") \
129  XX(9, Comment, "Comment") \
130  XX(10, UserAttribute, "User Attribute") \
131  XX(32, Data16, "Data, max 64K - 1") \
132  XX(33, Volume, "Volume, top-level container object") \
133  XX(34, MountPoint, "Root for another filesystem") \
134  XX(35, Directory, "Directory entry") \
135  XX(36, File, "File entry") \
136  XX(64, Data24, "Data, max 16M - 1")
137 
144 struct Object {
145  uint8_t typeData;
146 
150  using ID = uint32_t;
151 
152  enum class Type {
153 #define XX(value, tag, text) tag = value,
155 #undef XX
156  };
157 
158  // Top bit of object type set to indicate a reference
159  static constexpr uint8_t FWOBT_REF{0x80};
160 
165  enum class Attribute {
169  ReadOnly,
173  Archive,
180  Encrypted,
181  //
182  MAX
183  };
184 
186 
187  Type type() const
188  {
189  return static_cast<Type>(typeData & 0x7f);
190  }
191 
192  void setType(Type type, bool isRef = false)
193  {
194  typeData = unsigned(type);
195  if(isRef) {
196  typeData |= FWOBT_REF;
197  }
198  }
199 
200  bool isRef() const
201  {
202  return (typeData & FWOBT_REF) != 0;
203  }
204 
205  uint32_t getRef() const
206  {
207  if(!isRef()) {
208  return 0;
209  }
210  uint32_t id{0};
211  memcpy(&id, &data8.ref.packedOffset, data8.contentSize());
212  return id;
213  }
214 
215  bool isNamed() const
216  {
217  return type() >= Type::Volume && type() < Type::Data24;
218  }
219 
220  bool isData() const
221  {
222  return type() == Type::Data8 || type() == Type::Data16 || type() == Type::Data24;
223  }
224 
225  bool isDir() const
226  {
227  return type() == Type::Directory;
228  }
229 
230  bool isMountPoint() const
231  {
232  return type() == Type::MountPoint;
233  }
234 
235  union {
236  // Data8 - 8-bit size, max. 255 bytes
237  struct {
238  uint8_t _contentSize;
239  // uint8_t data[];
240 
241  unsigned contentOffset() const
242  {
243  return offsetof(Object, data8) + 1;
244  }
245 
246  unsigned contentSize() const
247  {
248  return _contentSize;
249  }
250 
251  void setContentSize(uint32_t value)
252  {
253  _contentSize = value;
254  }
255 
256  union {
257  // An object reference: the contents are stored externally (on the same volume)
258  struct {
259  uint32_t packedOffset; // 1-4 byte offset
260  } ref;
261 
262  // ID32
263  struct {
264  uint32_t value;
265  } id32;
266 
267  // Object attributes
268  struct {
269  uint8_t attr; // Attributes
271 
272  // Compression descriptor
273  Compression compression;
274 
275  // ReadACE, WriteACE
276  struct {
278  } ace;
279 
280  // Identifies a volume index, contained in a mount point
281  struct {
282  uint8_t index;
283  } volumeIndex;
284 
285  // User attribute
286  struct {
287  uint8_t tagValue;
288  // uint8_t[] data;
289  } userAttribute;
290 
291  // END - immediately followed by end marker
292  struct {
293  uint32_t checksum;
294  } end;
295  };
296  } data8;
297 
298  // Data16 - 16-bit size, max. (64KB - 1)
299  struct {
301  // uint8_t data[];
302 
303  unsigned contentOffset() const
304  {
305  return offsetof(Object, data16) + 2;
306  }
307 
308  uint32_t contentSize() const
309  {
310  return _contentSize;
311  }
312 
313  void setContentSize(uint32_t value)
314  {
315  _contentSize = value;
316  }
317 
318  uint32_t size() const
319  {
320  return contentOffset() + contentSize();
321  }
322 
323  union {
324  /*
325  * named object
326  *
327  * child objects can be contained or referenced (flag in _id)
328  * object attributes are optional so can be another object/attribute
329  */
330  struct {
331  uint8_t namelen;
332  TimeStamp mtime; // Object modification time
333  // char name[namelen];
334  // Object children[];
335 
336  // Offset to object name relative to content start
337  unsigned nameOffset() const
338  {
339  return sizeof(Object::data16.named);
340  }
341 
342  // Offset to start of child object table
343  unsigned childTableOffset() const
344  {
345  return nameOffset() + namelen;
346  }
347 
348  } named;
349  };
350  } data16;
351 
352  // Data24 - 24-bit size, max. (16MB - 1)
353  struct {
356  // uint8_t data[];
357 
358  size_t contentOffset() const
359  {
360  return offsetof(Object, data24) + 3;
361  }
362 
363  uint32_t contentSize() const
364  {
365  return (_contentSizeHigh << 16) | _contentSize;
366  }
367 
368  void setContentSize(uint32_t value)
369  {
370  _contentSize = value & 0xffff;
371  _contentSizeHigh = value >> 16;
372  }
373 
374  uint32_t size() const
375  {
376  return contentOffset() + contentSize();
377  }
378  } data24;
379  };
380 
383  size_t contentOffset() const
384  {
385  if(isRef() || (type() < Type::Data16)) {
386  return data8.contentOffset();
387  } else if(type() < Type::Data24) {
388  return data16.contentOffset();
389  } else {
390  return data24.contentOffset();
391  }
392  }
393 
398  uint32_t contentSize() const
399  {
400  if(isRef() || (type() < Type::Data16)) {
401  return data8.contentSize();
402  } else if(type() < Type::Data24) {
403  return data16.contentSize();
404  } else {
405  return data24.contentSize();
406  }
407  }
408 
409  void setContentSize(size_t size)
410  {
411  if(isRef() || type() < Type::Data16) {
412  data8.setContentSize(size);
413  } else if(type() < Type::Data24) {
414  data16.setContentSize(size);
415  } else {
416  data24.setContentSize(size);
417  }
418  }
419 
420  uint32_t childTableOffset() const
421  {
422  assert(isNamed());
423  return data16.contentOffset() + data16.named.childTableOffset();
424  }
425 
426  uint32_t childTableSize() const
427  {
428  assert(isNamed());
429  int size = data16.contentSize() - data16.named.childTableOffset();
430  return (size <= 0) ? 0 : size;
431  }
432 
436  uint32_t size() const
437  {
438  return contentOffset() + contentSize();
439  }
440 };
441 
442 static_assert(sizeof(Object) == 8, "Object alignment wrong!");
443 
444 #pragma pack()
445 
449 struct FWObjDesc {
451  Object obj{};
452 
453  FWObjDesc(Object::ID objId = 0) : id(objId)
454  {
455  }
456 
457  uint32_t offset() const
458  {
459  return id;
460  }
461 
462  uint32_t nextOffset() const
463  {
464  return offset() + obj.size();
465  }
466 
467  // Move to next object location
468  void next()
469  {
470  id = nextOffset();
471  }
472 
473  uint32_t contentOffset() const
474  {
475  return offset() + obj.contentOffset();
476  }
477 
478  uint32_t childTableOffset() const
479  {
480  return offset() + obj.childTableOffset();
481  }
482 };
483 
486 
487 } // namespace FWFS
488 } // namespace IFS
489 
struct IFS::FWFS::Object::@25::@27::@30::@33 id32
#define MAX(a, b)
Definition: spiffs_nucleus.h:541
uint32_t packedOffset
Definition: Object.h:259
uint32_t value
32-bit identifier, e.g. volume ID
Definition: Object.h:264
uint8_t attr
Definition: Object.h:269
#define FWFS_OBJTYPE_MAP(XX)
Object type identifiers.
Definition: Object.h:119
struct IFS::FWFS::Object::@25::@27::@30::@34 objectAttributes
Compression compression
Definition: Object.h:273
size_t contentOffset() const
return offset to start of object content
Definition: Object.h:383
struct IFS::FWFS::Object::@25::@27::@30::@38 end
FWFS Object Descriptor.
Definition: Object.h:449
UserRole role
Definition: Object.h:277
XX(value, tag, text)
Attribute
Object attributes.
Definition: Object.h:165
void next()
Definition: Object.h:468
FWObjDesc(Object::ID objId=0)
Definition: Object.h:453
Object::ID id
location
Definition: Object.h:450
uint8_t namelen
Length of object name.
Definition: Object.h:331
bool isMountPoint() const
Definition: Object.h:230
The String class.
Definition: WString.h:136
bool isNamed() const
Definition: Object.h:215
uint8_t typeData
Stored type plus flag.
Definition: Object.h:145
uint32_t ID
Object identifier (offset from start of image)
Definition: Object.h:150
constexpr uint32_t FWFILESYS_START_MARKER
Definition: Object.h:104
bool isRef() const
Definition: Object.h:200
uint32_t checksum
Definition: Object.h:293
uint32_t offset() const
Definition: Object.h:457
Type
Definition: Object.h:152
uint32_t getRef() const
Definition: Object.h:205
struct IFS::FWFS::Object::@25::@28 data16
Definition: DirectoryTemplate.h:36
Manage IFS timestamps stored as an unsigned 32-bit value.
Definition: TimeStamp.h:35
uint8_t index
Definition: Object.h:282
struct IFS::FWFS::Object::@25::@27::@30::@36 volumeIndex
bool isData() const
Definition: Object.h:220
constexpr size_t FWFS_BASE_OFFSET
Definition: Object.h:101
struct IFS::FWFS::Object::@25::@27::@30::@37 userAttribute
static T at_offset(const void *current, int offset)
Definition: Object.h:88
TimeStamp mtime
Definition: Object.h:332
uint8_t _contentSize
Definition: Object.h:238
struct IFS::FWFS::Object::@25::@27 data8
UserRole
Definition: UserRole.h:36
Type type() const
Definition: Object.h:187
bool isDir() const
Definition: Object.h:225
Object::Attributes getObjectAttributes(FileAttributes fileAttr)
uint32_t nextOffset() const
Definition: Object.h:462
uint32_t contentOffset() const
Definition: Object.h:473
uint32_t childTableOffset() const
Definition: Object.h:478
struct IFS::FWFS::Object::@25::@27::@30::@32 ref
uint32_t size() const
total size this object occupies in the image
Definition: Object.h:436
FileAttributes getFileAttributes(Object::Attributes objattr)
struct IFS::FWFS::Object::@25::@28::@39::@41 named
uint8_t _contentSizeHigh
Allows data up to 16MByte.
Definition: Object.h:355
void setType(Type type, bool isRef=false)
Definition: Object.h:192
struct IFS::FWFS::Object::@25::@29 data24
static constexpr uint8_t FWOBT_REF
Definition: Object.h:159
Object structure.
Definition: Object.h:144
uint32_t childTableOffset() const
Definition: Object.h:420
String toString(IFS::FWFS::Object::Type obt)
Get descriptive String for an object type.
constexpr uint32_t FWFILESYS_END_MARKER
Definition: Object.h:107
uint16_t _contentSize
Object size (excluding this header)
Definition: Object.h:300
uint8_t tagValue
Definition: Object.h:287
struct IFS::FWFS::Object::@25::@27::@30::@35 ace
uint32_t childTableSize() const
Definition: Object.h:426
void setContentSize(size_t size)
Definition: Object.h:409
uint32_t contentSize() const
return size of object content, excluding header and size fields
Definition: Object.h:398