LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Cvs-checkins > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: cvs at opencores.org<cvs@o...>
    Date: Fri Jun 23 21:03:51 CEST 2006
    Subject: [cvs-checkins] MODIFIED: mb-jpeg ...
    Top
    Date: 00/06/06 23:21:03

    Added: mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src
    xilfatfs_alloc.c xilfatfs_bufcache.c
    xilfatfs_chdir.c xilfatfs_close.c xilfatfs_direct.c
    xilfatfs_directory.c xilfatfs_fat.c
    xilfatfs_fat12.c xilfatfs_fat16.c xilfatfs_fat32.c
    xilfatfs_filespec.c xilfatfs_filestatus.c
    xilfatfs_mkdir.c xilfatfs_open.c xilfatfs_part.c
    xilfatfs_read.c xilfatfs_readdisk.c
    xilfatfs_standalone-utils.c xilfatfs_stats.c
    xilfatfs_sysace.c xilfatfs_sysace_stdio.c
    xilfatfs_wd.c xilfatfs_write.c
    Log:
    Updated to EDK8.1


    Revision Changes Path
    1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_alloc.c

    http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_alloc.c?rev=1.1&content-type=text/x-cvsweb-markup

    Index: xilfatfs_alloc.c
    ===================================================================
    /////////////////////////////////////////////////////////////////////////
    //
    // Copyright (c) 2004 Xilinx, Inc. All rights reserved.
    //
    // Xilinx, Inc.
    //
    // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
    // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
    // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
    // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
    // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
    // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
    // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
    // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
    // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
    // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
    // AND FITNESS FOR A PARTICULAR PURPOSE.
    //
    ////////////////////////////////////////////////////////////////////////////////

    #include <string.h>
    #include "alloc.h"
    #include "fat.h"

    /* Create and release WDs */
    static WorkingDirectory wd_buf[MAXWD];
    static int wd_init_flag = 1;

    WorkingDirectory *
    malloc_wd(const char *name)
    {
    int i;

    /* Do initialization because MBlaze seems not to initialize statics per K&R */
    if(wd_init_flag) {
    wd_init_flag = 0;
    for(i=0; i<MAXWD; i++ )
    wd_buf[i].name[0] = 0;
    }

    for(i=0; i<MAXWD; i++)
    if(wd_buf[i].name[0] == 0) {
    strncpy(wd_buf[i].name, name, MAXFILENAMESIZE);
    return wd_buf + i;
    }

    return 0;
    }

    void
    free_wd(WorkingDirectory *wd)
    {
    wd->name[0] = 0;
    }

    static FileStatus fs_buf[MAXFILES];
    static int fs_init_flag = 1;

    FileStatus *
    malloc_fs(void)
    {
    int i;

    if(fs_init_flag) {
    fs_init_flag = 0;
    for(i=0; i<MAXFILES; i++)
    fs_buf[i].reserved = 0;
    }

    for(i=0; i<MAXFILES; i++)
    if( fs_buf[i].reserved == 0 ) {
    fs_buf[i].reserved = 1;
    return fs_buf + i;
    }

    return 0;
    }

    void free_fs(FileStatus *fs) { fs->reserved = 0; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_bufcache.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_bufcache.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_bufcache.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <string.h> #include "xparameters.h" #include "sysace.h" #include "bufcache.h" #include "util.h" struct bufcache_status_s { unsigned char valid; unsigned char dirty; int sector; }; #define N_BUFCACHE_ENTRIES ((XILFATFS_BUFCACHE_SIZE/SECTORSIZE)) struct bufcache_status_s bc_status[N_BUFCACHE_ENTRIES]; unsigned char bc[XILFATFS_BUFCACHE_SIZE]; int bc_replace_index; int (*ll_write)(UINT32 sector, BYTE *buf); /* return the index of sector in buffer cache if present, * -1 if sector not in buffer cache */ int is_buffered(unsigned int sector) { int i; for (i = 0; i < N_BUFCACHE_ENTRIES; i++) if (bc_status[i].valid && bc_status[i].sector == sector) return i; return -1; } /* get a free entry in the buffer cache */ int bc_get_free_entry() { int i; for (i = 0; i < N_BUFCACHE_ENTRIES; i++) if (!bc_status[i].valid) return i; return -1; } /* find free space by replacing an entry */ int sequential_replace() { int cur_index = bc_replace_index; bc_replace_index = (bc_replace_index + 1)%N_BUFCACHE_ENTRIES; if (!bc_status[cur_index].valid) { /* current entry to be replaced is not in use */ return cur_index; } if (bc_status[cur_index].dirty) { /* sync the current entry to disk */ int n = (*ll_write)(bc_status[cur_index].sector, (bc+cur_index*SECTORSIZE)); if (n != SECTORSIZE) { /* fatal - cannot be synced */ return -1; } bc_status[cur_index].dirty = 0; } return cur_index; } /* initialize buffer cache. * use the low level write function (*ll_write_fn) when required to sync to disk * should be called before any other function to bufcache */ void init_bufcache(int (*ll_write_fn)(UINT32 sector, BYTE *buf)) { memset(bc_status, 0, sizeof (bc_status)); bc_replace_index = 0; ll_write = ll_write_fn; } /* update buffer cache with data for @sector */ int update_bufcache(int sector, unsigned char *sector_buf, int dirty) { int index = is_buffered(sector); if (index < 0) /* if not buffered */ index = bc_get_free_entry(); if (index < 0) { /* not buffered, and no free entry in the cache */ index = sequential_replace(); /* replace something */ if (index < 0) return -1; } bc_status[index].valid = 1; bc_status[index].dirty = dirty; bc_status[index].sector = sector; memcpy(bc + index*SECTORSIZE, sector_buf, SECTORSIZE); return SECTORSIZE; } /* read data for @sector from buffer cache */ int read_bufcache(int sector, unsigned char *sector_buf) { int n = is_buffered(sector); if (n < 0) return -1; memcpy(sector_buf, bc + n*SECTORSIZE, SECTORSIZE); return SECTORSIZE; } /* sync dirty entries to the disk */ int sync_bufcache() { int i, error = 0; for (i = 0; i < N_BUFCACHE_ENTRIES; i++) if (bc_status[i].valid && bc_status[i].dirty) { if ((*ll_write)(bc_status[i].sector, bc + i*SECTORSIZE) != SECTORSIZE) error = 1; bc_status[i].dirty = 0; } return -error; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_chdir.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_chdir.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_chdir.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "filespec.h" #include "directory.h" #include "util.h" /* Limited to 8 character filenames */ int sysace_chdir(const char *path) { WorkingDirectory *wd; int partition; wd = build_working_directory_stack(path, 1, 0); if (wd) { /* This is a valid directory path */ partition = wd->pi->PartitionNum; if (cwd[partition]) delete_working_directory_stack(cwd[partition]); cwd[partition] = wd; DefaultPartition = partition; return 0; } return -1; } #ifdef GET_CWD #define GETDCWDBUFSIZE 100 char *my_getdcwd(int drive, char *path, int pathsize) { int length, level; int i, j; char *s, *buf_t; char buf[GETDCWDBUFSIZE]; WorkingDirectory *wd; if (drive == 0) { /* Use the default drive */ drive = DefaultPartition; } else drive -= 1; if (drive < 0 || drive >= MAXPARTITION) return 0; if (cwd[drive] == 0) { /* Set the default */ cwd[drive] = build_working_directory_stack(DIRSEPSTRING, 1, 0); if (cwd[drive] == 0) return 0; } /* Determine the total length needed */ level = 0; length = 3; /* Drive specification, terminating 0 */ wd = cwd[drive]; while (wd) { length += strlen(wd->name); ++level; wd = wd->parent; } if (level > 2) length += level - 2; /* Allow for separating characters */ if (path) { /* Use the users buffer */ if (pathsize < length) return 0; s = path; } else { if (GETDCWDBUFSIZE < length) return 0; s = buf; } /* Drive letter */ s[0] = 'a' + drive; s[1] = ':'; /* terminate the string */ i = length; s[--i] = 0; wd = cwd[drive]; while (wd) { j = strlen(wd->name); /* Copy the directory name */ while (j > 0) { if (i < 2) { /* Something went wrong - we re about to run out of room */ return 0; } s[--i] = wd->name[--j]; } /* Add separator. Note that root and 2nd level directory do not need separators. */ if (level > 2) s[--i] = DIRSEPCHAR; --level; wd = wd->parent; } if (i != 2) { /* Something went wrong - at this point there should be space remaining for * the drive spec (2 characters). */ return 0; } if (s == path) return path; /* Make a new string - user is responsible for free()ing this string */ buf_t = (char *)malloc(strlen(buf) + 1); if (!buf_t) return 0; return strcpy(buf_t, buf); } #endif /*GET_CWD */ 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_close.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_close.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_close.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "sysace_stdio.h" #include "filestatus.h" #include "bufcache.h" int sysace_fclose(SYSACE_FILE *stream) { if (stream == 0) return 0; /* sync the buffer cache to the disk */ sync_bufcache(); return delete_file_status((FileStatus *) stream); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_direct.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_direct.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_direct.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// /* All functions have been moved to other files */ 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_directory.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_directory.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_directory.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <ctype.h> #include <string.h> #include "fat.h" #include "filespec.h" #include "alloc.h" #include "directory.h" int dir_name_compare(const char *a, const char *b, int n) { char ac, bc; int an = strlen(a); while (an > 0 && *a) { ac = tolower(*a); bc = tolower(*b); if (ac < bc) return -1; if (ac > bc) return 1; ++a; ++b; --n; --an; } while (n > 0) { /* finished text chars now check for trailing spaces */ if (*b != ' ') return -1; ++b; --n; } if (n == 0) return 0; if (*b) return 1; return 0; } /* Locate the named file or directory in the specified working directory * The name is not hierarchical. Set ext = NULL to find a directory. * Set ext = name = NULL to find an free entry */ int find_in_directory(WorkingDirectory *wd, const char *name, const char *ext, UINT32 * firstcluster, UINT32 * filesize, UINT32 *de_sector, UINT32 *de_offset) { BYTE buf[SECTORSIZE]; int bufcount; int is_sub_dir = 0; UINT32 sector; UINT32 filecount; UINT32 nsectors; UINT32 cluster; DirectoryEntry *de; if (wd->pi->FatType != FAT32 && wd->parent == 0) { /* Root directory */ filecount = wd->v.root.DirCount * DIRENT_SIZE; sector = wd->v.root.StartSector; nsectors = filecount / SECTORSIZE; cluster = 0; } else { /* Child directory || FAT32 * (In Fat32 root & child are treated similarly) */ cluster = wd->v.child.FirstCluster; sector = starting_sector(cluster, wd->pi); nsectors = wd->pi->SectorsPerCluster; filecount = nsectors * SECTORSIZE; is_sub_dir = 1; if (sector == 0) { /* FAT problem ? */ return 0; } } /* Keep going until the whole directory has been read. * Note: it is necessary to check filecount in the inner * loops as well because we can hit end-of-file anywhere * within a cluster. */ while (filecount) { /* Keep going until the whole root or cluster has been read */ while (nsectors && filecount) { /* Get the current sector */ if (read_sector(sector, buf) != SECTORSIZE) return 0; bufcount = 0; ++sector; --nsectors; while ((bufcount < SECTORSIZE) && filecount) { /* Process a single directory entry */ filecount -= DIRENT_SIZE; if (filecount < 0) { /* This is some wierd error, both filesize and * SECTORSIZE should be an integer multiple of DIRENT_SIZE. */ return 0; } de = (DirectoryEntry *) (buf + bufcount); switch (de->Name[0]) { case 0x00: /* This, and all subsequent entries are empty */ if (!name) { /* we are looking for a free entry */ *de_sector = sector - 1; *de_offset = bufcount; return 1; } return 0; break; case 0xe5: /* This entry is empty, but there may be more after it */ if (!name) { /* we are looking for a free entry */ *de_sector = sector - 1; *de_offset = bufcount; return 1; } break; case 0x05: /* escaped Kanji character */ de->Name[0] = 0xe5; /* fall through to default case ... */ default: if (!name) /* we are looking for a free entry */ break; /* and this is not it.. */ if ((de->Attributes & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) { /* This is a long file name */ break; } /* Must be a file, directory or volume ID */ switch (de->Attributes & (ATTR_DIRECTORY | ATTR_VOLUME_ID)) { case 0x00: /* This entry is a file */ if (ext) { /* Here if we are looking for a file */ if (!dir_name_compare(name, (char *) (de->Name), 8) && !dir_name_compare(ext, (char *) (de->Extension), 3)) { if (wd->pi->FatType == FAT32) { /* first cluster is a 32 bit entry for FAT32 */ *firstcluster = make_UINT32 (de->FirstClusterOfFile_hi[1], de->FirstClusterOfFile_hi[0], de->FirstClusterOfFile[1], de->FirstClusterOfFile[0]); } else { *firstcluster = (UINT32)make_UINT16 (de->FirstClusterOfFile[1], de->FirstClusterOfFile[0]); } *filesize = make_UINT32(de->FileSize[3], de->FileSize[2], de->FileSize[1], de->FileSize[0]); *de_sector = sector - 1; *de_offset = bufcount; return 1; } } break; case ATTR_DIRECTORY: /* This entry is a directory */ if (ext == 0) { if (!dir_name_compare(name, (char *) (de->Name), 8)) { if (wd->pi->FatType == FAT32) { /* first cluster is a 32 bit entry for FAT32 */ *firstcluster = make_UINT32 (de->FirstClusterOfFile_hi[1], de->FirstClusterOfFile_hi[0], de->FirstClusterOfFile[1], de->FirstClusterOfFile[0]); } else { *firstcluster = (UINT32)make_UINT16 (de->FirstClusterOfFile[1], de->FirstClusterOfFile[0]); } *filesize = make_UINT32(de->FileSize[3], de->FileSize[2], de->FileSize[1], de->FileSize[0]); *de_sector = sector - 1; *de_offset = bufcount; return 1; } } break; case ATTR_VOLUME_ID: /* Volume ID */ break; default: /* Bad directory */ return 0; } } bufcount += DIRENT_SIZE; } } /* Finished with root or current cluster. If this is not the * root, then move to the next cluster. */ /* Root directory (in FAT12/16) has one continuous list of sectors */ if (wd->pi->FatType != FAT32 && wd->parent == 0) return 0; /* If this is a child directory go to next cluster */ cluster = next_cluster(cluster, wd->pi); if (cluster == BAD_CLUSTER) { /* FAT problem ? */ return 0; } if (is_sub_dir) { /* reset filesize to read another clusters worth of directory entries */ filecount = (wd->pi->SectorsPerCluster * SECTORSIZE); } if ((sector = starting_sector(cluster, wd->pi)) == 0) { /* FAT problem ? */ return 0; } nsectors = wd->pi->SectorsPerCluster; } /* while(filesize) */ /* Never found it */ return 0; } void update_de_filesize(DirectoryEntry *de, UINT32 filesize) { write_UINT32(de->FileSize, filesize); } void update_de_firstcluster(DirectoryEntry *de, UINT32 firstcluster, PartitionInfo *pi) { UINT16 f_lo, f_hi; f_lo = (UINT16)(firstcluster & 0xFFFF); f_hi = (UINT16)(firstcluster >> 16); write_UINT16(de->FirstClusterOfFile, f_lo); if (pi->FatType == FAT32) write_UINT16(de->FirstClusterOfFile_hi, f_hi); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_fat.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "directory.h" #include "util.h" /* given a cluster, look into the FAT to find the next * cluster in the link list */ UINT32 next_cluster(UINT32 cluster, PartitionInfo * pi) { if (cluster < 2) return BAD_CLUSTER; return pi->op->next_cluster(cluster, pi); } /* return the first sector corresponding to a cluster */ UINT32 starting_sector(UINT32 cluster, PartitionInfo * pi) { if (cluster == 0) return 0; return (((cluster - 2) * (UINT32) pi->SectorsPerCluster) + pi->DataSector); } /* next_cluster_generic: given a cluster number, return the * cluster that is next in this cluster chain by looking * into the FAT data structure for this partition * * generic for FAT16 & FAT32 */ UINT32 next_cluster_generic(UINT32 cluster, PartitionInfo * pi) { BYTE buf[SECTORSIZE]; UINT32 TempNextCluster; UINT32 Fat0SectorNum; UINT32 Fat1SectorNum; int NextClusterPosition; if (!pi->op->is_valid_cluster(cluster, pi)) return BAD_CLUSTER; Fat0SectorNum = pi->op->get_fat_sector_for_cluster(cluster, pi); NextClusterPosition = pi->op->get_fat_offset_for_cluster(cluster, pi); if (read_sector(Fat0SectorNum, buf) != SECTORSIZE) return BAD_CLUSTER; TempNextCluster = pi->op->get_next_cluster(buf + NextClusterPosition, pi); /* check for FAT misMatch !!! */ if (pi->NumberOfFats > 1) { Fat1SectorNum = Fat0SectorNum + pi->SectorsPerFat; if (read_sector(Fat1SectorNum, buf) != SECTORSIZE) return BAD_CLUSTER; if (TempNextCluster != pi->op->get_next_cluster(buf + NextClusterPosition, pi)) return BAD_CLUSTER; /* FAT tables don't match bail */ } return (TempNextCluster); } /* Follow the cluster chain in FAT16/32 and free all allotted * clusters. */ int free_cluster_chain_generic(UINT32 cluster, PartitionInfo *pi) { UINT32 sector_in_buf = 0; UINT32 sector, offset; int modified = 0; /* denotes if the sector_in_buf has been modified */ char buf[SECTORSIZE]; while (!pi->op->is_eoc(cluster, pi)) { sector = pi->op->get_fat_sector_for_cluster(cluster, pi); if (sector != sector_in_buf) { /* have to read in a new sector from FAT */ /* write to disk if the old sector was modified */ if (modified) { if (write_sector(sector_in_buf, buf) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf) != SECTORSIZE) return -1; modified = 0; } /* read in the new sector */ if (read_sector(sector, buf) != SECTORSIZE) return -1; sector_in_buf = sector; } offset = pi->op->get_fat_offset_for_cluster(cluster, pi); /* obtain the current value & reset it to zero */ cluster = pi->op->get_next_cluster(buf + offset, pi); pi->op->set_next_cluster(buf + offset, 0, pi); modified = 1; } if (modified) { if (write_sector(sector_in_buf, buf) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf) != SECTORSIZE) return -1; modified = 0; } return 0; } /* truncate a file to size 0: done by following the cluster chain * and freeing all allotted clsuters for this file */ int truncate_file(UINT32 cluster, PartitionInfo *pi) { if (cluster < 2) return -1; return pi->op->free_cluster_chain(cluster, pi); } /* find a free cluster, set the next entry of that cluster to EOC * and return that cluster. * A request to allocate_one_cluster automatically sets the entry * in FAT for that cluster to point to EOC. This is because we want * to reduce the # of read and write calls to the disk */ UINT32 allocate_one_cluster_generic(PartitionInfo *pi) { BYTE buf[SECTORSIZE]; int FatEntrySize; UINT32 cluster = 0, sector, i; UINT32 eoc; if (pi->FatType == FAT16) { FatEntrySize = 2; eoc = FAT16_EOC; } else if (pi->FatType == FAT32) { FatEntrySize = 4; eoc = FAT32_EOC; } else { /* works only for FAT16/32 */ return 0; } for (sector = pi->FatSector; sector < pi->FatSector + pi->SectorsPerFat; sector++) { /* read in the sector */ if (read_sector(sector, buf) != SECTORSIZE) return 0; /* find if an entry is free */ for (i = 0; i < SECTORSIZE; i+= FatEntrySize) { UINT32 cluster_val = pi->op->get_next_cluster(buf + i, pi); if (cluster_val == 0) { /* this cluster is free */ BYTE buf2[SECTORSIZE]; UINT32 cluster_val_2; if (read_sector(sector + pi->SectorsPerFat, buf2) != SECTORSIZE) return 0; cluster_val_2 = pi->op->get_next_cluster(buf2 + i, pi); if (cluster_val_2 != cluster_val) return 0; /* FAT mismatch */ /* write EOC as the entry for this cluster * in both the FATs */ pi->op->set_next_cluster(buf2 + i, eoc, pi); if (write_sector(sector + pi->SectorsPerFat, buf2) != SECTORSIZE) return 0; pi->op->set_next_cluster(buf + i, eoc, pi); if (write_sector(sector, buf) != SECTORSIZE) return 0; return cluster; } cluster++; } } return 0; } int link_cluster_generic(UINT32 from_cluster, UINT32 to_cluster, PartitionInfo *pi) { UINT32 sector = pi->op->get_fat_sector_for_cluster(from_cluster, pi); UINT32 offset = pi->op->get_fat_offset_for_cluster(from_cluster, pi); BYTE buf[SECTORSIZE]; if (read_sector(sector, buf) != SECTORSIZE) return -1; /* set the next cluster for from_cluster to to_cluster */ pi->op->set_next_cluster(buf + offset, to_cluster, pi); if (write_sector(sector, buf) != SECTORSIZE) return -1; return 0; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat12.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat12.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_fat12.c =================================================================== ///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. ///////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "directory.h" #include "util.h" /* given the cluster #, find the sector in the partition where * the FAT entry for that cluster is present */ UINT32 get_fat12_sector_for_cluster(UINT32 cluster, PartitionInfo *pi) { /* Each FAT entry takes 1.5 bytes in FAT 12 */ return ((cluster + cluster/2) / SECTORSIZE) + pi->FatSector; } /* given the cluster #, find the offset in the sector in the partition where * the FAT entry for that cluster is present */ UINT32 get_fat12_offset_for_cluster(UINT32 cluster, PartitionInfo *pi) { return ((cluster + cluster/2) % SECTORSIZE); } /* given the address (fat_entry) where the FAT entry for a cluster * is present, return the next cluster for that entry */ UINT32 get_next_cluster_fat12(BYTE *fat_entry, PartitionInfo *pi, UINT32 cluster) { UINT32 tmp_next_cluster; /* We need 12 bits from the 2 bytes - so first read in the 2 bytes */ tmp_next_cluster = (UINT32) make_UINT16(*(fat_entry + 1), *(fat_entry)); if (cluster & 0x1) /* if cluster is odd, we take the higher 12 bits */ tmp_next_cluster >>= 4; else /* else we take the lower 12 bits */ tmp_next_cluster &= 0xFFF; return tmp_next_cluster; } /* given the address (fat_entry) where the FAT entry for a cluster * is present, set the next cluster entry to next_cluster */ void set_next_cluster_fat12(BYTE *fat_entry, UINT32 next_cluster, PartitionInfo *pi, UINT32 cluster) { UINT16 old_entry = make_UINT16(*(fat_entry+1), *(fat_entry)); UINT32 new_entry; if (cluster & 0x1) { /* if cluster is odd, we need to update the higher 12 bits */ new_entry = (next_cluster << 4) | (old_entry & 0xF); write_UINT16(fat_entry, new_entry); } else { /* else write the lower order 12 bits */ new_entry = (next_cluster & 0xFFF) | (old_entry & 0xF000); write_UINT16(fat_entry, new_entry); } } /* find if this is the end of cluster mark */ int is_eoc_fat12(UINT32 cluster, PartitionInfo *pi) { return (cluster >= FAT12_EOC); } int is_valid_cluster_fat12(UINT32 cluster, PartitionInfo *pi) { return (cluster < MAX_FAT12_CLUSTERS); } /* next_cluster_fat12: given a cluster number, return the * cluster that is next in this cluster chain by looking * into the FAT data structure for this partition * * For FAT12, each entry in the FAT is 1.5 bytes = 12 bits. * This results in two complications: * 1. A single FAT entry may span two sectors. * 2. After reading in 16 bits, 12 bits must be extracted * depending on whether the cluster # is even or odd. */ UINT32 next_cluster_fat12(UINT32 cluster, PartitionInfo * pi) { BYTE buf[SECTORSIZE*2]; UINT32 TempNextCluster; UINT32 Fat0SectorNum; UINT32 Fat1SectorNum; int NextClusterPosition; if (cluster > MAX_FAT12_CLUSTERS) return BAD_CLUSTER; Fat0SectorNum = pi->op->get_fat_sector_for_cluster(cluster, pi); NextClusterPosition = pi->op->get_fat_offset_for_cluster(cluster, pi); if (read_sector(Fat0SectorNum, buf) != SECTORSIZE) return BAD_CLUSTER; /* Additionally (as compared to FAT 16/32 we have to see if the entry * spans a sector boundary, and if so read in the next sector. */ if (NextClusterPosition == SECTORSIZE - 1) if (read_sector(Fat0SectorNum + 1, buf + SECTORSIZE) != SECTORSIZE) return BAD_CLUSTER; TempNextCluster = get_next_cluster_fat12(buf + NextClusterPosition, pi, cluster); /* check for FAT misMatch !!! */ if (pi->NumberOfFats > 1) { UINT32 FAT1_TempNextCluster = 0; Fat1SectorNum = Fat0SectorNum + pi->SectorsPerFat; if (read_sector(Fat1SectorNum, buf) != SECTORSIZE) return 0; if (NextClusterPosition == SECTORSIZE - 1) if (read_sector(Fat0SectorNum + 1, buf + SECTORSIZE) != SECTORSIZE) return BAD_CLUSTER; FAT1_TempNextCluster = get_next_cluster_fat12(buf + NextClusterPosition, pi, cluster); if (TempNextCluster != FAT1_TempNextCluster) return BAD_CLUSTER; /* FAT tables don't match bail */ } return (TempNextCluster); } /* Follow the cluster chain in FAT12 and free all allotted clusters. */ int free_cluster_chain_fat12(UINT32 cluster, PartitionInfo *pi) { UINT32 sector_in_buf = 0; UINT32 sector, offset, old_cluster; int modified = 0; /* denotes if the sector_in_buf has been modified */ int used_second_sector = 0; /* denotes if a 2nd sector was read & modified */ char buf[SECTORSIZE*2]; while (!pi->op->is_eoc(cluster, pi)) { sector = pi->op->get_fat_sector_for_cluster(cluster, pi); debug_xil_printf("%d: cluster: %d is at sector: %d\n\r", __LINE__, (int)cluster, (int)sector); if (sector != sector_in_buf) { /* have to read in a new sector from FAT */ /* write to disk if the old sector was modified */ if (modified) { if (write_sector(sector_in_buf, buf) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf) != SECTORSIZE) return -1; /* if the writes had spanned 2 sectors, then write out * the 2nd sector too */ if (used_second_sector) { if (write_sector(sector_in_buf, buf + SECTORSIZE) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf + SECTORSIZE) != SECTORSIZE) return -1; used_second_sector = 0; } debug_xil_printf("written modified sec %d\n", (unsigned int)sector_in_buf); modified = 0; } debug_xil_printf("%s @ %d, reading in new sector\n\r", __FUNCTION__, __LINE__); /* read in the new sector */ if (read_sector(sector, buf) != SECTORSIZE) return -1; sector_in_buf = sector; } offset = pi->op->get_fat_offset_for_cluster(cluster, pi); if (offset == SECTORSIZE - 1) { /* FAT entry spans sector boundary */ if (read_sector(sector, buf + SECTORSIZE) != SECTORSIZE) return 0; used_second_sector = 1; } /* obtain the current value & reset it to zero */ old_cluster = cluster; cluster = get_next_cluster_fat12(buf + offset, pi, cluster); set_next_cluster_fat12(buf + offset, 0, pi, old_cluster); modified = 1; } if (modified) { if (write_sector(sector_in_buf, buf) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf) != SECTORSIZE) return -1; /* if the writes had spanned 2 sectors, then write out * the 2nd sector too */ if (used_second_sector) { if (write_sector(sector_in_buf, buf + SECTORSIZE) != SECTORSIZE) return -1; /* update FAT 2 */ if (pi->NumberOfFats > 1) if (write_sector(sector_in_buf + pi->SectorsPerFat, buf + SECTORSIZE) != SECTORSIZE) return -1; used_second_sector = 0; } debug_xil_printf("written modified sec %d\n", (unsigned int)sector_in_buf); modified = 0; } return 0; } int link_cluster_fat12(UINT32 from_cluster, UINT32 to_cluster, PartitionInfo *pi) { UINT32 sector = pi->op->get_fat_sector_for_cluster(from_cluster, pi); UINT32 offset = pi->op->get_fat_offset_for_cluster(from_cluster, pi); BYTE buf[SECTORSIZE*2]; if (read_sector(sector, buf) != SECTORSIZE) return -1; if (offset == SECTORSIZE - 1) { /* read in next sector if this FAT entry spans two sectors */ if (read_sector(sector + 1, buf + SECTORSIZE) != SECTORSIZE) return -1; } /* set the next cluster for from_cluster to to_cluster */ set_next_cluster_fat12(buf + offset, to_cluster, pi, from_cluster); if (write_sector(sector, buf) != SECTORSIZE) return -1; if (offset == SECTORSIZE - 1) if (write_sector(sector + 1, buf + SECTORSIZE) != SECTORSIZE) return -1; /* update 2nd FAT if present */ if (pi->NumberOfFats > 1) { if (write_sector(sector + pi->SectorsPerFat, buf) != SECTORSIZE) return -1; if (offset == SECTORSIZE - 1) if (write_sector(sector + 1 + pi->SectorsPerFat, buf + SECTORSIZE) != SECTORSIZE) return -1; } return 0; } /* find a free cluster, set the next entry of that cluster to EOC * and return that cluster. */ UINT32 allocate_one_cluster_fat12(PartitionInfo *pi) { UINT32 cluster = 0; for (cluster = 2; cluster < (pi->TotalSectors/pi->SectorsPerCluster); cluster++) if (next_cluster(cluster, pi) == 0) { link_cluster_fat12(cluster, FAT12_EOC, pi); return cluster; } return 0; } fat_ops fat12_ops = { get_fat12_sector_for_cluster, get_fat12_offset_for_cluster, 0, 0, is_eoc_fat12, is_valid_cluster_fat12, next_cluster_fat12, free_cluster_chain_fat12, allocate_one_cluster_fat12, link_cluster_fat12, }; 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat16.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat16.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_fat16.c =================================================================== ///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. ///////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "directory.h" #include "util.h" UINT32 get_fat16_sector_for_cluster(UINT32 cluster, PartitionInfo *pi) { /* Each FAT entry takes 2 bytes in FAT 16 */ return ((cluster * 2) / SECTORSIZE) + pi->FatSector; } UINT32 get_fat16_offset_for_cluster(UINT32 cluster, PartitionInfo *pi) { /* Each FAT entry takes 2 bytes in FAT 16 */ return ((cluster * 2) % SECTORSIZE); } UINT32 get_next_cluster_fat16(BYTE *fat_entry, PartitionInfo *pi) { return (UINT32)(0xffff & make_UINT16(*(fat_entry + 1), *(fat_entry))); } void set_next_cluster_fat16(BYTE *fat_entry, UINT32 next_cluster, PartitionInfo *pi) { write_UINT16(fat_entry, next_cluster); } int is_eoc_fat16(UINT32 cluster, PartitionInfo *pi) { return (cluster >= FAT16_EOC); } int is_valid_cluster_fat16(UINT32 cluster, PartitionInfo *pi) { return (cluster < MAX_FAT16_CLUSTERS); } fat_ops fat16_ops = { get_fat16_sector_for_cluster, get_fat16_offset_for_cluster, get_next_cluster_fat16, set_next_cluster_fat16, is_eoc_fat16, is_valid_cluster_fat16, next_cluster_generic, free_cluster_chain_generic, allocate_one_cluster_generic, link_cluster_generic, }; 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat32.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_fat32.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_fat32.c =================================================================== ///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. ///////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "directory.h" #include "util.h" /* given the cluster #, find the sector in the partition where * the FAT entry for that cluster is present */ UINT32 get_fat32_sector_for_cluster(UINT32 cluster, PartitionInfo *pi) { /* Each FAT entry takes 4 bytes in FAT 32 */ return ((cluster * 4) / SECTORSIZE) + pi->FatSector; } UINT32 get_fat32_offset_for_cluster(UINT32 cluster, PartitionInfo *pi) { /* Each FAT entry takes 4 bytes in FAT 32 */ return ((cluster * 4) % SECTORSIZE); } UINT32 get_next_cluster_fat32(BYTE *fat_entry, PartitionInfo *pi) { return 0x0FFFFFFF & make_UINT32(*(fat_entry + 3), *(fat_entry + 2), *(fat_entry + 1), *(fat_entry)); } void set_next_cluster_fat32(BYTE *fat_entry, UINT32 next_cluster, PartitionInfo *pi) { UINT32 old_entry; /* extract the higher order 4 bits from old entry */ old_entry = 0xf0000000 & make_UINT32(*(fat_entry + 3), *(fat_entry + 2), *(fat_entry + 1), *(fat_entry)); next_cluster &= 0x0fffffff; next_cluster |= old_entry; write_UINT32(fat_entry, next_cluster); } int is_eoc_fat32(UINT32 cluster, PartitionInfo *pi) { return (cluster >= FAT32_EOC); } int is_valid_cluster_fat32(UINT32 cluster, PartitionInfo *pi) { return (cluster < MAX_FAT32_CLUSTERS); } fat_ops fat32_ops = { get_fat32_sector_for_cluster, get_fat32_offset_for_cluster, get_next_cluster_fat32, set_next_cluster_fat32, is_eoc_fat32, is_valid_cluster_fat32, next_cluster_generic, free_cluster_chain_generic, allocate_one_cluster_generic, link_cluster_generic, }; 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_filespec.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_filespec.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_filespec.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <ctype.h> #include "filespec.h" /* Routines to parse out path names. The only characters that are * checked for are \ (backslash), . (period) and : (colon). The * rest are treated as valid characters for names. * * Examine path to see if it starts with a directory name. * If so, copy it to buf and return number of characters * consumed. If buf is too short, 0 is returned. The is_dir * flags says that we expect this to be a directory specifier, i.e. * a trailing name with no file extension is a directory name, * not a file name. The root flag says that this might be the root * directory, i.e if it starts with backslash, return just that. */ static int find_dir(const char *path, char *buf, int length, int is_dir, int root) { int i = 0; int relative = 0; if (root && path[0] == DIRSEPCHAR) { /* This is the root */ if (length < 2) return 0; buf[0] = DIRSEPCHAR; buf[1] = 0; return 1; } while (i < length) { if (path[i] == 0) { /* End of string - could be a directory or a file * name that has no extension */ if (is_dir) { /* Last field is a directory */ buf[i] = 0; return i; } else { /* Last field is a file */ return 0; } } if (path[i] == DIRSEPCHAR) { if (i > 0) { /* hierarchy separator */ buf[i] = 0; return i + 1; /* eat the directory separator too */ } else return 0; } /* Look for bad characters */ if (path[i] == '.') { if (i == 0) relative = 1; else if (i > 1 || !relative) return 0; } if (path[i] == ':') return 0; /* Keep copying - so far so good */ buf[i] = path[i]; ++i; } /* Never found the end of this name */ return 0; } /* Examine path to see if it starts with a device spec. * If so, copy it to buf and return the number of chars * consumed. If buf is too short, 0 is returned. * Device spec can be a DOS style (e.g. a:) or network * style (e.g. \\server). */ static int find_device(const char *path, char *buf, int length) { char c; int i; /* look for server form */ if (path[0] == DIRSEPCHAR && path[1] == DIRSEPCHAR) { /* Find the server name - it looks just like a directory name */ i = 0; while (i < length) { if (path[i + 2] == 0 || path[i + 2] == DIRSEPCHAR) { /* hit end of server name */ buf[i] = 0; return i + 2; /* eat the double backslash too */ } /* Watch for illegal characters */ if (path[i + 2] == '.' || path[i + 2] == ':') return 0; buf[i] = path[i + 2]; ++i; } return 0; } /* Must be a plain old DOS disk (letter colon) */ if (length < 2 || path[0] == 0 || path[1] != ':') return 0; c = tolower(path[0]); if (c < 'a' || c > 'z') return 0; /* It was a device */ buf[0] = c; buf[1] = 0; return 2; } /* Examine path to see if it starts with a file name. * If so, copy it to buf and return number of characters * consumed. If buf is too short, 0 is returned. The is_dir * flags says that we expect this to be a directory specifier, i.e. * a trailing name with no file extension is a directory name, * not a file name. */ static int find_file(const char *path, char *buf, int length, int is_dir) { int i = 0; /* Do not apply file name rules if this is known to be a directory path */ if (is_dir) return 0; while (i < length) { if (path[i] == 0) { /* End of string - file has no extension */ buf[i] = 0; return i; } if (path[i] == '.') { /* Hit the file extension */ buf[i] = 0; return i; } /* Look for bad characters */ if (path[i] == DIRSEPCHAR || path[i] == ':') return 0; /* Keep copying - so far so good */ buf[i] = path[i]; ++i; } /* Never found the end of this name */ return 0; } static int find_ext(const char *path, char *buf, int length) { int i = 0; /* Must start with a dot */ if (path[0] != '.') return 0; while (i < length) { /* 3 character max */ if (i > 3) return 0; if (path[i + 1] == 0) { buf[i] = 0; return i + 1; } /* Look for bad characters */ if (path[i + 1] == '.' || path[i + 1] == DIRSEPCHAR || path[i + 1] == ':') return 0; /* Keep copying - so far so good */ buf[i] = path[i + 1]; ++i; } /* Never found the end of this name */ return 0; } /* Find the next field in the path. Returns the number of characters * consumed by this field. The field type pointed to by type should * Be set initially to 'START' and will be updated after the field * has been found. The identified field will be stored in buf (up to l * characters) - if it does not fit, there will be an error. * The flag is_dir says that the path is a directory path, i.e. the * last field will be treated as a directory, not a file with no * extension. */ int parse_path(const char *path, char *buf, int length, int is_dir, field_type * type) { int i = 0; switch (*type) { case PATH_START: /* String cannot be empty */ if (*path == 0) { *type = PATH_ERROR; break; } /* Can start with device, directory or file */ if ((i = find_device(path, buf, length)) > 0) *type = DEVICE_NAME; else if ((i = find_dir(path, buf, length, is_dir, 1)) > 0) *type = DIR_NAME; else if ((i = find_file(path, buf, length, is_dir)) > 0) *type = FILE_NAME; else *type = PATH_ERROR; break; case DEVICE_NAME: /* String cannot be empty if we are looking for a file name */ if (*path == 0) { if (!is_dir) *type = PATH_ERROR; else *type = PATH_DONE; break; } /* Device can be followed by directory or file */ if ((i = find_dir(path, buf, length, is_dir, 1)) > 0) *type = DIR_NAME; else if ((i = find_file(path, buf, length, is_dir)) > 0) *type = FILE_NAME; else *type = PATH_ERROR; break; case DIR_NAME: /* String cannot be empty if we are looking for a file name */ if (*path == 0) { if (!is_dir) *type = PATH_ERROR; else *type = PATH_DONE; break; } /* Directory can be followed by directory or file */ if ((i = find_dir(path, buf, length, is_dir, 0)) > 0) *type = DIR_NAME; else if ((i = find_file(path, buf, length, is_dir)) > 0) *type = FILE_NAME; else *type = PATH_ERROR; break; case FILE_NAME: if (*path == 0) *type = PATH_DONE; else if ((i = find_ext(path, buf, length)) > 0) *type = FILE_EXT; else *type = PATH_ERROR; break; case FILE_EXT: if (*path == 0) *type = PATH_DONE; else *type = PATH_ERROR; break; default: *type = PATH_ERROR; break; } return i; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_filestatus.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_filestatus.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_filestatus.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "filestatus.h" #include "alloc.h" /* global static for linked list start pointer */ static FileStatus *FileListHead = 0; /* find the filestatus corresponding to a given stream */ FileStatus *find_file_status(SYSACE_FILE *stream) { FileStatus *fs; for (fs = FileListHead; fs; fs = fs->next) if (fs == stream) return fs; return 0; } /* Create a new FILEINFO and add to list. * Fail if file is already open for write */ FileStatus *create_file_status(WorkingDirectory * wd, BYTE read, BYTE write) { FileStatus *ps; /* See it this file is already opened */ for (ps = FileListHead; ps; ps = ps->next) { if (ps->wd->v.child.FirstCluster == wd->v.child.FirstCluster && (write || ps->write)) return 0; } if ((ps = malloc_fs()) == 0) return 0; ps->wd = wd; ps->read = read; ps->write = write; ps->CurrentCluster = wd->v.child.FirstCluster; ps->PositionInCluster = 0; ps->PositionInFile = 0; ps->next = FileListHead; FileListHead = ps; return ps; } int delete_file_status(FileStatus * status) { FileStatus *ps; /* First unlink this item */ if (FileListHead == status) { /* It's the first item, just step over it */ FileListHead = status->next; } else { /* It's further down the list - keep looking */ for (ps = FileListHead; ps; ps = ps->next) { if (ps->next == status) { /* found it - remove from list */ ps->next = status->next; /* Stop search */ break; } } if (ps == 0) { /* Went through whole list and it wasn't there!! */ return -1; } } delete_working_directory_stack(status->wd); free_fs(status); return 0; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_mkdir.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_mkdir.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_mkdir.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "fat.h" #include "filespec.h" #include "directory.h" #include "util.h" DirectoryEntry dotdot_entry[2]; int sysace_mkdir(const char *path) { WorkingDirectory *wd = build_working_directory_stack(path, 1, 1); if (wd) { /* create dir succeeded */ delete_working_directory_stack(wd); sync_bufcache(); return 0; } else return -1; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_open.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_open.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_open.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <string.h> #include "sysace_stdio.h" #include "fat.h" #include "filestatus.h" SYSACE_FILE *sysace_fopen(const char *file, const char *mode) { BYTE read = 0; BYTE write = 0; WorkingDirectory *wd; FileStatus *ps; /* only "r" and "w" modes are supported */ if (!strcmp(mode, "r")) read = 1; else if (!strcmp(mode, "w")) write = 1; else return 0; /* create a working directory stack for the file */ if ((wd = build_working_directory_stack(file, 0, write)) == 0) return 0; if ((ps = create_file_status(wd, read, write)) == 0) { delete_working_directory_stack(wd); return 0; } return (SYSACE_FILE *) ps; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_part.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_part.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_part.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <ctype.h> #include <string.h> #include "fat.h" #include "directory.h" #include "util.h" /* The partition info buffers can be statically allocated. * Never free a pi ! */ static PartitionInfo pibuf[MAXPARTITION]; /* Make a new PartitionInfo structure and populate it */ PartitionInfo *get_partition_info(int partition) { BYTE buf[SECTORSIZE]; MasterBootRecord *mbr; PartitionEntry *pe; PartitionBootRecord *pbr; UINT16 total16; UINT32 total32; UINT16 reserved; UINT32 partitionSize, rootSize, dataClusters, dataOffset, fatSize; PartitionInfo *pi; static int sysace_initialized = 0; if (partition < 0 || partition >= MAXPARTITION) return 0; pi = pibuf + partition; pi->PartitionNum = partition; if (!sysace_initialized) { /* initialize sysace the first time around */ if (init_ace() < 0) return 0; sysace_initialized = 1; } /* Master Boot Record is always sector 0 */ if (read_sector(0, buf) != SECTORSIZE) return 0; mbr = (MasterBootRecord *) buf; /* Check Signature */ if (mbr->Signature[0] != 0x55 || mbr->Signature[1] != 0xaa) return 0; /* Point to the Relevant Partition Entry */ pe = &(mbr->PartitionEntry[partition]); pi->StartSector = make_UINT32(pe->PartitionSector[3], pe->PartitionSector[2], pe->PartitionSector[1], pe->PartitionSector[0]); partitionSize = make_UINT32(pe->TotalSectors[3], pe->TotalSectors[2], pe->TotalSectors[1], pe->TotalSectors[0]); /* Read the Partition Boot Record */ if (read_sector(pi->StartSector, buf) != SECTORSIZE) return 0; pbr = (PartitionBootRecord *) buf; /* Determine the total number of sectors in this partition * It may be specified in 16 or 32 bits */ total16 = make_UINT16(pbr->BPB.TotalSectors16[1], pbr->BPB.TotalSectors16[0]); total32 = make_UINT32(pbr->BPB.TotalSectors32[3], pbr->BPB.TotalSectors32[2], pbr->BPB.TotalSectors32[1], pbr->BPB.TotalSectors32[0]); if (total16) { if (total32 != 0 && total32 != total16) return 0; pi->TotalSectors = (UINT32) total16; } else { if (total32 == 0) return 0; pi->TotalSectors = total32; } if (pi->TotalSectors > partitionSize) return 0; pi->BytesPerSector = make_UINT16(pbr->BPB.BytesPerSector[1], pbr->BPB.BytesPerSector[0]); /* Check against compile-time constants * currently allow only 512 bytes per sec */ if (pi->BytesPerSector != SECTORSIZE) return 0; pi->SectorsPerCluster = pbr->BPB.SectorsPerCluster; if (pi->SectorsPerCluster == 0) { /* Protect division later on! */ return 0; } /* sanity check for SectorsPerCluster: * should be a power of 2 * should be <= 128 * should be such that bytes per cluster <= 32k (MAX_BYTES_PER_CLUSTER) */ if (pi->SectorsPerCluster & (pi->SectorsPerCluster - 1)) return 0; if (pi->SectorsPerCluster > 128) return 0; if (pi->SectorsPerCluster * pi->BytesPerSector > MAX_BYTES_PER_CLUSTER) return 0; reserved = make_UINT16(pbr->BPB.ReservedSector[1], pbr->BPB.ReservedSector[0]); pi->NumberOfFats = pbr->BPB.NumberOfFats; pi->RootDirCount = make_UINT16(pbr->BPB.RootDirCount[1], pbr->BPB.RootDirCount[0]); pi->SectorsPerFat = (UINT32) make_UINT16(pbr->BPB.SectorsPerFat[1], pbr->BPB.SectorsPerFat[0]); if (pi->SectorsPerFat == 0) { /* check if the fat32 entry is present * if not then this is invalid FAT */ pi->SectorsPerFat = make_UINT32(pbr->BPB.SectorsPerFat_32[3], pbr->BPB.SectorsPerFat_32[2], pbr->BPB.SectorsPerFat_32[1], pbr->BPB.SectorsPerFat_32[0]); if (pi->SectorsPerFat == 0) return 0; } /* Determine the FAT type based on the # of data clusters */ rootSize = ((pi->RootDirCount << LOG2_DIRENT_SIZE) + SECTORSIZE - 1) / SECTORSIZE; fatSize = pi->SectorsPerFat * pi->NumberOfFats; dataOffset = reserved + fatSize + rootSize; dataClusters = (pi->TotalSectors - dataOffset) / pi->SectorsPerCluster; if (dataClusters < MAX_FAT12_CLUSTERS) { debug_print("FAT12 PARTITION\n\r"); pi->FatType = FAT12; #ifdef CONFIG_FAT12 pi->op = &fat12_ops; #else pi->op = NULL; #endif } else if (dataClusters < MAX_FAT16_CLUSTERS) { debug_print("FAT16 PARTITION\n\r"); pi->FatType = FAT16; pi->op = &fat16_ops; } else { pi->FatType = FAT32; debug_print("FaT32 PARTITION\n\r"); pi->op = &fat32_ops; } /* more consistency checks */ switch (pi->FatType) { case FAT12: case FAT16: if (reserved != 1) return 0; /* pi->RootDirCount * 32 should be an even multiple * of BytesPerSector */ if ((pi->RootDirCount * 32) % pi->BytesPerSector) return 0; if (((pi->RootDirCount * 32) / pi->BytesPerSector) % 2) return 0; break; case FAT32: if (pi->RootDirCount != 0) return 0; break; default: return 0; } pi->FatSector = pi->StartSector + reserved; pi->RootDirSector = pi->FatSector + fatSize; pi->DataSector = pi->RootDirSector + rootSize; if (pi->FatType == FAT32) { pi->RootCluster = make_UINT32(pbr->BPB.RootCluster[3], pbr->BPB.RootCluster[2], pbr->BPB.RootCluster[1], pbr->BPB.RootCluster[0]); } return pi; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_read.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_read.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_read.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <string.h> #include "filestatus.h" #include "sysace_stdio.h" #include "fat.h" #if defined( DUMMY_DISK ) static char *dummy_data = "Are we there yet?\n"; #endif int read_from_file(FileStatus * fs, char *buf, int count) { int readcount, n; int remaining; BYTE sectorbuf[SECTORSIZE]; UINT32 sector; UINT32 filesize; UINT32 nsectors; UINT32 sector_offset; int byte_offset; /* Safety check */ if (fs == 0 || !fs->read || count < 0) return 0; filesize = fs->wd->v.child.FileSize; if (fs->PositionInFile >= filesize) return 0; readcount = 0; /* Compute number of bytes left to read - may be limited * by size of users buf or by file size */ remaining = filesize - fs->PositionInFile; if (count < remaining) remaining = count; while (fs->PositionInFile < filesize) { /* Which sector of this cluster did we leave off at last time ? */ sector_offset = fs->PositionInCluster / SECTORSIZE; /* Which byte of that sector did we leave off at last time ? */ byte_offset = fs->PositionInCluster % SECTORSIZE; /* Sector address to start reading this time */ sector = starting_sector(fs->CurrentCluster, fs->wd->pi); if (sector == 0) { /* FAT problem ? */ return 0; } sector += sector_offset; /* How many sectors left to read in this cluster */ nsectors = fs->wd->pi->SectorsPerCluster - sector_offset; while (nsectors) { if (read_sector(sector, sectorbuf) != SECTORSIZE) return -1; if (remaining <= (SECTORSIZE - byte_offset)) { /* End of file or end of buffer occurs in this sector * Read what's left and quit */ memcpy(buf + readcount, (char *) (sectorbuf + byte_offset), remaining); fs->PositionInFile += remaining; fs->PositionInCluster += remaining; return (remaining + readcount); } /* End of file is beyond this sector */ n = SECTORSIZE - byte_offset; memcpy(buf + readcount, (char *) (sectorbuf + byte_offset), n); fs->PositionInFile += n; fs->PositionInCluster += n; readcount += n; remaining -= n; /* Point to start of next sector in cluster */ byte_offset = 0; sector += 1; nsectors -= 1; } /* end of while */ /* Done with that cluster, advance to the next one */ fs->CurrentCluster = next_cluster(fs->CurrentCluster, fs->wd->pi); if (fs->CurrentCluster == BAD_CLUSTER) { /* Bad cluster address - this means that there is a FAT problem, * because we should have dtected that this was the last cluster * based on filesize. The file system is hosed. */ return 0; } /* We are at the start of this new cluster */ fs->PositionInCluster = 0; } return readcount; } int sysace_fread(void *buffer, int size, int count, SYSACE_FILE *stream) { FileStatus *fs = find_file_status(stream); if (fs == 0) return -1; return read_from_file(fs, (char *) buffer, size * count); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_readdisk.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_readdisk.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_readdisk.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// /* All functions have been moved to other files */ 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_standalone-utils.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_standalone-utils.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_standalone-utils.c =================================================================== ///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. ///////////////////////////////////////////////////////////////////////////// /* Define the same functions present in sysace.c & sysace_stdio.c * only these now work on a file (virtualized disk) rather than * the compact flash */ #include <stdio.h> #include <sysace.h> /* pointer to the virtual disk */ FILE *disk_fp; char *diskpath = "../cfdisk"; int init_ace() { disk_fp = fopen(diskpath, "r+"); if (!disk_fp) { printf("%s: Error opening virtual disk: %s\n", __FUNCTION__, diskpath); return -1; } return 0; } int read_sector(UINT32 sector, BYTE *sector_buf) { /* fseek to the correct position & return the sector */ if (fseek(disk_fp, sector * SECTORSIZE, SEEK_SET) < 0) { printf("error while seeking..\n"); return -1; } return fread(sector_buf, 1, SECTORSIZE, disk_fp); } int write_sector(UINT32 sector, BYTE *sector_buf) { /* fseek to the correct position & write the sector */ if (fseek(disk_fp, sector * SECTORSIZE, SEEK_SET) < 0) { printf("error while seeking..\n"); return -1; } return fwrite(sector_buf, 1, SECTORSIZE, disk_fp); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_stats.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_stats.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_stats.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <stdio.h> #include "stats.h" #include "util.h" unsigned int xilfatfs_stats_read; unsigned int xilfatfs_stats_write; void init_xilfatfs_stats() { xilfatfs_stats_read = 0; xilfatfs_stats_write = 0; } void dump_xilfatfs_stats() { xil_printf("# of sysace reads: %d\n\r", xilfatfs_stats_read); xil_printf("# of sysace writes: %d\n\r", xilfatfs_stats_write); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_sysace.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_sysace.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_sysace.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include "xparameters.h" #include "sysace.h" #include "xsysace_l.h" #include "xsysace.h" #include "xstatus.h" #include "xbasic_types.h" #include "xio.h" #include "bufcache.h" #include "stats.h" static Xuint32 sysace_base_addr = 0; int read_sector_cf(UINT32 sector, BYTE *pSectorBuffer) { xilfatfs_stats_read++; return XSysAce_ReadSector(sysace_base_addr, sector, pSectorBuffer); } int write_sector_cf(UINT32 sector, BYTE *pSectorBuffer) { xilfatfs_stats_write++; return XSysAce_WriteSector(sysace_base_addr, sector, pSectorBuffer); } /***** initalize system ace for reading and writing *****/ int init_ace() { XSysAce Ace; XStatus Result; XStatus status_init; /* This code assumes only one systemace interface in the build and its Device ID is 0*/ status_init = XSysAce_Initialize(&Ace, 0); sysace_base_addr = Ace.BaseAddress; while ((Result = XSysAce_Lock(&Ace, XFALSE)) != XST_SUCCESS) ; XSysAce_RegWrite32(sysace_base_addr + XSA_CR_OFFSET, XSA_CR_FORCECFGMODE_MASK); init_bufcache(write_sector_cf); return (int) (status_init); } int read_sector(UINT32 sector, BYTE *sector_buf) { if (is_buffered(sector) < 0) { /* sector not buffered */ int n = read_sector_cf(sector, sector_buf); if (n == SECTORSIZE) { /* if valid data read */ if (update_bufcache(sector, sector_buf, 0) < 0) return -1; } return n; } else { /* sector already present in buffer */ return read_bufcache(sector, sector_buf); } } int write_sector(UINT32 sector, BYTE *sector_buf) { return update_bufcache(sector, sector_buf, 1); } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_sysace_stdio.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_sysace_stdio.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_sysace_stdio.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// /* All functions have been moved to other files */ 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_wd.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_wd.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_wd.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <ctype.h> #include <string.h> #include "fat.h" #include "filespec.h" #include "alloc.h" #include "directory.h" #include "util.h" /* Defaults to all zeros */ WorkingDirectory *cwd[MAXPARTITION] = { 0 }; int DefaultPartition = 0; void delete_working_directory_stack(WorkingDirectory * wd) { WorkingDirectory *parent; while (wd) { parent = wd->parent; free_wd(wd); wd = parent; } return; } #define WD_BUFSIZE 10 #define WD_EXT_BUFSIZE 5 WorkingDirectory *_build_working_directory_stack(const char *path, int is_dir, int create) { char buf[WD_BUFSIZE]; char ext_buf[WD_EXT_BUFSIZE]; field_type type = PATH_START; WorkingDirectory *wd = 0; WorkingDirectory *child; int i = 0; int partition = DefaultPartition; #if defined(CONFIG_WRITE) && defined(CONFIG_DIR_SUPPORT) char leaf_buf[WD_BUFSIZE]; #endif while (type != PATH_DONE) { i += parse_path(path + i, buf, WD_BUFSIZE, is_dir, &type); switch (type) { case DEVICE_NAME: /* Cannot support server spec */ if (strlen(buf) > 1) { delete_working_directory_stack(wd); return 0; } /* interpret drive letter */ if ((partition = tolower(buf[0]) - 'a') < 0 || partition >= MAXPARTITION) { delete_working_directory_stack(wd); return 0; } break; case DIR_NAME: if (wd == 0 && !strcmp(buf, DIRSEPSTRING)) { /* The specification is absolute - this is the root directory */ if ((wd = make_root_directory(partition)) == 0) return 0; break; } if (wd == 0) { /* This is a relative pathname - see if there is a CWD for this partition. * If not, default to the root directory for the partition. Then duplicate * the default stack so that the child can be appended. */ if (cwd[partition] == 0) cwd[partition] = make_root_directory(partition); if (cwd[partition] == 0) return 0; wd = copy_directory_stack(cwd[partition]); if (wd == 0) return 0; } /* Add the child directory to the path */ if ((child = make_child_directory(buf, NULL, wd)) == 0) { #if defined(CONFIG_WRITE) && defined(CONFIG_DIR_SUPPORT) if ((!is_dir) || (is_dir && !create)) #endif { delete_working_directory_stack(wd); return 0; } } #if defined(CONFIG_WRITE) && defined(CONFIG_DIR_SUPPORT) /* request to create a directory */ if (is_dir && create && (child == 0)) { /* create only if we are at the leaf */ parse_path(path + i, leaf_buf, WD_BUFSIZE, is_dir, &type); if (type != PATH_DONE) { /* we are not at the leaf, but couldn't go further * so invalid path */ return 0; } else /* we are at the leaf, so we need to create the directory */ return create_file_entry(buf, "", wd, ATTR_DIRECTORY); } #endif wd = child; break; case FILE_NAME: /* Buf contains a filename - now see if there is an extension there */ parse_path(path + i, ext_buf, WD_EXT_BUFSIZE, is_dir, &type); if (type == PATH_DONE) { /* The extension is empty */ ext_buf[0] = 0; } else if (type != FILE_EXT) { /* There was an error */ delete_working_directory_stack(wd); return 0; } if (wd == 0) { /* There is no directory, so copy over the cwd */ if (cwd[partition] == 0) cwd[partition] = make_root_directory(partition); if (cwd[partition] == 0) return 0; wd = copy_directory_stack(cwd[partition]); if (wd == 0) return 0; } /* See if this file exists */ if ((child = make_child_directory(buf, ext_buf, wd)) == 0) { #ifdef CONFIG_WRITE if (!create) /* no such file, and no request to create one */ #endif { delete_working_directory_stack(wd); return 0; } } /* if this is a request to create an entry, then * create an entry if none exists */ #ifdef CONFIG_WRITE if (create && child == 0) { /* search for a free directory entry * make a new entry with size 0 */ child = create_file_entry(buf, ext_buf, wd, 0); } #endif return child; case PATH_DONE: return wd; default: /* Error condition */ delete_working_directory_stack(wd); return 0; } } return wd; } WorkingDirectory *build_working_directory_stack(const char *path, int is_dir, int write) { WorkingDirectory *wd = NULL; if (write == 0) /* create for read mode */ return _build_working_directory_stack(path, is_dir, 0); #ifdef CONFIG_WRITE /* when created in write mode, the file has to be * truncated if already present * created if absent */ wd = _build_working_directory_stack(path, is_dir, 1); if (!wd) return 0; if (is_dir) return wd; /* if this is a pre-existing file (size != 0), then truncate it */ if (wd->v.child.FileSize != 0) { debug_xil_printf("File already exists..size = %d\n\r", (unsigned int)wd->v.child.FileSize); if (truncate_file(wd->v.child.FirstCluster, wd->pi) < 0) return 0; /* change filesize to 0. * the directory entry is not changed yet */ wd->v.child.FileSize = 0; debug_xil_printf("%s @ %d, file truncated\n\r", __FUNCTION__, __LINE__); } else { debug_print("File doesn't exist (Created now) or size 0.\n\r"); } #endif return wd; } void set_child_details(WorkingDirectory *wd, UINT32 firstcluster, UINT32 filesize, UINT32 de_sector, UINT32 de_offset, WorkingDirectory *parent) { wd->v.child.FirstCluster = firstcluster; wd->v.child.FileSize = filesize; wd->v.child.DirLocation.sector = de_sector; wd->v.child.DirLocation.offset = de_offset; wd->parent = parent; wd->pi = parent->pi; } WorkingDirectory *make_child_directory(const char *name, const char *ext, WorkingDirectory * parent) { WorkingDirectory *wd; UINT32 firstcluster; UINT32 filesize; UINT32 de_sector; UINT32 de_offset; /* find if child is present in given parent directory */ if (!find_in_directory(parent, name, ext, &firstcluster, &filesize, &de_sector, &de_offset)) return 0; /* create child wd */ if ((wd = malloc_wd(name)) == 0) return 0; set_child_details(wd, firstcluster, filesize, de_sector, de_offset, parent); return wd; } void set_root_details(WorkingDirectory *wd, PartitionInfo *pi) { switch(pi->FatType) { case FAT12: case FAT16: wd->v.root.StartSector = pi->RootDirSector; wd->v.root.DirCount = pi->RootDirCount; return; case FAT32: wd->v.child.FirstCluster = pi->RootCluster; return; } } WorkingDirectory *make_root_directory(int partition) { WorkingDirectory *wd; PartitionInfo *pi; if ((pi = get_partition_info(partition)) == 0) return 0; if ((wd = malloc_wd(DIRSEPSTRING)) == 0) return 0; wd->parent = 0; wd->pi = pi; /* copy over the information about root directory */ set_root_details(wd, pi); return wd; } #ifdef CONFIG_WRITE /* names are truncated to 8.3 format when writing */ void initialize_de(DirectoryEntry *de, char *name, char *ext, UINT32 firstcluster, UINT32 filesize, PartitionInfo *pi, BYTE attrib) { int i; for (i = 0; i < 8; i++) { if (*name) { de->Name[i] = toupper(*name); name++; } else de->Name[i] = ' '; } for (i = 0; i < 3; i++) { if (*ext) { de->Extension[i] = toupper(*ext); ext++; } else de->Extension[i] = ' '; } de->Attributes = attrib; memset(de->Reserved, 0, 8); memset(de->Date, 0, 2); update_de_firstcluster(de, firstcluster, pi); update_de_filesize(de, filesize); return; } #endif WorkingDirectory *copy_directory_stack(WorkingDirectory * stack) { WorkingDirectory *src, *dest, *first, *previous; first = 0; previous = 0; src = stack; /* Copy child directories */ while (src) { dest = malloc_wd(src->name); if (dest == 0) { delete_working_directory_stack(first); return 0; } if (first == 0) first = dest; if (previous) previous->parent = dest; dest->parent = 0; dest->pi = src->pi; if (src->parent || src->pi->FatType == FAT32) { /* Child directory */ dest->v.child.FirstCluster = src->v.child.FirstCluster; dest->v.child.FileSize = src->v.child.FileSize; } else { /* Root directory */ dest->v.root.StartSector = src->v.root.StartSector; dest->v.root.DirCount = src->v.root.DirCount; } src = src->parent; previous = dest; } return first; } 1.1 mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_write.c http://www.opencores.org/cvsweb.shtml/mb-jpeg/microblaze_0/libsrc/xilfatfs_v1_00_a/src/src/xilfatfs_write.c?rev=1.1&content-type=text/x-cvsweb-markup Index: xilfatfs_write.c =================================================================== ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Xilinx, Inc. All rights reserved. // // Xilinx, Inc. // // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A // COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR // STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION // IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE // FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. // XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO // THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO // ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. // //////////////////////////////////////////////////////////////////////////////// #include <string.h> #include "alloc.h" #include "fat.h" #include "filestatus.h" #include "sysace.h" #include "sysace_stdio.h" #include "util.h" /* write_to_file: * Write from the current position in chunks of sectors. * Update the file size in the directory entry * Update FAT if a new cluster is added */ int write_to_file(FileStatus *fs, char *buf, int count) { int writecount, n; int remaining; BYTE sectorbuf[SECTORSIZE], dir_buf[SECTORSIZE]; UINT32 sector; UINT32 nsectors; UINT32 sector_offset; UINT32 filesize; int byte_offset; PartitionInfo *pi = fs->wd->pi; UINT32 next_cluster; DirectoryEntry *de; /* Safety check */ if (fs == 0 || !fs->write || count <= 0) return 0; filesize = fs->wd->v.child.FileSize; debug_xil_printf("Original file size: %d\n\r", (int)filesize); writecount = 0; /* written til now */ remaining = count; /* remaining left to write */ /* read directory entry for this file. the directory entry * is updated at the end with the new file size */ if (read_sector(fs->wd->v.child.DirLocation.sector, dir_buf) != SECTORSIZE) return -1; de = (DirectoryEntry *) (dir_buf + fs->wd->v.child.DirLocation.offset); /* if this is the first byte of the file, then the firstcluster * entry for it should be set in its directory entry */ if (filesize == 0) { fs->wd->v.child.FirstCluster = pi->op->allocate_one_cluster(pi); if (fs->wd->v.child.FirstCluster == 0) return 0; /* out of space */ fs->CurrentCluster = fs->wd->v.child.FirstCluster; fs->PositionInCluster = fs->PositionInFile = 0; /* set the first cluster entry in the directory entry */ debug_xil_printf("First cluster set to: %d\n\r", (int)fs->CurrentCluster); update_de_firstcluster(de, fs->CurrentCluster, pi); } /* if we are currently in the middle of a sector, then read in * the contents before writing into it. */ /* Which byte of that sector did we leave off at last time ? */ byte_offset = fs->PositionInCluster % SECTORSIZE; if (byte_offset) { debug_xil_printf("%s @ %d: byte_offset = %d\n\r", __FUNCTION__, __LINE__, byte_offset); /* Which secto