FreeCalypso > hg > fc-magnetite
view src/cs/drivers/drv_app/ffs/board/core.h @ 636:57e67ca2e1cb
pcmdata.c: default +CGMI to "FreeCalypso" and +CGMM to model
The present change has no effect whatsoever on Falconia-made and Openmoko-made
devices on which /pcm/CGMI and /pcm/CGMM files have been programmed in FFS
with sensible ID strings by the respective factories, but what should AT+CGMI
and AT+CGMM queries return when the device is a Huawei GTM900 or Tango modem
that has been converted to FreeCalypso with a firmware change? Before the
present change they would return compiled-in defaults of "<manufacturer>" and
"<model>", respectively; with the present change the firmware will self-identify
as "FreeCalypso GTM900-FC" or "FreeCalypso Tango" on the two respective targets.
This firmware identification will become important if someone incorporates an
FC-converted GTM900 or Tango modem into a ZeroPhone-style smartphone where some
high-level software like ofono will be talking to the modem and will need to
properly identify this modem as FreeCalypso, as opposed to some other AT command
modem flavor with different quirks.
In technical terms, the compiled-in default for the AT+CGMI query (which will
always be overridden by the /pcm/CGMI file in FFS if one is present) is now
"FreeCalypso" in all configs on all targets; the compiled-in default for the
AT+CGMM query (likewise always overridden by /pcm/CGMM if present) is
"GTM900-FC" if CONFIG_TARGET_GTM900 or "Tango" if CONFIG_TARGET_TANGO or the
original default of "<model>" otherwise.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 19 Jan 2020 20:14:58 +0000 |
parents | 945cf7f506b2 |
children |
line wrap: on
line source
/****************************************************************************** * Flash File System (ffs) * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com * * ffs core functions * * $Id: core.h 1.80.1.15.1.36 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ * ******************************************************************************/ #if (TARGET == 1) #include "rv/rv_defined_swe.h" #endif /****************************************************************************** * Compile option switches ******************************************************************************/ // FFS compiled with extra test functionality #define FFS_TEST 1 // Default max number of simultaneous open files #ifdef RVM_MSFE_SWE #define FFS_FD_MAX 20 #else #define FFS_FD_MAX 4 #endif #define FFS_RECLAIM_NEW 1 /****************************************************************************** * Compile constants ******************************************************************************/ // FFS API version (in four-digit BCD format) #define FFS_API_VERSION ((uint16) 0x0642) // FFS_DRV_VERSION is in drv.h // TMFFS protocol version is in tmffs.h // Magic for determining (formatted) file system version. First two digits // represent major version, bottom two digits represent minor version. An // ffs code compiled for one major version X is compatible with any other // format version with major = X. Minor version is incremented when adding // new features that does not break compatibility. #define FFS_FORMAT_VERSION (0x0210) #define BLOCK_MAGIC_LOW ('f'<<8|'F') // "Ffs#" #define BLOCK_MAGIC_HIGH ('#'<<8|'s') #define BLOCK_MAGIC ((BLOCK_MAGIC_HIGH << 8)|(BLOCK_MAGIC_LOW)) // Absolute maximum number of inodes allowed #define FFS_INODES_MAX 2048 // Default maximum number of inodes allowed #define FFS_INODES_MAX_DEFAULT 1024 // Default number of path components (limit due to recursiveness of // inodes_reclaim()) #define FFS_PATH_DEPTH_MAX 6 // Maximum number of blocks (flash sectors) in a ffs system. FFS_BLOCKS_MAX // must be >= the number of blocks in the largest flash device memory // map. It is used to allocate the number of entries in the static bstat // array. #define FFS_BLOCKS_MAX 128 // Default size of journal file (represented as 256'ths of the blocksize) #define FFS_JOURNAL_SIZE_IN256THS 16 // one 16'ths of the block size. // Without the min size will the maximum of files (fs.blocks_files_max) in // one block be 32 files if the blocksize is 8kB! #define FFS_JOURNAL_SIZE_MIN 1024 #define FFS_JOURNAL_NAME ".journal" // Default max size of file name (excluding null terminator) #define FFS_FILENAME_MAX 20 // Maximum distance in age between youngest and oldest blocks #define FFS_DAGE_MAX 256 #define FFS_DAGE_GAIN_MIN (FFS_DAGE_MAX / 4) #define FFS_DAGE_EARLY_WIDTH 64 // Offset on file descriptors #define FFS_FD_OFFSET '1' // Macros to set flags and test bits in flash memory words (negative logic) #define BIT_SET(value, bits) ((value) & (~bits)) #define IS_BIT_SET(value, bits) (~(value) & (bits)) // Number of free inodes and journal entries to keep for "emergencies" #define FFS_INODES_MARGIN 4 #define FFS_JOURNAL_MARGIN 4 /****************************************************************************** * Macros used in both drv.c and core.c ******************************************************************************/ // Convert a offset_t value to a block index #define offset2block(offset) (((uint32) offset) >> dev.binfo[0].size_ld) // Convert between offset and address #define offset2addr(offset) (dev.base + (offset)) // Size of a block #define blocksize(block) (1 << dev.binfo[block].size_ld) // Test if flag is set #define is_open_option(options, flags) ((options & flags) == flags) // Amount of reserved space. #define RESERVED_LOW 2 * fs.journal_size #define RESERVED_NONE 0 // We have to saturate because a recently reclaimed inodes block could // theoretically possess a high age #define saturate_dage(dage) (dage > (2*FFS_DAGE_MAX) ? (2*FFS_DAGE_MAX) : dage) /****************************************************************************** * External declarations ******************************************************************************/ extern struct fs_s fs; extern struct block_stat_s bstat[FFS_BLOCKS_MAX]; extern struct ffs_stats_s stats; extern const struct block_info_s *binfo; /****************************************************************************** * Block Types ******************************************************************************/ // Block age, ie. number of times block has been erased typedef uint16 age_t; // Maximum age a block can have #define BLOCK_AGE_MAX 0xFFFF // ffs block status flags. These are stored in the first 2 bytes of // the ffs block in the flash sector. enum BLOCK_FLAGS { BF_LOST = 0x80, // block is lost and will soon be erased BF_FREE = 0x40, // free (preformatted and with block magic) BF_DATA = 0x02, // data BF_CLEANING = 0x01, // block is being cleaned BF_INODES = 0x10, // block contains inodes BF_COPYING = 0x04 // block is a coming inodes block }; enum BLOCK_STATES { BF_IS_EMPTY = ~(0), BF_IS_FREE = ~(BF_FREE), BF_IS_DATA = ~(BF_FREE | BF_DATA), BF_IS_CLEANING = ~(BF_FREE | BF_DATA | BF_CLEANING), BF_IS_COPYING = ~(BF_FREE | BF_COPYING), BF_IS_INODES = ~(BF_FREE | BF_COPYING | BF_INODES), BF_IS_INODES_LOST = ~(BF_FREE | BF_COPYING | BF_INODES | BF_LOST) }; // Header of each FFS block struct block_header_s { uint16 magic_low; // 32-bit magic number uint16 magic_high; uint16 version; // FFS_FORMAT_VERSION used for formatting age_t age; // number of times this block has been erased uint16 flags; // status flags of this block (BLOCK_FLAGS) uint16 reserved0; uint16 reserved1; uint16 reserved2; }; // Important the below define MUST fit to the size of the header that is written #define BHEADER_SIZE sizeof(struct block_header_s) #define OLD_BLOCK_MAGIC_LOW ('S'<<8|'F') // "FS" #define OLD_FFS_FORMAT_VERSION (0x0100) // 1.00 (in four-digit BCD format) // Old header of each FFS block. From old/previous FFS format version struct block_header_old_s { uint8 flags; uint8 copied; uint8 magicflags; uint8 reserved0; uint16 magic_low; uint16 magic_high; uint16 reserved1; uint16 reserved2; }; // Block status. This struct holds the status of one ffs block This relation // is always valid: <block size> = <used> + <lost> + <free>. The block size // is obtained from the corresponding block_info structure. <used> and // <lost> variables always holds a value which is a multiple of // FFS_GRANULARITY. For inodes, <used> is number of inodes in active use, // <lost> is number of deleted/lost inodes, <numfiles> is the index of the // first free inode. struct block_stat_s { blocksize_t used; // number of used bytes blocksize_t lost; // number of lost bytes uint16 flags; // flash block flags (first 16 bits of each block) uint16 objects; // number of valid objects }; /****************************************************************************** * Object Types ******************************************************************************/ // This enum MUST be in sync with the one in ffs.h. enum OBJECT_TYPE_E { // remaining filetypes are in ffs.h OT_ERASED = 0, OT_NULL = 7, OT_MASK = 7, OT_MAX = 4 }; // This enum MUST be in sync with the one in ffs.h. enum OBJECT_FLAGS_E { // remaining object flags are in ffs.h OF_UNDEF0 = 1<<5, OF_UNDEF1 = 1<<6, OF_EXACT = 1<<7, // used by control()/update_commit() interaction. This // is *not* an object flag! OF_ALL = OF_READONLY, // all flags allowed to be changed by user OF_MASK = 0xF0 }; struct inode_s { uint16 size; uint8 reserved; // size extension? objflags_t flags; iref_t child; // link to first inode in dir (this inode is a dir) iref_t sibling; // link to next inode in same directory location_t location; // location of object uint16 sequence; // uint16 updates; // times this object has been updated }; struct file_descriptor_s { char *buf; // Write buffer iref_t seghead; // First chunk. Contain file name and optional data iref_t wch; // Inode of work chunk (if chunk is read to buf) int fp; // File pointer int wfp; // Work file pointer always points to start of wch int size; // Size of object (all chunks and data from buf) int8 options; // Open options int dirty; // Indicate if buf contain valid data or not }; /****************************************************************************** * Journal types and global fs structure ******************************************************************************/ enum JOURNAL_FLAGS { JOURNAL_WRITING = 0x02, // journal is being written to journal file JOURNAL_READY = 0x04, // journal has been written to journal file JOURNAL_DONE = 0x08 // journal has been written to ffs }; enum JOURNAL_STATES { JOURNAL_IS_EMPTY = ~(0), JOURNAL_IS_WRITING = ~(JOURNAL_WRITING), JOURNAL_IS_READY = ~(JOURNAL_WRITING | JOURNAL_READY), JOURNAL_IS_DONE = ~(JOURNAL_WRITING | JOURNAL_READY | JOURNAL_DONE) }; // Journal entry structure. Note that the state byte *MUST* be the first // byte of the structure! struct journal_s { uint8 state; // state of journal entry. objflags_t flags; // type of object iref_t i; // iref of object iref_t diri; // iref of object that is this object's parent/sibling iref_t oldi; // iref of object being replaced (only for updates) location_t location; // object's location uint16 size; // object's size iref_t repli; // inode which is replaced }; // Main ffs info struct (initialised by ffs_initialize()) struct fs_s { struct inode_s *inodes_addr; // base address of inodes iref_t root; // iref of root directory bref_t inodes; // index into bstat containing inode block bref_t newinodes; // index into bstat containing new inode block bref_t blocks_free_min; // Number of spare blocks (0 or 1) int filesize_max; // Max size of object data int reserved_space; // Byte size of space reserved for journal relocation iref_t inodes_max; // Max number of inodes possible iref_t inodes_high; // number of inodes triggering an inodes_reclaim() iref_t objects_max; // Max number of objects (valid inodes) allowed age_t age_max; // Max block age found by blocks_fsck() iref_t block_files_max; // max number of files in a block iref_t block_files_reserved; // Reserved for journals uint16 format; // FFS version as formatted in flash blocks uint16 sequence; // Object sequence number (for debug only) effs_t initerror; // ffs_initialize() return code uint8 lost_threshold; // Threshold percentage for data block reclaim uint8 flags; // Global FFS options/flags uint8 filename_max; // Max length of a filename uint8 path_depth_max; // Max path componenents allowed uint8 numfds; // Mumber of available file descriptors uint8 testflags; int8 journal_depth; // Current journal nesting depth (0 or 1) iref_t ijournal; // iref of journal file uint32 journal_size; // Byte size of journal file uint32 journal_pos; // Byte offset to first free entry in journal file struct journal_s journal; uint8 fd_max; // number of max available file descriptors int fd_buf_size; // size of stream buffer struct file_descriptor_s fd[FFS_FD_MAX]; struct journal_s ojournal; // "Old" journal int link_child; // Link child in journal or not iref_t i_backup; // Used by ffs_file_write() int chunk_size_max; // Max size of one chunk int chunk_size_min; // Min size of one chunk uint32 debug[4]; }; // This is the layout of the FFS performance statistics file. The file is // created with the name ".statistics" in the root directory at format. It // is updated after each data and inodes reclaim (after writing the file // that provoked the reclaim). The file is only updated if it exists, so if // the user does not want the file, she can erase it after the initial // format. FIXME: The use of the .statistics file is not yet implemented struct ffs_stats_s { uint32 data_allocated; // implemented struct { // Not yet implemented uint32 created; uint32 updated; uint32 read; } files; struct { // Not yet implemented uint32 written[2]; uint32 read[2]; } bytes; struct { uint32 most_lost; // Block candidate uint32 most_unused; // Block candidate uint32 youngest; // Block candidate uint32 valid[2]; // Amount of valid reclaimed data uint32 lost[2]; // Amount of lost reclaimed data } drec; struct { uint32 num; // Number of inode reclaims uint32 valid; // Number of valid reclaimed inodes uint32 lost; // Number of lost reclaimed inodes } irec; }; extern struct ffs_stats_s stats; /****************************************************************************** * Miscellaneous types ******************************************************************************/ // only used with (FFS_TEST == 1) enum TEST_RECOVERY { JOURNAL_TEST_BASE = 0x10, JOURNAL_TEST_EMPTY, JOURNAL_TEST_WRITING, JOURNAL_TEST_READY, JOURNAL_TEST_COMMITTING, JOURNAL_TEST_COMMITTED, JOURNAL_TEST_DONE, BLOCK_COMMIT_BASE = 0x20, BLOCK_COMMIT_BEFORE, BLOCK_COMMIT_NO_VALID, BLOCK_COMMIT_OLD_FREE, BLOCK_COMMIT_AFTER, BLOCK_RECLAIM_BASE = 0x40, BLOCK_RECLAIM_ALLOC, BLOCK_RECLAIM_CLEANING, BLOCK_RECLAIM_NO_CLEAN, BLOCK_RECOVER_OBJECTS }; enum FLASH_DATA { FLASH_NULL8 = 0xFF, FLASH_NULL16 = 0xFFFF, FLASH_NULL32 = 0xFFFFFFFFL, IREF_NULL = FLASH_NULL16 }; // This enum MUST be in sync with the one in ffs.h. enum OBJECT_CONTROL { // remaining object control codes are in ffs.h OC_FS_FLAGS = 80, OC_TRACE_INIT = 82, OC_DEV_MANUFACT = 88, OC_DEV_DEVICE = 89, OC_DEBUG_FIRST = 120, OC_DEBUG_0 = 120, OC_DEBUG_1 = 121, OC_DEBUG_2 = 122, OC_DEBUG_3 = 123, OC_DEBUG_LAST = 123, OC_FS_TESTFLAGS = 127 }; enum FS_FLAGS { FS_DIR_DATA = 0x01 // allow directory objects to contain data. }; enum RECLAIM_CANDIDATE { MOST_LOST, MOST_UNUSED, YOUNGEST }; /****************************************************************************** * Macros ******************************************************************************/ // Convert between location and offset #define location2offset(location) ((location) << dev.atomlog2) #define offset2location(offset) (((uint32) offset) >> dev.atomlog2) // test if object is of a specific type #define is_object(objp, type) (((objp)->flags & OT_MASK) == (type)) // test if object is valid (directory, file or symlink) #define is_object_valid(ip) ((ip->flags & OT_MASK) <= OT_MAX && (ip->flags & OT_MASK) != OT_ERASED) // test if block is in a specific state #define is_block(block, state) (bstat[block].flags == (uint16) (state)) // test if block has certain flags set #define is_block_flag(block, bits) (IS_BIT_SET(bstat[block].flags, (bits))) // convert an object's data address to the address of the object's name #define addr2name(addr) (addr) // Convert a size to an aligned size #define atomalign(size) (((size) + dev.atomsize-1) & ~dev.atomnotmask) #define wordalign(size) (((size) + 3) & ~3) #define halfwordalign(size) (((size) + 1) & ~1) #define inode_addr(i) (fs.inodes_addr + i) #define JOURNAL_POS_INITIAL (wordalign(2 + sizeof(FFS_JOURNAL_NAME) + 1)) /****************************************************************************** * Function prototypes ******************************************************************************/ // Helper functions effs_t is_filename(const char *s); int ffs_strlen(const char *s); int ffs_strcmp(const char *s, const char *p); char *addr2data(const char *addr, const struct inode_s *ip); int object_datasize(iref_t i); iref_t is_readonly(iref_t i, const char *name); iref_t dir_traverse(iref_t i, iref_t *entries); bref_t block_alloc(bref_t n, uint16 flags); bref_t block_alloc_try(bref_t *n); void block_flags_write(uint8 block, uint8 flags); offset_t data_alloc(int size); offset_t data_alloc_try(int size); offset_t data_reserved_alloc(int size); iref_t inode_alloc(void); effs_t is_fd_valid(fd_t fdi); effs_t is_offset_in_buf(int offset, fd_t fdi); iref_t chunk_alloc(int realsize, int is_journal, offset_t *offset); iref_t inode_alloc_try(void); fd_t get_fdi(iref_t i); offset_t data_prealloc(int realsize); // Functions used by API effs_t object_update(iref_t oldi); iref_t object_create(const char *name, const char *buf, int size, iref_t dir); int file_read(const char *name, void *addr, int size); int stream_read(fd_t fdi, void *src, int size); int object_read(const char *name, char *buf, int size, int linkflag); iref_t object_stat(const char *name, struct xstat_s *stat, int linkflag, int fdi, int extended); effs_t object_remove(iref_t i); iref_t object_rename(iref_t oldi, const char *newname, iref_t newdir); effs_t object_control(iref_t i, int8 action, int value); int object_truncate(const char *pathname, fd_t fdi, offset_t length); iref_t object_lookup(const char *path, char **leaf, iref_t *dir); iref_t object_lookup_once(const char *path, char **leaf, iref_t *dir); iref_t dir_open(const char *name); iref_t dir_next (iref_t dir, iref_t i, char *name, int8 size); // Journalling void journal_begin(iref_t oldi); void journal_end(uint8 type); void journal_commit(uint8 type); int journal_push(void); int journal_pop(void); iref_t journal_create(iref_t oldi); effs_t journal_init(iref_t i); // Format, Init and Reclaim void block_preformat(bref_t b, age_t age); effs_t fs_preformat(void); effs_t is_formattable(int8 flag); effs_t fs_format(const char *fsname_and_options); effs_t ffs_initialize(void); void fs_params_init(const char *p); blocksize_t block_used(bref_t b); effs_t ffs_begin(void); int ffs_end(int error); int block_reclaim(bref_t b); int blocks_reclaim(void); void block_commit(void); iref_t data_reclaim(int space); int data_reclaim_try(int space); iref_t data_block_reclaim(bref_t b, int reclaim_candidate); iref_t object_relocate(iref_t oldi); iref_t block_clean(bref_t b); void block_free(bref_t block); void inodes_set(iref_t i); effs_t inodes_reclaim(void); int reclaim(void); // Internally used functions effs_t file_read_int(const char *path, void *src, int size); effs_t file_update(const char *path, void *src, int size); int statistics_file_create(void); int statistics_write(void); void statistics_init(void); void statistics_update_drec(int valid, int lost, int candidate); void statistics_update_irec(int valid, int lost); // Chunk Operations iref_t segment_create(const char *buf, int size, iref_t dir); int segment_datasize(const struct inode_s *ip); int segment_read(iref_t i, char *buf, int size, int offset); iref_t segment_next(iref_t i); iref_t segment_traverse(iref_t i, iref_t *entries); int segfile_seek(iref_t in_i, int in_pos, iref_t *out_i, int *out_pos_i); iref_t chunk_traverse(iref_t i); effs_t datasync(fd_t fdi); // debug/test functions void tr_bstat(void); void tr_fd(fd_t fdi); // These prototypes really belong in ffs.h but as they have not been // implemented, we will not show these prototypes to application // programmers. effs_t fcntl(fd_t fd, int8 action, uint32 *param);