⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 format.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码.移植性非常高. 里面带有source i.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    format.c

Abstract:

    This file contains routines for formatting volumes.

Revision History:

--*/

#include "fatfs.h"


/*  FormatVolume - Format a volume
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      pfv - pointer to FMTVOLREQ structure (NULL if none)
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, error code if not
 *
 *  NOTES
 *      Note that some of the values calculated by this function are arbitrary
 *      (eg, 256 root directory entries for SRAM cards vs. 512 root entries for
 *      ATA cards; no backup FATs unless specifically requested by the caller; etc).
 *      Which means the resulting volume may not exactly match what an MS-DOS or
 *      Win95 FORMAT utility would have created, but the volume should still be a
 *      legitimate FAT volume, and so hopefully all MS-DOS-based or Win95-based systems
 *      will have no problem mounting/reading it.
 */

DWORD FormatVolume(PVOLUME pvol, PFMTVOLREQ pfv)
{
    DWORD dwFlags;
    int iFAT, cLoops;
    BYTE cFATs, bMediaDesc;
    DWORD csecReserved, cRootEntries;
    DWORD sec, csecHidden, csecClus;
    DWORD csecFATs, csecFATsLast;
    DWORD csecRoot, csecData, cclusData;
    DEVPB devpb, volpb;
    DWORD cbitsClus, secVolBias;
    DWORD dwError = ERROR_SUCCESS;
    BYTE abSector[DEFAULT_SECTOR_SIZE];
    TCHAR szVolumeName[MAX_PATH];

    dwFlags = FMTVOL_QUICK;
    if (pfv)
    dwFlags = pfv->fv_flags;

    // All we support right now is "quick format"

    if (!(dwFlags & FMTVOL_QUICK))
        return ERROR_INVALID_FUNCTION;

       
    // Now we can proceed with the "logical" formatting process...

    QueryVolumeParameters(pvol, &volpb, TRUE);
    QueryVolumeParameters(pvol, &devpb, FALSE);

    if (devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector != sizeof(abSector)) {
    DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FormatVolume: unsupported sector size (%d)\n"), devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector));
    return ERROR_GEN_FAILURE;
    }

    // Determine if we need to format the entire device or if the volume is already
    // sufficiently well-defined.  Don't bother with a backup FAT unless caller requests it.

    cFATs = 1;
    if (dwFlags & FMTVOL_BACKUP_FAT)
    cFATs++;

    cRootEntries = 256;
    if (dwFlags & FMTVOL_ROOT_ENTRIES)
    cRootEntries = pfv->fv_cRootEntries;

    csecReserved = 1;
    secVolBias = 0;
    csecHidden = devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors = 0;

    // If there's partition information for this volume, use it;  otherwise,
    // rely on any existing volume information (for the case where we're being reformatted)

    if (pvol->v_ppi) {
    secVolBias = pvol->v_ppi->pi_secAbsolute;
    devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors = pvol->v_ppi->pi_secAbsolute;
    if (pvol->v_ppi->pi_ppiParent)
        devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors -= pvol->v_ppi->pi_secPartTable;
    devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = pvol->v_ppi->pi_PartEntry.Part_TotalSectors;
    }
    else if (volpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors != 0 && !(dwFlags & FMTVOL_DISK)) {
    secVolBias = pvol->v_secVolBias;
    devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors = volpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors;
    devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = volpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors;
    }

    // Compute new volume characteristics now

    if (dwFlags & FMTVOL_VOLUME_SIZE) {
    // But you can't make the volume *bigger* than it really is...
    if (pfv->fv_csecVol > devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors)
        return ERROR_INVALID_PARAMETER;
    devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = pfv->fv_csecVol;
    }

    // Determine if this is disk should be partitioned (and have hidden sectors)

    if (devpb.DevPrm.OldDevPB.bMediaType == MEDIA_HD) {

    // Partitioned disks typically reserve the entire first track,
    // although only the first sector is used.  Carry the tradition forward...

    if (!(dwFlags & FMTVOL_ROOT_ENTRIES))
        cRootEntries = 512;

    if (secVolBias == 0)
        csecHidden = devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors = devpb.DevPrm.OldDevPB.BPB.BPB_SectorsPerTrack;
    }

    if (csecHidden || devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors)
    bMediaDesc = MEDIA_HD;
    else
    bMediaDesc = MEDIA_1440;

    
    csecClus = 1;

    if (dwFlags & FMTVOL_CLUSTER_SIZE) {
    csecClus = pfv->fv_csecClus;
    // Make sure the cluster size is valid, fits in a byte, and is a power of two...
    if (csecClus == 0 || csecClus > 255 || (csecClus & (csecClus-1)))
        return ERROR_INVALID_PARAMETER;
    }

    // Compute how many clusters will fit on the media, by first estimating
    // how many sectors will be in the data area, then recomputing the number
    // of clusters until we get a consistent answer.

restart:

    do {
    cLoops = 4;
    csecFATs = csecRoot = 0;
    do {

        csecData = devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors -
            csecHidden - csecReserved - csecFATs - csecRoot;
        do {
        cclusData = csecData / csecClus;

        if (csecClus > (DWORD)(MAX_CLUS_SIZE/devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector)) {

            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FormatVolume: media too large (%d clusters at %d secs/clus)\n"), dwError, cclusData, csecClus));

            // If a volume size has been specified, then we have to bail

            if (dwFlags & FMTVOL_VOLUME_SIZE)
            return ERROR_INVALID_PARAMETER;

            
            dwFlags |= FMTVOL_VOLUME_SIZE;
#ifdef FAT32
            devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = (FAT32_BAD-1)*(MAX_CLUS_SIZE/devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector);
#else
            devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = (FAT16_BAD-1)*(MAX_CLUS_SIZE/devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector);
#endif
            goto restart;
        }

        if (!(dwFlags & (FMTVOL_16BIT_FAT | FMTVOL_32BIT_FAT))) {
            if (cclusData < FAT1216_THRESHOLD) {
            cbitsClus = 12; // Should use a 12-bit FAT
            break;
            }
        }

        if (!(dwFlags & (FMTVOL_12BIT_FAT | FMTVOL_32BIT_FAT))) {
            if (cclusData < FAT1632_THRESHOLD) {
            cbitsClus = 16; // Should use a 16-bit FAT
            break;
            }
        }

#ifndef FAT32
        csecClus *= 2;  // if no FAT32 support, no choice but to grow cluster size
#else
        // So, at the current cluster size, a 32-bit FAT is the only answer;
        // however, we won't settle on that as long as the cluster size is still small
        // (less than 4K) AND the cluster was not explicitly selected by the caller.

        if (!(dwFlags & (FMTVOL_CLUSTER_SIZE | FMTVOL_32BIT_FAT)) &&
            csecClus < (DWORD)(4096/devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector)) {
                        csecClus *= 2;      // grow the cluster size
        }
        else {
            // Bite the bullet and go with a 32-bit FAT;  note that FAT32 also requires
            // more than the usual number of reserved sectors, which we need to "reserve" now.
            cbitsClus = 32;
            csecReserved = 2;   // why only 2? see "minimalist" comments below...
            break;
        }
#endif

        } while (TRUE);

        // NOTE: when computing csecFATs, we must add DATA_CLUSTER (2) to cclusData, because
        // the first two entries in a FAT aren't real entries, but we must still account for them.

        csecFATsLast = csecFATs;
        csecFATs = (((cclusData+DATA_CLUSTER) * cbitsClus + 7)/8 + devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector-1) / devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector * cFATs;
#ifdef FAT32
        if (cbitsClus == 32)        // csecRoot comes into play only on non-FAT32 volumes
        csecRoot = 0;
        else
#endif
        csecRoot = (sizeof(DIRENTRY) * cRootEntries + devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector-1) / devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector;

    } while (csecFATs != csecFATsLast && --cLoops);

    if (cLoops)
        break;

    // We couldn't get a consistent answer, so chop off one cluster

    devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors -= csecClus;

    } while (TRUE);

    DEBUGMSG (ZONE_INIT,(DBGTEXT ("FATFS!FormatVolume:\n\n")));
    DEBUGMSGW(ZONE_INIT,(DBGTEXTW("Disk type:             %s\n"), csecHidden || devpb.DevPrm.OldDevPB.BPB.BPB_HiddenSectors? TEXTW("fixed") : TEXTW("removable")));
    DEBUGMSG (ZONE_INIT,(DBGTEXT ("Sectors/FAT:           %d (%d FATs)\n"), csecFATs/cFATs, cFATs));
    DEBUGMSG (ZONE_INIT,(DBGTEXT ("New cluster size:      %d (%d-bit FAT)\n"), csecClus * devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector, cbitsClus));
    DEBUGMSG (ZONE_INIT,(DBGTEXT ("New total clusters:    %d\n"), cclusData));
    DEBUGMSG (ZONE_INIT,(DBGTEXT ("Total available space: %d bytes\n\n"), cclusData * csecClus * devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector));

    // Now try to lock the volume in preparation for writing

    dwError = LockVolume(pvol, VOLF_LOCKED);
    if (dwError) {
    DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FormatVolume: cannot lock volume (%d)\n"), dwError));
    goto abort;
    }

    // We will invalidate all buffers now, whether dirty or not, since we're about to rewrite
    // the disk structure.  Note that LockVolume is already supposed to insure that any threads
    // that might have missed the locking transition have left FATFS, so there shouldn't be any
    // risk of this invalidation being undone by another thread still modifying the disk state.

    InvalidateBufferSet(pvol, TRUE);

    pvol->v_flags |= VOLF_FORMATTING;

    // Now write a new partition table if this is a partitioned disk and we're
    // reformatting the whole disk...

    if (csecHidden) {

    PPARTENTRY ppe;
    DWORD maxCyl =
        devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors /
       (devpb.DevPrm.OldDevPB.BPB.BPB_Heads * devpb.DevPrm.OldDevPB.BPB.BPB_SectorsPerTrack) - 1;

    // The bulk of the partition sector needs to be zeroed.

    memset(abSector, 0, devpb.DevPrm.OldDevPB.BPB.BPB_BytesPerSector);
    abSector[0] = BS3BYTJMP;
    abSector[1] = 0xfd;
    abSector[2] = 0xff;

    // Point to first partition table slot (the only one we're going to fill)

    ppe = (PPARTENTRY)(abSector+PARTTABLE_OFFSET);

    ppe->Part_BootInd = PART_BOOTABLE;
    ppe->Part_FirstHead = 1;
    ppe->Part_FirstSector = 1;
    ppe->Part_FirstTrack = 0;

    if (cbitsClus == 12) {
        ppe->Part_FileSystem = PART_DOS2_FAT;       // 12-bit FAT ID
    } else {
#ifdef FAT32
        if (cbitsClus == 32)
        ppe->Part_FileSystem = PART_DOS32X13;   // 32-bit FAT ID
        else
#endif
        if (devpb.DevPrm.OldDevPB.BPB.BPB_BigTotalSectors < 65536)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -