]> Git Repo - u-boot.git/blame - fs/fat/fat.c
Merge branch 'Makefile' of git://git.denx.de/u-boot-arm
[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
71f95118
WD
34/*
35 * Convert a string to lowercase.
36 */
37static void
38downcase(char *str)
39{
40 while (*str != '\0') {
41 TOLOWER(*str);
42 str++;
43 }
44}
45
7205e407
WD
46static block_dev_desc_t *cur_dev = NULL;
47static unsigned long part_offset = 0;
48static int cur_part = 1;
49
50#define DOS_PART_TBL_OFFSET 0x1be
51#define DOS_PART_MAGIC_OFFSET 0x1fe
52#define DOS_FS_TYPE_OFFSET 0x36
71f95118
WD
53
54int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr)
55{
7205e407
WD
56 startblock += part_offset;
57 if (cur_dev == NULL)
58 return -1;
59 if (cur_dev->block_read) {
3e3b9569
PP
60 return cur_dev->block_read (cur_dev->dev
61 , startblock, getsize, (unsigned long *)bufptr);
71f95118
WD
62 }
63 return -1;
64}
65
66
67int
7205e407 68fat_register_device(block_dev_desc_t *dev_desc, int part_no)
71f95118 69{
7205e407 70 unsigned char buffer[SECTOR_SIZE];
566a494f 71 disk_partition_t info;
7205e407
WD
72
73 if (!dev_desc->block_read)
74 return -1;
566a494f 75 cur_dev = dev_desc;
7205e407
WD
76 /* check if we have a MBR (on floppies we have only a PBR) */
77 if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
78 printf ("** Can't read from device %d **\n", dev_desc->dev);
79 return -1;
80 }
81 if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
82 buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
83 /* no signature found */
84 return -1;
85 }
dd60d122
JL
86#if (defined(CONFIG_CMD_IDE) || \
87 defined(CONFIG_CMD_SCSI) || \
88 defined(CONFIG_CMD_USB) || \
02df4a27
AF
89 defined(CONFIG_MMC) || \
90 defined(CONFIG_SYSTEMACE) )
91 /* First we assume, there is a MBR */
92 if (!get_partition_info (dev_desc, part_no, &info)) {
93 part_offset = info.start;
94 cur_part = part_no;
95 } else if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3)) {
96 /* ok, we assume we are on a PBR only */
97 cur_part = 1;
98 part_offset = 0;
99 } else {
100 printf ("** Partition %d not valid on device %d **\n",
bf1060ea 101 part_no, dev_desc->dev);
02df4a27
AF
102 return -1;
103 }
104
7205e407 105#else
02df4a27
AF
106 if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) {
107 /* ok, we assume we are on a PBR only */
108 cur_part = 1;
109 part_offset = 0;
110 info.start = part_offset;
111 } else {
112 /* FIXME we need to determine the start block of the
113 * partition where the DOS FS resides. This can be done
114 * by using the get_partition_info routine. For this
115 * purpose the libpart must be included.
116 */
117 part_offset = 32;
118 cur_part = 1;
bf1060ea 119 }
02df4a27 120#endif
71f95118
WD
121 return 0;
122}
123
124
125/*
126 * Get the first occurence of a directory delimiter ('/' or '\') in a string.
127 * Return index into string if found, -1 otherwise.
128 */
129static int
130dirdelim(char *str)
131{
132 char *start = str;
133
134 while (*str != '\0') {
135 if (ISDIRDELIM(*str)) return str - start;
136 str++;
137 }
138 return -1;
139}
140
141
142/*
143 * Match volume_info fs_type strings.
144 * Return 0 on match, -1 otherwise.
145 */
146static int
147compare_sign(char *str1, char *str2)
148{
149 char *end = str1+SIGNLEN;
150
151 while (str1 != end) {
152 if (*str1 != *str2) {
153 return -1;
154 }
155 str1++;
156 str2++;
157 }
158
159 return 0;
160}
161
162
163/*
164 * Extract zero terminated short name from a directory entry.
165 */
166static void get_name (dir_entry *dirent, char *s_name)
167{
168 char *ptr;
169
170 memcpy (s_name, dirent->name, 8);
171 s_name[8] = '\0';
172 ptr = s_name;
173 while (*ptr && *ptr != ' ')
174 ptr++;
175 if (dirent->ext[0] && dirent->ext[0] != ' ') {
176 *ptr = '.';
177 ptr++;
178 memcpy (ptr, dirent->ext, 3);
179 ptr[3] = '\0';
180 while (*ptr && *ptr != ' ')
181 ptr++;
182 }
183 *ptr = '\0';
184 if (*s_name == DELETED_FLAG)
185 *s_name = '\0';
186 else if (*s_name == aRING)
187