]> Git Repo - J-u-boot.git/blame - fs/fat/fat.c
[PCS440EP] upgrade the PCS440EP board:
[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
WD
33
34#if (CONFIG_COMMANDS & CFG_CMD_FAT)
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 }
b0d8f5bf
PP
88#if ((CONFIG_COMMANDS & CFG_CMD_IDE) || \
89 (CONFIG_COMMANDS & CFG_CMD_SCSI) || \
90 (CONFIG_COMMANDS & CFG_CMD_USB) || \
566a494f 91 (defined(CONFIG_MMC)) || \
b0d8f5bf 92 defined(CONFIG_SYSTEMACE) )
566a494f
HS
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", part_no, dev_desc->dev);
103 return -1;
104 }
7205e407 105#else
566a494f
HS
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 {
7205e407
WD
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 */
566a494f 117 part_offset = 32;
7205e407 118 cur_part = 1;
7205e407 119 }
566a494f 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