mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
fat: fatwrite: fix the command for FAT12
The u-boot command fatwrite empties FAT clusters from the beginning
till the end of the file.
Specifically for FAT12 it fails to detect the end of the file and goes
beyond the file bounds thus corrupting the file system.
Additionally, FAT entry chaining-up into a file is not implemented
for FAT12.
The users normally workaround this by re-formatting the partition as
FAT16/FAT32, like here:
https://github.com/FEDEVEL/openrex-uboot-v2015.10/issues/1
The patch fixes the bounds of a file and FAT12 entries chaining into
a file, including EOF markup.
Signed-off-by: Philipp Skadorov <philipp.skadorov@savoirfairelinux.com>
(cherry picked from commit 49abbd9cc3)
Signed-off-by: Hariharan K <quic_harihk@quicinc.com>
Change-Id: Ib9c75d4553ea576cbc592f3291cfdebc45b8376b
This commit is contained in:
parent
a04c25d601
commit
5593ba9b9f
1 changed files with 53 additions and 8 deletions
|
|
@ -466,11 +466,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:
|
||||
|
|
@ -481,6 +482,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;
|
||||
|
|
@ -518,6 +523,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;
|
||||
|
|
@ -527,7 +571,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
|
|||
}
|
||||
|
||||
/*
|
||||
* Determine the entry value at index 'entry' in a FAT (16/32) table
|
||||
* Determine the next free cluster after 'entry' in a FAT (12/16/32) table
|
||||
*/
|
||||
static __u32 determine_fatent(fsdata *mydata, __u32 entry)
|
||||
{
|
||||
|
|
@ -647,6 +691,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;
|
||||
|
||||
|
|
@ -666,16 +712,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;
|
||||
}
|
||||
|
||||
|
|
@ -746,7 +789,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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue