📄 fat32.c
字号:
/*
nexOS: nexos generic ata driver - generic ata driver FAT32 dir reader
Copyright 2004 nexOS development team
This file is part of nexOS.
nexOS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
nexOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with nexOS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* this file just contains a test and gets removed after devfs is done */
#include "ata.h"
#include "fat32.h"
#include <libnexos-module/nexos-module.h>
extern const char *ata_map_sysid(BYTE);
extern const char ata_cmderr[][15];
DWORD fat32_firstsecofcluster(DWORD cluster, FAT32BS *bs);
void fat32_fatentry_from_cluster(DWORD cluster, FAT32BS *bs, DWORD *sector, DWORD *offset);
int fat32_buildclusterchain(ATA_DRIVE *drv, DWORD startsector, FAT32BS *bs,
DWORD startcluster, DWORD clusterbuf[], DWORD bufelems);
void fat32_printbs(FAT32BS *bs);
int fat32_readdir(int argc, char *argv[])
{
if( argc < 4 )
{
kprintf("usage: %s <controller> <drive> <partition>\n",argv[0]);
kprintf("Controller: 0-1\tDrive: 0-1\tPartition: 0-3\n");
kprintf("example: %s 0 0 2\nreads fat32 dir on primary master partition 2\n",argv[0]);
return 0;
}
if( argv[1][0] < '0' || argv[1][0] > '1' || argv[2][0] < '0' ||
argv[2][0] > '1' || argv[3][0] < '0' || argv[3][0] > '3' )
{
kprintf("usage: %s <controller> <drive> <partition>\n",argv[0]);
kprintf("Controller: 0-1\tDrive: 0-1\tPartition: 0-3\n");
kprintf("example: %s 0 0 2\nreads fat32 dir on primary master partition 2\n",argv[0]);
return 0;
}
ATA_DRIVE drv;
BLOCK blk;
int status;
char sector[512];
MBR *mbr = (MBR*)sector;
int partition = argv[3][0]-0x30;
/* load data into struct */
drv.controller = argv[1][0] - 0x30;
drv.drive = argv[2][0] - 0x30;
/* read MBR first to determine if the chosen partition is fat32 actually */
/* the blk struct uses 64-bit LBA adresses (for future use) */
blk.lownum = 0;
blk.highnum = 0;
blk.len = 1;
blk.buf = sector;
/* select drive and identify it */
ata_select(&drv);
ata_identify(&drv,sector);
/* read MBR */
if( (status = ata_readblocks(&drv,blk)) == ATA_ERR_NONE )
{
if( mbr->partitions[partition].systid != 0x0B )
{
kprintf("Selected partition type is not FAT32, but %s.\n",
ata_map_sysid(mbr->partitions[partition].systid));
return 0;
}
}
else
{
kprintf("(%s:%d)ERROR %X: %s\n",__FILE__,__LINE__,status,ata_cmderr[status]);
return 0;
}
DWORD partstartsec = mbr->partitions[partition].relsect;
FAT32BS *fat32bs = (FAT32BS*)sector;
FAT32DIRENT direntrys[16];
DWORD clchain[256];
DWORD clchainlen;
int i,j,k;
char fname[13];
char attrstr[7];
BYTE namefirstbyte;
/* selected partition is valid, so load the 1st sector in the partition */
blk.lownum = partstartsec;
blk.highnum = 0;
blk.len = 1;
blk.buf = fat32bs;
if( (status = ata_readblocks(&drv,blk)) != ATA_ERR_NONE )
{
kprintf("(%s:%d)ERROR %X: %s\n",__FILE__,__LINE__,status,ata_cmderr[status]);
return 0;
}
/* build the clusterchain */
clchainlen = fat32_buildclusterchain(&drv,partstartsec,fat32bs,fat32bs->rootcluster,clchain,256);
/* we use the filename buffer to hold the volume label */
kmemset(fname,0,13);
kmemcpy(fname,fat32bs->vollabel,11);
/* print header */
kprintf("Root directory on \"%s\" (%X):\n",fname,fat32bs->volid);
kprintf(" Filename | Attributes | Size\n");
kprintf("--------------------+----------------+-------------\n");
/* cycle through all clusters and print the dir entrys */
for( i=0; i<clchainlen; i++)
{
for( k=0; k<fat32bs->secpercluster; k++ )
{
/* load next sector of cluster */
blk.lownum = fat32_firstsecofcluster(clchain[i],fat32bs) + partstartsec + k;
blk.buf = direntrys;
ata_readblocks(&drv,blk);
for( j=0; j<16; j++ )
{
/* check if this is the last entry/ a valid entry */
namefirstbyte = direntrys[j].name[0];
if( namefirstbyte == 0x00 )
break;
if( namefirstbyte != 0xE5 && namefirstbyte != 0x05 )
{
/* "valid" (normal file/dir) entry, copy filename */
kmemset(fname,0,13);
kmemcpy(fname,direntrys[j].name,11);
/* build attr string */
kmemset(attrstr,0,7);
if( direntrys[j].attr & FAT32_ATTR_READ_ONLY )
attrstr[0] = 'r';
else
attrstr[0] = '-';
if( direntrys[j].attr & FAT32_ATTR_HIDDEN )
attrstr[1] = 'h';
else
attrstr[1] = '-';
if( direntrys[j].attr & FAT32_ATTR_SYSTEM )
attrstr[2] = 's';
else
attrstr[2] = '-';
if( direntrys[j].attr & FAT32_ATTR_VOLUME_ID )
attrstr[3] = 'v';
else
attrstr[3] = '-';
if( direntrys[j].attr & FAT32_ATTR_DIRECTORY )
attrstr[4] = 'd';
else
attrstr[4] = '-';
if( direntrys[j].attr & FAT32_ATTR_ARCHIVE )
attrstr[5] = 'a';
else
attrstr[5] = '-';
/* ignore volume id "files" */
if( !(direntrys[j].attr & FAT32_ATTR_VOLUME_ID) )
{
kprintf(" %s | %s | ",fname,attrstr);
if( direntrys[j].size > 1<<20 ) /* megabytes */
kprintf("%d mb",direntrys[j].size>>20);
else if( direntrys[j].size > 1<<10 ) /* kilobytes */
kprintf("%d kb",direntrys[j].size>>10);
else /* bytes */
kprintf("%d b",direntrys[j].size);
kprintf("\n");
}
}
}
}
}
return 0;
}
void fat32_printbs(FAT32BS *bs)
{
char text[12];
kmemset(text,0,12);kmemcpy(text,bs->oemname,8);kprintf("OEM name: %s\t",text);
kmemset(text,0,12);kmemcpy(text,bs->fstype,8);kprintf("FS type: %s\t",text);
kmemset(text,0,12);kmemcpy(text,bs->vollabel,11);kprintf("Vol.label: %s\t",text);
kprintf("Vol.ID: %X\n",bs->volid);
kprintf("FAT size (16/32): %d/%d\tNum FATs: %d\n",bs->fatsize16,bs->fatsize32,bs->numfats);
kprintf("Total sectors (16/32): %d/%d\tReserved sectors: %d\n",bs->totsec16,bs->totsec32,bs->resseccnt);
kprintf("Bytes per Sector: %X\tSectors per cluster: %d\tRootcluster: %d\n",bs->bytespersec,bs->secpercluster,bs->rootcluster);
kprintf("Bootsector signature (must be 0xAA55): %X\n",bs->signature);
}
void fat32_fatentry_from_cluster(DWORD cluster, FAT32BS *bs, DWORD *sector, DWORD *offset)
{
*sector = bs->resseccnt + ((cluster*4) / bs->bytespersec);
*offset = (cluster*4) % bs->bytespersec;
}
DWORD fat32_firstsecofcluster(DWORD cluster, FAT32BS *bs)
{
return ((cluster-2)*bs->secpercluster)+bs->resseccnt+(bs->fatsize32 * bs->numfats);
}
int fat32_buildclusterchain(ATA_DRIVE *drv, DWORD startsector, FAT32BS *bs,
DWORD startcluster, DWORD clusterbuf[], DWORD bufelems)
{
DWORD sectorbuf[128];
BLOCK blk;
blk.highnum = 0;
blk.lownum = startsector;
blk.len = 1;
blk.buf = sectorbuf;
DWORD lastsector, sector, offset;
DWORD curcluster;
DWORD nextcluster = startcluster;
DWORD i = 0;
lastsector = 0;
ata_readblocks(drv,blk);
for( curcluster=startcluster; curcluster > 1 && curcluster <= 0x0FFFFFF7 && i<bufelems; i++ )
{
clusterbuf[i] = curcluster;
fat32_fatentry_from_cluster(nextcluster,bs,§or,&offset);
if( sector != lastsector )
{
blk.lownum = startsector + sector;
ata_readblocks(drv,blk);
lastsector = sector;
}
curcluster = sectorbuf[offset/4];
}
return i;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -