ref: e614ab1d7f82b17b9a921280792ecbfb3a8d67d3
parent: d0007933f27f2cc8a821987af86c3429c7443c6f
author: cinap_lenrek <[email protected]>
date: Tue May 8 19:10:06 EDT 2012
9bootfat: fat12 support
--- a/sys/src/boot/pc/fat.c
+++ b/sys/src/boot/pc/fat.c
@@ -85,7 +85,7 @@
uchar volid[4];
uchar label[11];
uchar type[8];
- } fat16;
+ };
struct
{
uchar fatsize[4];
@@ -116,20 +116,33 @@
readnext(File *fp, ulong clust)
{
Fat *fat = fp->fat;
- uint b = fat->ver;
- ulong sect, off;
-
- sect = clust * b / Sectsz;
- off = clust * b % Sectsz;
- if(readsect(fat->drive, fat->fatlba + sect, fp->buf))
- memset(fp->buf, 0xff, 4);
- switch(fat->ver){
- case Fat16:
- return GETSHORT(&fp->buf[off]);
- case Fat32:
- return GETLONG(&fp->buf[off])& 0x0fffffff;
+ uchar tmp[2], *p;
+ ulong idx, lba;
+
+ if(fat->ver == Fat12)
+ idx = (3*clust)/2;
+ else
+ idx = clust*fat->ver;
+ lba = fat->fatlba + (idx / Sectsz);
+ if(readsect(fat->drive, lba, fp->buf))
+ memset(fp->buf, 0xff, Sectsz);
+ p = &fp->buf[idx % Sectsz];
+ if(p == &fp->buf[Sectsz-1]){
+ tmp[0] = *p;
+ if(readsect(fat->drive, ++lba, fp->buf))
+ memset(fp->buf, 0xff, Sectsz);
+ tmp[1] = fp->buf[0];
+ p = tmp;
}
- return 0;
+ if(fat->ver == Fat32)
+ return GETLONG(p) & 0xfffffff;
+ idx = GETSHORT(p);
+ if(fat->ver == Fat12){
+ if(clust & 1)
+ idx >>= 4;
+ idx &= 0xfff;
+ }
+ return idx;
}
int
@@ -141,7 +154,7 @@
if(fp->len > 0 && fp->rp >= fp->ep){
if(fp->clust != ~0U){
if(fp->lbaoff % fat->clustsize == 0){
- if((fp->clust >> 4) == fat->eofmark)
+ if(fp->clust < 2 || fp->clust >= fat->eofmark)
return -1;
fp->lbaoff = (fp->clust - 2) * fat->clustsize;
fp->clust = readnext(fp, fp->clust);
@@ -242,7 +255,7 @@
if(i == j && memcmp(name, path, j) == 0){
fileinit(fp, fat, 0);
fp->clust = dirclust(&d);
- fp->len = *((ulong*)d.len);
+ fp->len = GETLONG(d.len);
if(*end == 0)
return 0;
else if(d.attr & 0x10){
@@ -262,17 +275,19 @@
Pbs *p = buf;
uint fatsize, volsize, datasize, reserved;
uint ver, dirsize, dirents, clusters;
+
+ if(GETSHORT(p->sectsize) != Sectsz)
+ return -1;
+ if(memcmp(p->type, "FAT", 3) && memcmp(p->fat32.type, "FAT", 3))
+ return -1;
- /* sanity check */
- if(GETSHORT(p->sectsize) != Sectsz){
- print("sectsize != 512\r\n");
- halt();
- }
-
/* load values from fat */
+ ver = 0;
fatsize = GETSHORT(p->fatsize);
- if(fatsize == 0)
+ if(fatsize == 0){
fatsize = GETLONG(p->fat32.fatsize);
+ ver = Fat32;
+ }
volsize = GETSHORT(p->volsize);
if(volsize == 0)
volsize = GETLONG(p->bigvolsize);
@@ -281,21 +296,12 @@
dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
clusters = datasize / p->clustsize;
+ if(ver != Fat32)
+ if(clusters < 0xff7)
+ ver = Fat12;
+ else
+ ver = Fat16;
- /* determine fat type */
- if(clusters < 4085)
- ver = Fat12;
- else if(clusters < 65525)
- ver = Fat16;
- else
- ver = Fat32;
-
- /* another check */
- if(ver == Fat12){
- print("TODO: implement FAT12\r\n");
- halt();
- }
-
/* fill FAT descriptor */
fat->ver = ver;
fat->dirents = dirents;
@@ -305,11 +311,14 @@
if(ver == Fat32){
fat->datalba = fat->dirstart;
fat->dirstart = GETLONG(p->fat32.rootclust);
- fat->eofmark = 0xffffff;
+ fat->eofmark = 0xffffff7;
}else{
fat->datalba = fat->dirstart + dirsize;
- fat->eofmark = 0xfff;
- }
+ if(ver == Fat16)
+ fat->eofmark = 0xfff7;
+ else
+ fat->eofmark = 0xff7;
+ }
return 0;
}
@@ -333,6 +342,12 @@
return -1;
if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
return -1;
+ if(lba == 0){
+ fat->drive = drive;
+ fat->partlba = 0;
+ if(!conffat(fat, buf))
+ return 0;
+ }
p = (void*)&buf[0x1be];
for(i=0; i<4; i++){
switch(p[i].typ){
@@ -352,9 +367,8 @@
fat->partlba = lba + GETLONG(p[i].lba);
if(readsect(drive, fat->partlba, buf))
continue;
- if(conffat(fat, buf))
- continue;
- return 0;
+ if(!conffat(fat, buf))
+ return 0;
}
}
return -1;