]> git.sur5r.net Git - u-boot/blobdiff - fs/fat/fat_write.c
fat: fatwrite: fix the command for FAT12
[u-boot] / fs / fat / fat_write.c
index 40a3860e47c9f58d63dc6b813b53fd772bd11c96..aab0b0e71d8ed3e1bf27be5d8444bb97032f8af4 100644 (file)
@@ -467,11 +467,12 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 }
 
 /*
- * 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:
@@ -482,6 +483,10 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
                bufnum = entry / FAT16BUFSIZE;
                offset = entry - bufnum * FAT16BUFSIZE;
                break;
+       case 12:
+               bufnum = entry / FAT12BUFSIZE;
+               offset = entry - bufnum * FAT12BUFSIZE;
+               break;
        default:
                /* Unsupported FAT size */
                return -1;
@@ -520,6 +525,45 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
                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;
@@ -529,7 +573,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
 }
 
 /*
- * 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)
@@ -651,6 +695,8 @@ static void flush_dir_table(fsdata *mydata, dir_entry **dentptr)
                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;
 
@@ -670,16 +716,13 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
 {
        __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;
        }
 
@@ -750,7 +793,9 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
                *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;