bullshit commit, sync for travel (to zn00H!) :)
[my-code/arm.git] / betty / pffs.c
index 995e108..93351bd 100644 (file)
  * functions
  */
 
-int pffs_flash_register(t_pffs *pffs,u32 base_addr,u8 sec_num,u32 *sec_addr,
-                        u8 dmin,u8 dmax,u8 index1,u8 index2,
+#define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
+#define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
+#define pffs_daddr_msb(data) (((data)&PFFS_LEN_MSB_MASK))
+#define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
+
+u32 pffs_find_index(t_pffs *pffs,u8 sector) {
+
+       u16 data;
+
+       pffs->fr(pffs->base_addr+pffs->sec_addr[sector],&data,2);
+
+       if((data&0xf000)==PFFS_INDEX_MAGIC) {
+               pffs->index_sec=sector;
+               return PFFS_INDEX_FOUND;
+       }
+
+       return PFFS_NO_INDEX_FOUND;
+}
+
+int pffs_sec_empty(t_pffs *pffs,u8 sec) {
+
+       u32 addr;
+       u16 data;
+
+       addr=pffs->base_addr|pffs->sec_addr[sec];
+
+       while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
+               pffs->fr(addr,&data,2);
+               if(data!=0xffff)
+                       return PFFS_SEC_NOT_EMPTY;
+               addr+=2;
+       }
+
+       return PFFS_SEC_EMPTY;
+}
+
+int pffs_find_data_tmp(t_pffs *pffs,u8 sector) {
+
+       u32 iaddr,daddr,dend,dstart;
+       u16 data[3];
+       u8 fnlen;
+
+       iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
+       dstart=pffs->sec_addr[sector];
+       dend=pffs->sec_addr[sector+1];
+
+       while(iaddr<(pffs->base_addr|pffs->sec_addr[sector+1])) {
+               pffs->fr(iaddr,data,6);
+               if(pffs_check_magic(data[0]))
+                       break;
+               daddr=pffs_daddr_msb(data[0])|data[1];
+               if((daddr+data[2]<dstart)|(daddr>=dend)) {
+                       fnlen=pffs_fnlen(data[0]);
+                       iaddr+=(6+fnlen+fnlen);
+                       continue;
+               }
+               else
+                       return PFFS_NO_DATA_TMP;
+       }
+
+       pffs->data_tmp_sec=sector;
+       if(pffs_sec_empty(pffs,sector)!=PFFS_SEC_EMPTY)
+               pffs->fe(pffs->base_addr|dstart);
+
+       return PFFS_DATA_TMP_FOUND;;
+}
+
+int pffs_orientate(t_pffs *pffs) {
+
+       u8 sec,sec0,sec1,found;
+
+       sec0=pffs->sec_num_index[0];
+       sec1=pffs->sec_num_index[1];
+
+       found=0;
+
+       /* check index sectors */
+       if(pffs_find_index(pffs,sec0)==PFFS_INDEX_FOUND)
+               found=1;
+       else if(pffs_find_index(pffs,sec1)==PFFS_INDEX_FOUND)
+               found=1;
+
+       /* chose temp data sector */
+       if(found) {
+               sec0=pffs->sec_num_data[0];
+               sec1=pffs->sec_num_data[1];
+               for(sec=sec1;sec>=sec0;sec--)
+                       if(pffs_find_data_tmp(pffs,sec)==PFFS_DATA_TMP_FOUND)
+                               break;
+
+               return PFFS_INDEX_FOUND;
+       }
+
+       /* initial run => no data + no index assumed => check whether erased! */
+       // erase index sectors
+       if(!pffs_sec_empty(pffs,sec0))
+               pffs_sec_erase(pffs,sec0);
+       if(!pffs_sec_empty(pffs,sec1))
+               pffs_sec_erase(pffs,sec1);
+       pffs->index_sec=sec0;
+       // erase data sectors
+       sec0=pffs->sec_num_data[0];
+       sec1=pffs->sec_num_data[1];
+       pffs->data_tmp_sec=sec1;
+       for(sec=sec0;sec<=sec1;sec++)
+               if(!pffs_sec_empty(pffs,sec))
+                       pffs_sec_erase(pffs,sec);
+
+       return 0;
+}
+
+int pffs_get_data_sec(t_pffs_fd *fd) {
+
+       t_pffs *pffs;
+       u8 sec,sec0,sec1;
+
+       pffs->fd->pffs;
+       sec0=pffs->sec_num_data[0];
+       sec1=pffs->sec_num_data[1];
+
+       for(sec=sec0;sec<sec1;sec++) {
+               if((addr<pffs->sec_addr[sec+1])&(addr>=pffs->sec_addr[sec])) {
+                       fd->data_sec=sec;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+int pffs_rearrange(t_pffs *pffs) {
+
+       
+
+       return 0;
+}
+
+int pffs_flash_register(t_pffs *pffs,u32 base_addr,u32 *sec_addr,u8 sec_num,
                         int (*fw)(u32 addr,u16 *buf,int len),
                        int (*fr)(u32 addr,u16 *buf,int len),
                        int (*fe)(u32 addr)) {
 
+       /* assign physical flash specs */
        pffs->base_addr=base_addr;
-       pffs->sec_num=sec_num;
        pffs->sec_addr=sec_addr;
+       pffs->sec_num=sec_num;
+
+       /* flash acccess function pointers */
        pffs->fw=fw;
        pffs->fr=fr;
        pffs->fe=fe;
@@ -31,9 +170,188 @@ int pffs_flash_register(t_pffs *pffs,u32 base_addr,u8 sec_num,u32 *sec_addr,
 
 int pffs_init(t_pffs *pffs) {
 
+       /* check whether a flash is registered */
        if(!(pffs->state&PFFS_REGISTERED))
                return -1;
 
+       /* orientate */
+       pffs_orientate(pffs);
+
+       return 0;
+}
+
+int pffs_find_file(t_pffs *pffs,char *file,u32 *iaddr,u32 *daddr,u16 *len) {
+
+       u8 fnl;
+       u16 data[PFFS_MAX_FILENAME_SIZE+PFFS_HEADER_SIZE];
+
+       *iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
+
+       while(*iaddr<pffs->sec_addr[pffs->index_sec+1]) {
+               pffs->fr(*iaddr,data,3);
+
+               if(!pffs_check_magic(data[0]))
+                       break;
+
+               fnl=pffs_fnlen(data[0]);
+               pffs->fr(*iaddr+6,data+3,fnl+fnl);
+
+               if(!strncmp(file,(char *)(data+3),fnl+fnl)) {
+                       *daddr=pffs->base_addr|((data[0]&0x000f)<<16)|data[1];
+                       *len=data[2];
+                       return PFFS_FILE_FOUND;
+               }
+
+               *iaddr+=(6+fnl+fnl);
+       }
+       
+       return PFFS_FILE_NOT_FOUND;
+}
+
+int pffs_open_read(t_pffs_fd *fd) {
+
+       int ret;
+
+       ret=pffs_find_file(fd->pffs,fd->file,
+                          &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+       if(ret==PFFS_FILE_FOUND) {
+               fd->dptr=fd->daddr;
+               fd->mode=PFFS_READ;
+       }
+
+       return ret;
+}
+
+int pffs_write_index_init(t_pffs_fd *fd) {
+
+       t_pffs *pffs;
+       u16 data[PFFS_HEADER_SIZE+PFFS_MAX_FILENAME_SIZE];
+
+       pffs=fd->pffs;
+       fns=fd->fn-size;
+
+       if(fd->iaddr+6+fns+fns>=pffs->sec_addr[pffs->index_sec+1])
+               return PFFS_NO_INDEX_SPACE_LEFT;
+
+       data[0]=0x7f00|(fns<<4)|((fd->daddr>>16)&0xf);
+       data[1]=fd->daddr&0xffff;
+       pffs->fw(fd->iaddr,data,4);
+       pffs->fw(fd->iaddr+6,fd->file,fns+fns);
+       
+       return PFFS_INDEX_WROTE_INIT;
+}
+
+int pffs_write_finish(t_pffs_fd *fd) {
+
+       fd->pffs->fw(fd->iaddr+4,&(fd->len),2);
+
        return 0;
 }
 
+int pffs_open_write(t_pffs_fd *fd) {
+
+       int ret;
+
+       ret=pffs_find_file(fd->pffs,fd->file,
+                          &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+       switch(ret) {
+               case PFFS_FILE_NOT_FOUND:
+                       ret=pffs_write_index_init();
+                       if(ret!=PFFS_INDEX_WROTE_INIT)
+                               break;
+                       fd->dptr=fd->daddr;
+                       fd->len=0;
+                       fd->mode=PFFS_WRITE;
+                       break;
+               case PFFS_FILE_FOUND:
+               default:
+                       break;
+       }
+
+       return ret;
+}                      
+
+int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode) {
+
+       int ret;
+
+       /* the pffs struct */
+       fd->pffs=pffs;
+
+       /* filename */
+       fd->fn_size=strlen(file);
+       if(fd->fn_size&1)
+               fd->file[fd->fn_size++]='\0';
+       fd->fn_size>>1;
+       if(fd->fn_size>PFFS_MAX_FILENAME_SIZE)
+               return PFFS_FILENAME_TOO_LONG;
+       strncpy(fd->file,file,fd->fn_size+fd->fn_size);
+
+       /* clear fd mode */
+       fd->mode=0;
+
+       /* action */
+       switch(mode) {
+               case PFFS_READ:
+                       ret=pffs_open_read(fd);
+                       break;
+               case PFFS_WRITE:
+                       ret=pffs_open_write(fd);
+                       break;
+               case PFFS_RDWR:
+               default:
+                       return PFFS_MODE_UNSUPPORTED;
+       }
+
+       return ret;
+}
+
+int pffs_read(t_pffs_fd *fd,u8 *buf,int len) {
+
+       int missing;
+       int sec_end;
+
+       /* check whether valid */
+       if(!(fd->mode&PFFS_READ))
+               return PFFS_EINVAL;
+
+       /* check len */
+       if(len&1)
+               return PFFS_INVALID_LEN;
+
+       /* check how much we read */
+       missing=fd->len-(fd->dptr-fd->daddr);
+       if(len>missing)
+               len=missing;
+
+       if((fd->dptr+len)>=pffs->sec_addr[pffs->sec_num_data[1]+1])
+               sec_end=pffs->sec_addr[pffs->sec_num_data[1]+1]-fd->dptr;
+
+
+       /* read */
+       fd->pffs->fr(fd->dptr,(u16 *)buf,len);
+       fd->dptr+=len;;
+
+       return len;
+}
+
+int pffs_write(t_pffs_fd *fd,u8 buf,int len) {
+
+       /* check whether valid */
+       if(!(fd->mode&PFFS_WRITE))
+               return PFFS_EINVAL;
+
+       /* check len */
+       if(len&1)
+               return PFFS_INVALID_LEN;
+
+       missing=PFFS_MAX_FILE_SIZE-fd->len;
+       if(len>missing)
+               len=missing;
+
+       /* check for  */
+       if(fd->dptr+len>=pffs->)
+}
+