]> Git Repo - J-u-boot.git/blame - fs/fat/fat.c
Merge branch '080131_artila' of git://linux-arm.org/u-boot-armdev
[J-u-boot.git] / fs / fat / fat.c
CommitLineData
71f95118
WD
1/*
2 * fat.c
3 *
4 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
5 *
6 * 2002-07-28 - [email protected] - ported to ppcboot v1.1.6
7 * 2003-03-10 - [email protected] - ported to uboot
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <config.h>
30#include <fat.h>
31#include <asm/byteorder.h>
7205e407 32#include <part.h>
71f95118 33
dd60d122 34#if defined(CONFIG_CMD_FAT)
71f95118
WD
35
36/*
37 * Convert a string to lowercase.
38 */
39static void
40downcase(char *str)
41{
42 while (*str != '\0') {
43 TOLOWER(*str);
44 str++;
45 }
46}
47
7205e407
WD
48static block_dev_desc_t *cur_dev = NULL;
49static unsigned long part_offset = 0;
50static int cur_part = 1;
51
52#define DOS_PART_TBL_OFFSET 0x1be
53#define DOS_PART_MAGIC_OFFSET 0x1fe
54#define DOS_FS_TYPE_OFFSET 0x36
71f95118
WD
55
56int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr)
57{
7205e407
WD
58 startblock += part_offset;
59 if (cur_dev == NULL)
60 return -1;
61 if (cur_dev->block_read) {
3e3b9569
PP
62 return cur_dev->block_read (cur_dev->dev
63 , startblock, getsize, (unsigned long *)bufptr);
71f95118
WD
64 }
65 return -1;
66}
67
68
69int
7205e407 70fat_register_device(block_dev_desc_t *dev_desc, int part_no)
71f95118 71{
7205e407 72 unsigned char buffer[SECTOR_SIZE];
566a494f 73 disk_partition_t info;
7205e407
WD
74
75 if (!dev_desc->block_read)
76 return -1;
566a494f 77 cur_dev = dev_desc;
7205e407
WD
78 /* check if we have a MBR (on floppies we have only a PBR) */
79 if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
80 printf ("** Can't read from device %d **\n", dev_desc->dev);
81 return -1;
82 }
83 if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
84 buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
85 /* no signature found */
86 return -1;
87 }
dd60d122
JL
88#if (defined(CONFIG_CMD_IDE) || \
89 defined(CONFIG_CMD_SCSI) || \
90 defined(CONFIG_CMD_USB) || \
02df4a27
AF
91 defined(CONFIG_MMC) || \
92 defined(CONFIG_SYSTEMACE) )
93 /* First we assume, there is a MBR */
94 if (!get_partition_info (dev_desc, part_no, &info)) {
95 part_offset = info.start;
96 cur_part = part_no;
97 } else if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3)) {
98 /* ok, we assume we are on a PBR only */
99 cur_part = 1;
100 part_offset = 0;
101 } else {
102 printf ("** Partition %d not valid on device %d **\n",
bf1060ea 103 part_no, dev_desc->dev);
02df4a27
AF
104 return -1;
105 }
106
7205e407 107#else
02df4a27
AF
108 if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) {
109 /* ok, we assume we are on a PBR only */
110 cur_part = 1;
111 part_offset = 0;
112 info.start = part_offset;
113 } else {
114 /* FIXME we need to determine the start block of the
115 * partition where the DOS FS resides. This can be done
116 * by using the get_partition_info routine. For this
117 * purpose the libpart must be included.
118 */
119 part_offset = 32;
120 cur_part = 1;
bf1060ea 121 }
02df4a27 122#endif
71f95118
WD
123 return 0;
124}
125
126
127/*
128 * Get the first occurence of a directory delimiter ('/' or '\') in a string.
129 * Return index into string if found, -1 otherwise.
130 */
131static int
132dirdelim(char *str)
133{
134 char *start = str;
135
136 while (*str != '\0') {
137 if (ISDIRDELIM(*str)) return str - start;
138 str++;
139 }
140 return -1;
141}
142
143
144/*
145 * Match volume_info fs_type strings.
146 * Return 0 on match, -1 otherwise.
147 */
148static int
149compare_sign(char *str1, char *str2)
150{
151 char *end = str1+SIGNLEN;
152
153 while (str1 != end) {
154 if (*str1 != *str2) {
155 return -1;
156 }
157 str1++;
158 str2++;
159 }
160
161 return 0;
162}
163
164
165/*
166 * Extract zero terminated short name from a directory entry.
167 */
168static void get_name (dir_entry *dirent, char *s_name)
169{
170 char *ptr;
171
172 memcpy (s_name, dirent->name, 8);
173 s_name[8] = '\0';
174 ptr = s_name;
175 while (*ptr && *ptr != ' ')
176 ptr++;
177 if (dirent->ext[0] && dirent->ext[0] != ' ') {
178 *ptr = '.';
179 ptr++;
180 memcpy (ptr, dirent->ext, 3);
181 ptr[3] = '\0';
182 while (*ptr && *ptr != ' ')
183 ptr++;
184 }
185 *ptr = '\0';
186 if (*s_name == DELETED_FLAG)
187 *s_name = '\0';
188 else if (*s_name == aRING)
189