summaryrefslogtreecommitdiff
path: root/firmware/common
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common')
-rw-r--r--firmware/common/dir.c83
-rw-r--r--firmware/common/disk.c26
-rw-r--r--firmware/common/file.c3
3 files changed, 97 insertions, 15 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 1bad9327f6..5fa5f9db6e 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -23,11 +23,48 @@
23#include "fat.h" 23#include "fat.h"
24#include "dir.h" 24#include "dir.h"
25#include "debug.h" 25#include "debug.h"
26#include "atoi.h"
26 27
27#define MAX_OPEN_DIRS 8 28#define MAX_OPEN_DIRS 8
28 29
29static DIR opendirs[MAX_OPEN_DIRS]; 30static DIR opendirs[MAX_OPEN_DIRS];
30 31
32#ifdef HAVE_MULTIVOLUME
33
34/* how to name volumes, first char must be outside of legal file names,
35 a number gets appended to enumerate, if applicable */
36#ifdef HAVE_MMC
37static const char* vol_names = ":MMC";
38#else
39static const char* vol_names = ":HD";
40#endif
41
42/* returns on which volume this is, and copies the reduced name
43 (sortof a preprocessor for volume-decorated pathnames) */
44static int strip_volume(const char* name, char* namecopy)
45{
46 int volume = 0;
47
48 if (name[1] == vol_names[0] ) /* a colon identifies our volumes */
49 {
50 const char* temp;
51 temp = name + 1 + strlen(vol_names); /* behind special name */
52 volume = atoi(temp); /* number is following */
53 temp = strchr(temp, '/'); /* search for slash behind */
54 if (temp != NULL)
55 name = temp; /* use the part behind the volume */
56 else
57 name = "/"; /* else this must be the root dir */
58 }
59
60 strncpy(namecopy, name, MAX_PATH);
61 namecopy[MAX_PATH-1] = '\0';
62
63 return volume;
64}
65#endif /* #ifdef HAVE_MULTIVOLUME */
66
67
31DIR* opendir(const char* name) 68DIR* opendir(const char* name)
32{ 69{
33 char namecopy[MAX_PATH]; 70 char namecopy[MAX_PATH];
@@ -35,6 +72,9 @@ DIR* opendir(const char* name)
35 char* end; 72 char* end;
36 struct fat_direntry entry; 73 struct fat_direntry entry;
37 int dd; 74 int dd;
75#ifdef HAVE_MULTIVOLUME
76 int volume;
77#endif
38 78
39 /* find a free dir descriptor */ 79 /* find a free dir descriptor */
40 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ ) 80 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ )
@@ -55,15 +95,21 @@ DIR* opendir(const char* name)
55 return NULL; 95 return NULL;
56 } 96 }
57 97
58 if ( fat_opendir(&(opendirs[dd].fatdir), 0, NULL) < 0 ) { 98#ifdef HAVE_MULTIVOLUME
99 /* try to extract a heading volume name, if present */
100 volume = strip_volume(name, namecopy);
101 opendirs[dd].volumecounter = 0;
102#else
103 strncpy(namecopy,name,sizeof(namecopy)); /* just copy */
104 namecopy[sizeof(namecopy)-1] = '\0';
105#endif
106
107 if ( fat_opendir(IF_MV2(volume,) &(opendirs[dd].fatdir), 0, NULL) < 0 ) {
59 DEBUGF("Failed opening root dir\n"); 108 DEBUGF("Failed opening root dir\n");
60 opendirs[dd].busy = false; 109 opendirs[dd].busy = false;
61 return NULL; 110 return NULL;
62 } 111 }
63 112
64 strncpy(namecopy,name,sizeof(namecopy));
65 namecopy[sizeof(namecopy)-1] = 0;
66
67 for ( part = strtok_r(namecopy, "/", &end); part; 113 for ( part = strtok_r(namecopy, "/", &end); part;
68 part = strtok_r(NULL, "/", &end)) { 114 part = strtok_r(NULL, "/", &end)) {
69 /* scan dir for name */ 115 /* scan dir for name */
@@ -76,7 +122,8 @@ DIR* opendir(const char* name)
76 if ( (entry.attr & FAT_ATTR_DIRECTORY) && 122 if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
77 (!strcasecmp(part, entry.name)) ) { 123 (!strcasecmp(part, entry.name)) ) {
78 opendirs[dd].parent_dir = opendirs[dd].fatdir; 124 opendirs[dd].parent_dir = opendirs[dd].fatdir;
79 if ( fat_opendir(&(opendirs[dd].fatdir), 125 if ( fat_opendir(IF_MV2(volume,)
126 &(opendirs[dd].fatdir),
80 entry.firstcluster, 127 entry.firstcluster,
81 &(opendirs[dd].parent_dir)) < 0 ) { 128 &(opendirs[dd].parent_dir)) < 0 ) {
82 DEBUGF("Failed opening dir '%s' (%d)\n", 129 DEBUGF("Failed opening dir '%s' (%d)\n",
@@ -84,6 +131,9 @@ DIR* opendir(const char* name)
84 opendirs[dd].busy = false; 131 opendirs[dd].busy = false;
85 return NULL; 132 return NULL;
86 } 133 }
134#ifdef HAVE_MULTIVOLUME
135 opendirs[dd].volumecounter = -1; /* n.a. to subdirs */
136#endif
87 break; 137 break;
88 } 138 }
89 } 139 }
@@ -102,7 +152,28 @@ struct dirent* readdir(DIR* dir)
102{ 152{
103 struct fat_direntry entry; 153 struct fat_direntry entry;
104 struct dirent* theent = &(dir->theent); 154 struct dirent* theent = &(dir->theent);
105 155#ifdef HAVE_MULTIVOLUME
156 /* Volumes (secondary file systems) get inserted into the root directory
157 of the first volume, since we have no separate top level. */
158 if (dir->volumecounter >= 0 /* on a root dir */
159 && dir->volumecounter < NUM_VOLUMES /* in range */
160 && dir->fatdir.file.volume == 0) /* at volume 0 */
161 { /* fake special directories, which don't really exist, but
162 will get redirected upon opendir() */
163 while (++dir->volumecounter < NUM_VOLUMES)
164 {
165 if (fat_ismounted(dir->volumecounter))
166 {
167 memset(theent, 0, sizeof(*theent));
168 theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
169 snprintf(theent->d_name, sizeof(theent->d_name),
170 "%s%d", vol_names, dir->volumecounter);
171 return theent;
172 }
173 }
174 }
175#endif
176 /* normal directory entry fetching follows here */
106 if (fat_getnext(&(dir->fatdir),&entry) < 0) 177 if (fat_getnext(&(dir->fatdir),&entry) < 0)
107 return NULL; 178 return NULL;
108 179
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index b85f460a69..cfe15984f9 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -41,12 +41,22 @@
41 41
42static struct partinfo part[8]; 42static struct partinfo part[8];
43 43
44struct partinfo* disk_init(void) 44struct partinfo* disk_init(IF_MV_NONVOID(int drive))
45{ 45{
46 int i; 46 int i;
47 unsigned char sector[512]; 47 unsigned char sector[512];
48#ifdef HAVE_MULTIVOLUME
49 /* For each drive, start at a different position, in order not to destroy
50 the first entry of drive 0.
51 That one is needed to calculate config sector position. */
52 struct partinfo* pinfo = &part[drive*4];
53 if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
54 return NULL; /* out of space in table */
55#else
56 struct partinfo* pinfo = part;
57#endif
48 58
49 ata_read_sectors(0,1,&sector); 59 ata_read_sectors(IF_MV2(drive,) 0,1,&sector);
50 60
51 /* check that the boot sector is initialized */ 61 /* check that the boot sector is initialized */
52 if ( (sector[510] != 0x55) || 62 if ( (sector[510] != 0x55) ||
@@ -58,20 +68,20 @@ struct partinfo* disk_init(void)
58 /* parse partitions */ 68 /* parse partitions */
59 for ( i=0; i<4; i++ ) { 69 for ( i=0; i<4; i++ ) {
60 unsigned char* ptr = sector + 0x1be + 16*i; 70 unsigned char* ptr = sector + 0x1be + 16*i;
61 part[i].type = ptr[4]; 71 pinfo[i].type = ptr[4];
62 part[i].start = BYTES2INT32(ptr, 8); 72 pinfo[i].start = BYTES2INT32(ptr, 8);
63 part[i].size = BYTES2INT32(ptr, 12); 73 pinfo[i].size = BYTES2INT32(ptr, 12);
64 74
65 DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n", 75 DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n",
66 i,part[i].type,part[i].start,part[i].size); 76 i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
67 77
68 /* extended? */ 78 /* extended? */
69 if ( part[i].type == 5 ) { 79 if ( pinfo[i].type == 5 ) {
70 /* not handled yet */ 80 /* not handled yet */
71 } 81 }
72 } 82 }
73 83
74 return part; 84 return pinfo;
75} 85}
76 86
77struct partinfo* disk_partinfo(int partition) 87struct partinfo* disk_partinfo(int partition)
diff --git a/firmware/common/file.c b/firmware/common/file.c
index 81b5a194c0..6714b9982c 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -132,7 +132,8 @@ int open(const char* pathname, int flags)
132 /* scan dir for name */ 132 /* scan dir for name */
133 while ((entry = readdir(dir))) { 133 while ((entry = readdir(dir))) {
134 if ( !strcasecmp(name, entry->d_name) ) { 134 if ( !strcasecmp(name, entry->d_name) ) {
135 fat_open(entry->startcluster, 135 fat_open(IF_MV2(dir->fatdir.file.volume,)
136 entry->startcluster,
136 &(file->fatfile), 137 &(file->fatfile),
137 &(dir->fatdir)); 138 &(dir->fatdir));
138 file->size = file->trunc ? 0 : entry->size; 139 file->size = file->trunc ? 0 : entry->size;