9bootfat: fat12 support
This commit is contained in:
parent
d0007933f2
commit
e614ab1d7f
1 changed files with 57 additions and 43 deletions
|
@ -85,7 +85,7 @@ struct Pbs
|
||||||
uchar volid[4];
|
uchar volid[4];
|
||||||
uchar label[11];
|
uchar label[11];
|
||||||
uchar type[8];
|
uchar type[8];
|
||||||
} fat16;
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uchar fatsize[4];
|
uchar fatsize[4];
|
||||||
|
@ -116,20 +116,33 @@ static ulong
|
||||||
readnext(File *fp, ulong clust)
|
readnext(File *fp, ulong clust)
|
||||||
{
|
{
|
||||||
Fat *fat = fp->fat;
|
Fat *fat = fp->fat;
|
||||||
uint b = fat->ver;
|
uchar tmp[2], *p;
|
||||||
ulong sect, off;
|
ulong idx, lba;
|
||||||
|
|
||||||
sect = clust * b / Sectsz;
|
if(fat->ver == Fat12)
|
||||||
off = clust * b % Sectsz;
|
idx = (3*clust)/2;
|
||||||
if(readsect(fat->drive, fat->fatlba + sect, fp->buf))
|
else
|
||||||
memset(fp->buf, 0xff, 4);
|
idx = clust*fat->ver;
|
||||||
switch(fat->ver){
|
lba = fat->fatlba + (idx / Sectsz);
|
||||||
case Fat16:
|
if(readsect(fat->drive, lba, fp->buf))
|
||||||
return GETSHORT(&fp->buf[off]);
|
memset(fp->buf, 0xff, Sectsz);
|
||||||
case Fat32:
|
p = &fp->buf[idx % Sectsz];
|
||||||
return GETLONG(&fp->buf[off])& 0x0fffffff;
|
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
|
int
|
||||||
|
@ -141,7 +154,7 @@ read(void *f, void *data, int len)
|
||||||
if(fp->len > 0 && fp->rp >= fp->ep){
|
if(fp->len > 0 && fp->rp >= fp->ep){
|
||||||
if(fp->clust != ~0U){
|
if(fp->clust != ~0U){
|
||||||
if(fp->lbaoff % fat->clustsize == 0){
|
if(fp->lbaoff % fat->clustsize == 0){
|
||||||
if((fp->clust >> 4) == fat->eofmark)
|
if(fp->clust < 2 || fp->clust >= fat->eofmark)
|
||||||
return -1;
|
return -1;
|
||||||
fp->lbaoff = (fp->clust - 2) * fat->clustsize;
|
fp->lbaoff = (fp->clust - 2) * fat->clustsize;
|
||||||
fp->clust = readnext(fp, fp->clust);
|
fp->clust = readnext(fp, fp->clust);
|
||||||
|
@ -242,7 +255,7 @@ fatwalk(File *fp, Fat *fat, char *path)
|
||||||
if(i == j && memcmp(name, path, j) == 0){
|
if(i == j && memcmp(name, path, j) == 0){
|
||||||
fileinit(fp, fat, 0);
|
fileinit(fp, fat, 0);
|
||||||
fp->clust = dirclust(&d);
|
fp->clust = dirclust(&d);
|
||||||
fp->len = *((ulong*)d.len);
|
fp->len = GETLONG(d.len);
|
||||||
if(*end == 0)
|
if(*end == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if(d.attr & 0x10){
|
else if(d.attr & 0x10){
|
||||||
|
@ -262,17 +275,19 @@ conffat(Fat *fat, void *buf)
|
||||||
Pbs *p = buf;
|
Pbs *p = buf;
|
||||||
uint fatsize, volsize, datasize, reserved;
|
uint fatsize, volsize, datasize, reserved;
|
||||||
uint ver, dirsize, dirents, clusters;
|
uint ver, dirsize, dirents, clusters;
|
||||||
|
|
||||||
/* sanity check */
|
if(GETSHORT(p->sectsize) != Sectsz)
|
||||||
if(GETSHORT(p->sectsize) != Sectsz){
|
return -1;
|
||||||
print("sectsize != 512\r\n");
|
if(memcmp(p->type, "FAT", 3) && memcmp(p->fat32.type, "FAT", 3))
|
||||||
halt();
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
/* load values from fat */
|
/* load values from fat */
|
||||||
|
ver = 0;
|
||||||
fatsize = GETSHORT(p->fatsize);
|
fatsize = GETSHORT(p->fatsize);
|
||||||
if(fatsize == 0)
|
if(fatsize == 0){
|
||||||
fatsize = GETLONG(p->fat32.fatsize);
|
fatsize = GETLONG(p->fat32.fatsize);
|
||||||
|
ver = Fat32;
|
||||||
|
}
|
||||||
volsize = GETSHORT(p->volsize);
|
volsize = GETSHORT(p->volsize);
|
||||||
if(volsize == 0)
|
if(volsize == 0)
|
||||||
volsize = GETLONG(p->bigvolsize);
|
volsize = GETLONG(p->bigvolsize);
|
||||||
|
@ -281,20 +296,11 @@ conffat(Fat *fat, void *buf)
|
||||||
dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
|
dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
|
||||||
datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
|
datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
|
||||||
clusters = datasize / p->clustsize;
|
clusters = datasize / p->clustsize;
|
||||||
|
if(ver != Fat32)
|
||||||
/* determine fat type */
|
if(clusters < 0xff7)
|
||||||
if(clusters < 4085)
|
ver = Fat12;
|
||||||
ver = Fat12;
|
else
|
||||||
else if(clusters < 65525)
|
ver = Fat16;
|
||||||
ver = Fat16;
|
|
||||||
else
|
|
||||||
ver = Fat32;
|
|
||||||
|
|
||||||
/* another check */
|
|
||||||
if(ver == Fat12){
|
|
||||||
print("TODO: implement FAT12\r\n");
|
|
||||||
halt();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill FAT descriptor */
|
/* fill FAT descriptor */
|
||||||
fat->ver = ver;
|
fat->ver = ver;
|
||||||
|
@ -305,11 +311,14 @@ conffat(Fat *fat, void *buf)
|
||||||
if(ver == Fat32){
|
if(ver == Fat32){
|
||||||
fat->datalba = fat->dirstart;
|
fat->datalba = fat->dirstart;
|
||||||
fat->dirstart = GETLONG(p->fat32.rootclust);
|
fat->dirstart = GETLONG(p->fat32.rootclust);
|
||||||
fat->eofmark = 0xffffff;
|
fat->eofmark = 0xffffff7;
|
||||||
}else{
|
}else{
|
||||||
fat->datalba = fat->dirstart + dirsize;
|
fat->datalba = fat->dirstart + dirsize;
|
||||||
fat->eofmark = 0xfff;
|
if(ver == Fat16)
|
||||||
}
|
fat->eofmark = 0xfff7;
|
||||||
|
else
|
||||||
|
fat->eofmark = 0xff7;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +342,12 @@ findfat(Fat *fat, int drive, ulong xbase, ulong lba)
|
||||||
return -1;
|
return -1;
|
||||||
if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
|
if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
|
||||||
return -1;
|
return -1;
|
||||||
|
if(lba == 0){
|
||||||
|
fat->drive = drive;
|
||||||
|
fat->partlba = 0;
|
||||||
|
if(!conffat(fat, buf))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
p = (void*)&buf[0x1be];
|
p = (void*)&buf[0x1be];
|
||||||
for(i=0; i<4; i++){
|
for(i=0; i<4; i++){
|
||||||
switch(p[i].typ){
|
switch(p[i].typ){
|
||||||
|
@ -352,9 +367,8 @@ findfat(Fat *fat, int drive, ulong xbase, ulong lba)
|
||||||
fat->partlba = lba + GETLONG(p[i].lba);
|
fat->partlba = lba + GETLONG(p[i].lba);
|
||||||
if(readsect(drive, fat->partlba, buf))
|
if(readsect(drive, fat->partlba, buf))
|
||||||
continue;
|
continue;
|
||||||
if(conffat(fat, buf))
|
if(!conffat(fat, buf))
|
||||||
continue;
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in a new issue