}
/*
- * Set the entry at index 'entry' in a FAT (16/32) table.
+ * Set the entry at index 'entry' in a FAT (12/16/32) table.
*/
static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
{
- __u32 bufnum, offset;
+ __u32 bufnum, offset, off16;
+ __u16 val1, val2;
switch (mydata->fatsize) {
case 32:
bufnum = entry / FAT16BUFSIZE;
offset = entry - bufnum * FAT16BUFSIZE;
break;
+ case 12:
+ bufnum = entry / FAT12BUFSIZE;
+ offset = entry - bufnum * FAT12BUFSIZE;
+ break;
default:
/* Unsupported FAT size */
return -1;
break;
case 16:
((__u16 *) mydata->fatbuf)[offset] = cpu_to_le16(entry_value);
+ break;
+ case 12:
+ off16 = (offset * 3) / 4;
+
+ switch (offset & 0x3) {
+ case 0:
+ val1 = cpu_to_le16(entry_value) & 0xfff;
+ ((__u16 *)mydata->fatbuf)[off16] &= ~0xfff;
+ ((__u16 *)mydata->fatbuf)[off16] |= val1;
+ break;
+ case 1:
+ val1 = cpu_to_le16(entry_value) & 0xf;
+ val2 = (cpu_to_le16(entry_value) >> 4) & 0xff;
+
+ ((__u16 *)mydata->fatbuf)[off16] &= ~0xf000;
+ ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 12);
+
+ ((__u16 *)mydata->fatbuf)[off16 + 1] &= ~0xff;
+ ((__u16 *)mydata->fatbuf)[off16 + 1] |= val2;
+ break;
+ case 2:
+ val1 = cpu_to_le16(entry_value) & 0xff;
+ val2 = (cpu_to_le16(entry_value) >> 8) & 0xf;
+
+ ((__u16 *)mydata->fatbuf)[off16] &= ~0xff00;
+ ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 8);
+
+ ((__u16 *)mydata->fatbuf)[off16 + 1] &= ~0xf;
+ ((__u16 *)mydata->fatbuf)[off16 + 1] |= val2;
+ break;
+ case 3:
+ val1 = cpu_to_le16(entry_value) & 0xfff;
+ ((__u16 *)mydata->fatbuf)[off16] &= ~0xfff0;
+ ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 4);
+ break;
+ default:
+ break;
+ }
+
break;
default:
return -1;
}
/*
- * Determine the next free cluster after 'entry' in a FAT (16/32) table
+ * Determine the next free cluster after 'entry' in a FAT (12/16/32) table
* and link it to 'entry'. EOC marker is not set on returned entry.
*/
static __u32 determine_fatent(fsdata *mydata, __u32 entry)
set_fatent_value(mydata, dir_newclust, 0xffffff8);
else if (mydata->fatsize == 16)
set_fatent_value(mydata, dir_newclust, 0xfff8);
+ else if (mydata->fatsize == 12)
+ set_fatent_value(mydata, dir_newclust, 0xff8);
dir_curclust = dir_newclust;
{
__u32 fat_val;
- while (1) {
+ while (!CHECK_CLUST(entry, mydata->fatsize)) {
fat_val = get_fatent_value(mydata, entry);
if (fat_val != 0)
set_fatent_value(mydata, entry, 0);
else
break;
- if (fat_val == 0xfffffff || fat_val == 0xffff)
- break;
-
entry = fat_val;
}
*gotsize += actsize;
/* Mark end of file in FAT */
- if (mydata->fatsize == 16)
+ if (mydata->fatsize == 12)
+ newclust = 0xfff;
+ else if (mydata->fatsize == 16)
newclust = 0xffff;
else if (mydata->fatsize == 32)
newclust = 0xfffffff;