jielie

JLFS

Format

Flash header

Unlike its predecessor, the SDFILE, the flash header now is only present in the beginning of a flash image, rather than being a header for each filesystem image as in the former case.

struct jlfs2_flash_header {
  uint16_t  hdr_crc;      /* Header CRC */
  uint16_t  burner_size;  /* Burner size */
  char      vid[4];       /* Version ID */
  uint32_t  flash_size;   /* Flash size */
  uint8_t   fs_ver;       /* FS version */
  uint8_t   block_align;  /* Block alignment */
  uint8_t   resvd;        /* (reserved) */
  uint8_t   special_opt;  /* Special option flag */
  char      pid[16];      /* Product ID */
};

When this header is put into the flash image, it is usually stored in encrypted form, however, some fields actually appear as unencrypted in the final image, while the header CRC still being correct.

Presumeably, this is done as follows:

File header

struct jlfs2_file_entry {
  uint16_t  hdr_crc;  /* Header CRC */
  uint16_t  data_crc; /* Data CRC */
  uint32_t  offset;   /* Data offset */
  uint32_t  size;     /* Size */
  uint8_t   attr;     /* Attributes */
  uint8_t   resvd;    /* (reserved) -- or not quite */
  uint16_t  index;    /* Index */
  char      name[16]; /* File name */
};

Unlike SDFILE, the file entries contain the ‘index’ field which can indicate whether it is the last file in the list or not, as well as having the header’s CRC field, thus completely eliminating need for a global header as a such. (in SDFILE, the header contains file count and a CRC of all file entries)

Layout

A typical layout has a block of file headers followed by the data for each file, like so:

    .------------------------.
    |  File A header         |  <=== index is zero
    :------------------------:
    |  File B header         |
    :------------------------:
    |  File C header         |
    :------------------------:
    .                        .
    .                        .
    :------------------------:
    |  File X header         |  <=== index is nonzero
    :------------------------:
    |                        |
    |  File A data           |
    |                        |
    :------------------------:
    |                        |
    |  File B data           |
    |                        |
    :------------------------:
    .                        .
    .                        .
    :------------------------:
    |                        |
    |  File X data           |
    |                        |
    '------------------------'

However, in some cases, like in the SFC map area, file headers and their data are interleaved like so:

    .------------------------.
    |  File A header         |  <=== index is zero
    :------------------------:
    |                        |
    |  File A data           |
    |                        |
    :------------------------:
    |  File B header         |
    :------------------------:
    |                        |
    |  File B data           |
    |                        |
    :------------------------:
    |  File C header         |
    :------------------------:
    .                        .
    .                        .
    :------------------------:
    |  File X header         |  <=== index is nonzero
    :------------------------:
    |                        |
    |  File X data           |
    |                        |
    '------------------------'

Moreover, the data are addressed relative to the location of the file header, rather than the beginning of a whole image, and the size field contains size of both the file header and its data, effectively indicating the size of the whole ‘image’. If this is a directory entry, then the files within such an entry (laid in a usual way now) are addressed relative to the directory’s entry header as well.

This approach allows to easily construct an image simply by concatenating several images together, without any need to reconstruct the whole image.