3 /* <project_name> -- <project_description>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #define DOS_ID (('D' << 24) | ('O' << 16) | ('S' << 8))
32 #define DBB(buf) ((struct DosBootBlock *)(buf))
53 uint32_t hash_table_size
;
56 uint32_t hash_table
[HT_SIZE
];
58 uint32_t bitmap_page
[BM_SIZE
];
64 char name
[MAXNAMELEN
+1];
71 uint32_t cotime_ticks
;
72 uint32_t next_same_hash
;
78 #define DDB(buf) ((struct DosDirBlock *)(buf))
80 #define MAX_DATABLK 72
81 #define MAXCOMMENTLEN 79
87 uint32_t hash_table_size
;
90 uint32_t data_blocks
[MAX_DATABLK
];
95 char comment
[MAXCOMMENTLEN
+1];
101 char name
[MAXNAMELEN
+1];
106 uint32_t next_same_hash
;
112 struct DosDataBlock
{
116 uint32_t data_size
; /* in bytes */
122 #define DFB(buf) ((struct DosFileBlock *)(buf))
125 int (*load_file
) (void *this, char *filename
, void *buffer
);
126 void (*destroy
) (void *this);
127 struct RdbPartition
*partition
;
129 struct DosDataBlock
*data
;
135 #define isDIRCACHE(self) ((self)->capabilities & 4)
136 #define isINTL(self) ((self)->capabilities & 2)
137 #define isFFS(self) ((self)->capabilities & 1)
138 #define isOFS(self) (!isFFS(self))
141 static int dos_loadsector(dos_boot_dev_t
*self
, uint32_t block
, void *buffer
)
144 printf("dos_loadsector(%d) => 0x%08x\n", block
, (self
->partition
->info
->start
145 + (block
* (self
->blocksize
/ 512))) * 512);
147 return loadsector(self
->partition
->info
->start
148 + (block
* (self
->blocksize
/ 512)),
149 self
->partition
->info
->blksz
, self
->blocksize
/ 512,
153 static inline char intlupper(char in
)
155 unsigned char c
= (unsigned char)in
;
156 return (c
>='a' && c
<='z') || (c
>=224 && c
<=254 && c
!=247) ? c
- ('a'-'A') : c
;
159 static inline char dosupper(char in
)
161 unsigned char c
= (unsigned char)in
;
162 return (c
>='a' && c
<='z') ? c
- ('a'-'A') : c
;
165 static int dos_strncmp(dos_boot_dev_t
* self
, const char *a
, const char *b
, int len
)
169 while (len
&& rc
== 0 ) {
173 rc
= intlupper(*a
) - intlupper(*b
);
175 rc
= dosupper(*a
) - dosupper(*b
);
184 static int dos_hash(dos_boot_dev_t
* self
, const char *name
)
190 len
= hash
= strlen(name
);
191 for (i
= 0; i
< len
; i
++) {
193 upper
= intlupper(name
[i
]);
195 upper
= dosupper(name
[i
]);
196 hash
= (hash
* 13 + (unsigned char)upper
) & 0x7ff;
199 return hash
% HT_SIZE
;
202 static int dos_loadfile(dos_boot_dev_t
* self
, char *filename
, void *filebuffer
)
204 char path
[256], *fp
, *dp
;
207 strncpy(path
, filename
, sizeof(path
));
208 path
[sizeof(path
)-1] = 0;
210 printf("Load %s -> 0x%lx\n", filename
, (unsigned long)filebuffer
);
215 dos_loadsector(self
, self
->rootblock
, buff
);
221 fp
= strchr(dp
, '/');
227 sector
= DDB(buff
)->hash_table
[dos_hash(self
, dp
)];
229 while (sector
!= 0) {
230 dos_loadsector(self
, sector
, buff
);
232 if (DDB(buff
)->type
!= T_HEADER
) {
233 printf(".. corrupt T_HEADER at sector %d\n", sector
);
237 if ((DDB(buff
)->name_len
== dp_len
) &&
238 (dos_strncmp(self
, dp
, DDB(buff
)->name
, dp_len
) == 0)) {
242 sector
= DDB(buff
)->next_same_hash
;
249 printf(".. found %s, %d\n", dp
, DDB(buff
)->sub_type
);
251 /* Header is in 'buff' at this point */
252 if (DDB(buff
)->sub_type
== ST_FILE
) {
253 int total
= 0, size
, block
, count
= 0;
255 printf(".. was expecting a directory\n");
258 size
= total
= DFB(buff
)->byte_size
;
260 if (filebuffer
== NULL
)
263 for (block
= 0; size
> 0; block
++) {
267 if (block
== MAX_DATABLK
) {
269 dos_loadsector(self
, DFB(buff
)->extension
, buff
);
272 dos_loadsector(self
, DFB(buff
)->data_blocks
[(MAX_DATABLK
- 1) - block
], self
->data
);
273 if ((count
& 0xf) == 0)
274 printf("%d%%\r", (total
- size
)*100/total
);
278 tocopy
= (size
> self
->data
->data_size
) ? self
->data
->data_size
: size
;
279 data
= &self
->data
->data
[0];
282 tocopy
= (size
> self
->blocksize
) ? self
->blocksize
: size
;
286 memcpy(filebuffer
, data
, tocopy
);
287 filebuffer
+= tocopy
;
290 printf(".. %lu bytes\n", (unsigned long)total
);
294 /* Header is in 'buff' at this point */
295 if (DDB(buff
)->sub_type
!= ST_DIR
) {
305 static int dos_destroy(dos_boot_dev_t
* this)
313 boot_dev_t
*dos_create(struct RdbPartition
*partition
)
315 dos_boot_dev_t
*boot
;
318 boot
= malloc(sizeof(dos_boot_dev_t
) + partition
->info
->blksz
* 2);
320 printf("** dos_create: out of memory\n");
324 boot
->partition
= partition
;
326 boot
->buff
= (void *)&boot
[1];
327 boot
->data
= (void *)(boot
->buff
+ partition
->info
->blksz
);
330 loadsector(boot
->partition
->info
->start
, boot
->partition
->info
->blksz
,
332 if ((DBB(buffer
)->id
& 0xffffff00) != DOS_ID
) {
333 printf("** Bad dos partition or disk - %d:%d **\n",
334 boot
->partition
->disk
, boot
->partition
->partition
);
339 boot
->capabilities
= ((uint8_t *)buffer
)[3];
340 boot
->rootblock
= DBB(buffer
)->rootblock
;
341 boot
->blocksize
= boot
->partition
->info
->blksz
;
343 dos_loadsector(boot
, boot
->rootblock
, buffer
);
344 printf("sizeof(DDB) = %d\n", sizeof(*DDB(buffer
)));
345 printf(" type = %d, sub_type = %d\n", DDB(buffer
)->type
, DDB(buffer
)->sub_type
);
347 if (DDB(buffer
)->type
!= T_HEADER
|| DDB(buffer
)->sub_type
!= ST_ROOT
) {
348 printf("** Root node not found - %d:%d **\n",
349 boot
->partition
->disk
, boot
->partition
->partition
);
354 printf("Found DOS\\%2x partition! Name: %*s\n", boot
->capabilities
,
355 DDB(buffer
)->name_len
, (char *)DDB(buffer
)->name
);
357 boot
->load_file
= (int (*)(void *, char *, void *))dos_loadfile
;
358 boot
->destroy
= (void (*)(void *))dos_destroy
;
360 return (boot_dev_t
*) boot
;