comparison mpffs/Description @ 41:86a494a5f2b0

MPFFS description: documented relocated chunks and the journal file
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 05 Jul 2013 03:26:06 +0000
parents c9f7a4afccc9
children
comparison
equal deleted inserted replaced
40:7ceab8bfacb3 41:86a494a5f2b0
4 "proper" name for this FFS, and needing _some_ identifier to refer to it, I 4 "proper" name for this FFS, and needing _some_ identifier to refer to it, I
5 have named it Mokopir-FFS, from "Moko" and "Pirelli" - sometimes abbreviated 5 have named it Mokopir-FFS, from "Moko" and "Pirelli" - sometimes abbreviated
6 further to MPFFS. 6 further to MPFFS.
7 7
8 (I have previously called the FFS in question MysteryFFS; but now that I've 8 (I have previously called the FFS in question MysteryFFS; but now that I've
9 successfully reverse-engineered it, it isn't such a mystery any more :-) 9 successfully reverse-engineered it, it isn't as much of a mystery any more :-)
10 10
11 At a high functional level, Mokopir-FFS presents the following features: 11 At a high functional level, Mokopir-FFS presents the following features:
12 12
13 * Has a directory tree structure like UNIX file systems; 13 * Has a directory tree structure like UNIX file systems;
14 14
306 The descendant pointer of each file head object (the object of type F1, the one 306 The descendant pointer of each file head object (the object of type F1, the one
307 reached by traversing the directory tree) indicates whether or not there are 307 reached by traversing the directory tree) indicates whether or not there are
308 any continuation chunks present. If this descendant pointer is nil, there are 308 any continuation chunks present. If this descendant pointer is nil, there are
309 no continuation chunks; otherwise it points to the first continuation chunk 309 no continuation chunks; otherwise it points to the first continuation chunk
310 object. File continuation objects have type F4, don't have any siblings (the 310 object. File continuation objects have type F4, don't have any siblings (the
311 sibling pointer is nil), and the descendant pointer of each continuation object 311 sibling pointer is nil - but see below regarding relocated chunks), and the
312 points to the next continuation object, if there is one - nil otherwise. 312 descendant pointer of each continuation object points to the next continuation
313 object, if there is one - nil otherwise.
313 314
314 Payload data delineation 315 Payload data delineation
315 316
316 Each chunk, whether head or continuation, always has a length that is a nonzero 317 Each chunk, whether head or continuation, always has a length that is a nonzero
317 multiple of 16 bytes. The length of the chunk here means the amount of flash 318 multiple of 16 bytes. The length of the chunk here means the amount of flash
339 the effective data length (end_pointer - start_pointer) will be 0 or -1. (The 340 the effective data length (end_pointer - start_pointer) will be 0 or -1. (The
340 latter possibility is the most likely, as there will normally be a "shared" 00 341 latter possibility is the most likely, as there will normally be a "shared" 00
341 byte, serving as both the filename terminator and the 00 before the padding 342 byte, serving as both the filename terminator and the 00 before the padding
342 FF bytes.) 343 FF bytes.)
343 344
345 Relocated chunks
346
347 Let's go back to the scenario in which a particular data sector is full (no more
348 usable free space left) and contains a mixture of active and dirty (deleted or
349 invalidated) data. How does the dirty flash space get reclaimed, so that the
350 amount of available space (blank flash ready to hold new data) becomes equal to
351 the total FFS size minus the total size of active files and overhead? It can
352 only be done by relocating the still-active objects from the full sector to a
353 new one, invalidating the old copies, and once the old sector consists of
354 nothing but invalidated data, subjecting it to flash erasure.
355
356 So how do the active FFS objects get relocated from a "condemned" sector to a
357 new one? If the object is a directory, a new index entry is created, pointing
358 to the newly relocated name chunk, but it is then made to fit into the old tree
359 structure without disrupting the latter: the new index entry is added at the
360 tail of the sibling-chain of the parent directory's descendants, the old index
361 entry for the same directory is invalidated (as if the directory were rmdir'ed),
362 and the descendant pointer of the newly written index entry is set to a copy of
363 the descendant pointer from the old index entry for the same directory. The
364 same approach is used when the head chunk of a file needs to be relocated; in
365 both cases a read-only FFS implementation doesn't need to do anything special to
366 support reading file and directory objects that have been relocated in this
367 manner.
368
369 However, if the relocated object is a file continuation chunk, then the manner
370 in which such objects get relocated does affect file reading code. What if a
371 chunk in the middle of a chain linked by "descend" pointers needs to be moved?
372 What happens in this case is that the old copy of the chunk gets invalidated
373 (the object type byte turned to 00) like in the other object relocating cases,
374 and the sibling pointer of that old index entry (which was originally FFFF as
375 continuation objects have no siblings) is set to point to the new index entry
376 for the same chunk. The "descend" pointer in the new index entry is a copy of
377 that pointer from the old index entry.
378
379 The manner of chunk relocation just described has been observed in the FFS
380 images read out of my most recent batch of Pirelli phones - the same ones in
381 which the root directory object is not at index #1. Thinking about it as I
382 write this, I've realized that the way in which continuation objects get
383 relocated is exactly the same as for other object types - thus the compaction
384 code in the firmware doesn't need to examine what object type it is moving.
385 However, the case of continuation chunk relocation deserves special attention
386 because it affects a read-only implementation like ours - the utilities whose
387 source accompanies this document used to fail on these FFS images until I
388 implemented the following additional handling:
389
390 When following the chunk chain of a file, normally the only object type that's
391 expected is F4 - any other object type is an error. However, as a result of
392 chunk relocation, one can also encounter deleted objects, i.e., type == 00.
393 If such a deleted object is encountered, follow its sibling pointer, which must
394 be non-nil.
395
396 Journal file
397
398 Every Mokopir-FFS image I've seen so far contains a special file named
399 /.journal; this file is special in the following ways:
400
401 * The object type byte is E1 instead of F1;
402 * Unlike regular files, this special file is internally-writable.
403
404 What I mean by the above is that regular files are mostly immutable: once a
405 file has been created with some data content in the head chunk, it can only be
406 either appended to (one or more continuation chunks added), or overwritten by
407 creating a new file with the same name at the same level in the tree hierarchy
408 and invalidating the old one. But the special /.journal file is different: I
409 have never observed it to consist of more than the head chunk, and this head
410 chunk is pre-allocated with some largish and apparently fixed length (4 KiB on
411 my GTA02, 16 KiB on the Pirelli). This pre-allocated chunk contains what look
412 like 16-byte records at the beginning (on the first 4-byte boundary after the
413 NUL terminating the ".journal" name), followed by blank flash for the remainder
414 of the pre-allocated chunk - so it surely looks like new flash writes happen
415 within this chunk.
416
417 I do not currently know the purpose of this /.journal file or the meaning of the
418 records it seems to contain. This understanding would surely be needed if one
419 wanted to create FFS images from scratch or to implement FFS write operations,
420 but I reason that a read-only implementation can get away with simply ignoring
421 this file. I reason that this file can't be necessary in order to parse an FFS
422 image for reading because one needs to parse the tree structure first in order
423 to locate this journal file itself.
424
344 ------------------------------------------------------------------------------- 425 -------------------------------------------------------------------------------
345 426
346 That's all I can think of right now. If anything is unclear, see the 427 That's all I can think of right now. If anything is unclear, see the
347 accompanying source code for the listing/extraction utilities: with the general 428 accompanying source code for the listing/extraction utilities: with the general
348 explanation given by this document, it should be clear what my code does and 429 explanation given by this document, it should be clear what my code does and
357 and writing listing/extraction test code iteratively until I got something that 438 and writing listing/extraction test code iteratively until I got something that
358 appears to correctly parse all FFS images available to me - the result is the 439 appears to correctly parse all FFS images available to me - the result is the
359 code in this package. 440 code in this package.
360 441
361 I never got as far as attempting to locate the FFS implementation routines 442 I never got as far as attempting to locate the FFS implementation routines
362 within the proprietary firmware binary code images, and I most certainly don't 443 within the proprietary firmware binary code images, and I haven't found an
363 have anything from TI that would help in this case. (The TSM30 code doesn't 444 implementation of this particular FFS in any of the leaked sources yet either.
364 seem to be of any use as its FFS appears to be totally different, and I haven't 445 The TSM30 code doesn't seem to be of any use as its FFS appears to be totally
365 looked at the FFS code in the more recently found LoCosto code leak because I 446 different. As to the more recently found LoCosto code leak, I found that one a
366 assumed from the documentation in the latter that the FFS implemented there is 447 few days *after* I got the Moko/Pirelli "MysteryFFS" reverse-engineered on my
367 different as well.) 448 own, and when I did look at the FFS in the LoCosto code later, I saw what seems
449 to be a different FFS as well.
368 450
369 Michael Spacefalcon 451 Michael Spacefalcon
370 SE 52 Mes 11 452 SE 52 Mes 16