revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-sam440 / boot / parthenope / src / dos.c
blob9a27001b4dd1611c38cc64816cce69a7df8fa429
1 /* dos.c */
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.
20 #include "context.h"
21 #include "rdb.h"
22 #include "dos.h"
24 #define DOS_ID (('D' << 24) | ('O' << 16) | ('S' << 8))
26 struct DosBootBlock {
27 uint32_t id;
28 uint32_t checksum;
29 uint32_t rootblock;
32 #define DBB(buf) ((struct DosBootBlock *)(buf))
34 #define HT_SIZE 72
35 #define BM_SIZE 25
36 #define MAXNAMELEN 30
38 #define T_HEADER 2
39 #define ST_ROOT 1
40 #define ST_DIR 2
41 #define ST_FILE -3
42 #define ST_LFILE -4
43 #define ST_LDIR 4
44 #define ST_LSOFT 3
45 #define T_LIST 16
46 #define T_DATA 8
47 #define T_DIRC 33
49 struct DosDirBlock {
50 uint32_t type;
51 uint32_t header_key;
52 uint32_t high_seq;
53 uint32_t hash_table_size;
54 uint32_t first_data;
55 uint32_t checksum;
56 uint32_t hash_table[HT_SIZE];
57 uint32_t bitmap_flag;
58 uint32_t bitmap_page[BM_SIZE];
59 uint32_t bitmap_ext;
60 uint32_t ctime_days;
61 uint32_t ctime_mins;
62 uint32_t ctime_ticks;
63 uint8_t name_len;
64 char name[MAXNAMELEN+1];
65 uint8_t resv[8];
66 uint32_t atime_days;
67 uint32_t atime_mins;
68 uint32_t atime_ticks;
69 uint32_t cotime_days;
70 uint32_t cotime_mins;
71 uint32_t cotime_ticks;
72 uint32_t next_same_hash;
73 uint32_t parent;
74 uint32_t extension;
75 uint32_t sub_type;
78 #define DDB(buf) ((struct DosDirBlock *)(buf))
80 #define MAX_DATABLK 72
81 #define MAXCOMMENTLEN 79
83 struct DosFileBlock {
84 uint32_t type;
85 uint32_t header_key;
86 uint32_t high_seq;
87 uint32_t hash_table_size;
88 uint32_t first_data;
89 uint32_t checksum;
90 uint32_t data_blocks[MAX_DATABLK];
91 uint32_t resv[2];
92 uint32_t access;
93 uint32_t byte_size;
94 uint8_t comment_len;
95 char comment[MAXCOMMENTLEN+1];
96 uint8_t resv_1[11];
97 uint32_t days;
98 uint32_t mins;
99 uint32_t ticks;
100 uint8_t name_len;
101 char name[MAXNAMELEN+1];
102 uint32_t resv_2;
103 uint32_t real;
104 uint32_t next_link;
105 uint32_t resv_3[5];
106 uint32_t next_same_hash;
107 uint32_t parent;
108 uint32_t extension;
109 uint32_t sub_type;
112 struct DosDataBlock {
113 uint32_t type;
114 uint32_t header_key;
115 uint32_t seq_num;
116 uint32_t data_size; /* in bytes */
117 uint32_t next_data;
118 uint32_t check_sum;
119 uint8_t data[];
122 #define DFB(buf) ((struct DosFileBlock *)(buf))
124 typedef struct {
125 int (*load_file) (void *this, char *filename, void *buffer);
126 void (*destroy) (void *this);
127 struct RdbPartition *partition;
128 char *buff;
129 struct DosDataBlock *data;
130 uint32_t rootblock;
131 uint32_t blocksize;
132 int capabilities;
133 } dos_boot_dev_t;
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)
143 #if DEBUG
144 printf("dos_loadsector(%d) => 0x%08x\n", block, (self->partition->info->start
145 + (block * (self->blocksize / 512))) * 512);
146 #endif
147 return loadsector(self->partition->info->start
148 + (block * (self->blocksize / 512)),
149 self->partition->info->blksz, self->blocksize / 512,
150 buffer);
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)
167 int rc = 0;
169 while (len && rc == 0 ) {
170 if (!*a && !*b)
171 return 0;
172 if (isINTL(self))
173 rc = intlupper(*a) - intlupper(*b);
174 else
175 rc = dosupper(*a) - dosupper(*b);
176 a++;
177 b++;
178 len--;
181 return rc;
184 static int dos_hash(dos_boot_dev_t * self, const char *name)
186 uint32_t hash, len;
187 char upper;
188 int i;
190 len = hash = strlen(name);
191 for (i = 0; i < len; i++) {
192 if (isINTL(self))
193 upper = intlupper(name[i]);
194 else
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;
205 uint8_t *buff;
207 strncpy(path, filename, sizeof(path));
208 path[sizeof(path)-1] = 0;
210 printf("Load %s -> 0x%lx\n", filename, (unsigned long)filebuffer);
212 dp = path;
214 buff = self->buff;
215 dos_loadsector(self, self->rootblock, buff);
217 while (dp) {
218 uint32_t sector;
219 int dp_len;
221 fp = strchr(dp, '/');
222 if (fp)
223 *(fp++) = 0;
225 dp_len = strlen(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);
234 return -1;
237 if ((DDB(buff)->name_len == dp_len) &&
238 (dos_strncmp(self, dp, DDB(buff)->name, dp_len) == 0)) {
239 break;
242 sector = DDB(buff)->next_same_hash;
245 /* No such file */
246 if (sector == 0)
247 return -1;
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;
254 if (fp != NULL) {
255 printf(".. was expecting a directory\n");
256 return -1;
258 size = total = DFB(buff)->byte_size;
260 if (filebuffer == NULL)
261 return size;
263 for (block = 0; size > 0; block++) {
264 int tocopy;
265 void *data;
267 if (block == MAX_DATABLK) {
268 block = 0;
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);
275 count++;
277 if (isOFS(self)) {
278 tocopy = (size > self->data->data_size) ? self->data->data_size : size;
279 data = &self->data->data[0];
281 } else {
282 tocopy = (size > self->blocksize) ? self->blocksize : size;
283 data = self->data;
286 memcpy(filebuffer, data, tocopy);
287 filebuffer += tocopy;
288 size -= tocopy;
290 printf(".. %lu bytes\n", (unsigned long)total);
291 return total;
294 /* Header is in 'buff' at this point */
295 if (DDB(buff)->sub_type != ST_DIR) {
296 return -1;
299 dp = fp;
302 return -1;
305 static int dos_destroy(dos_boot_dev_t * this)
307 free(this);
309 return 0;
313 boot_dev_t *dos_create(struct RdbPartition *partition)
315 dos_boot_dev_t *boot;
316 void *buffer;
318 boot = malloc(sizeof(dos_boot_dev_t) + partition->info->blksz * 2);
319 if (boot == NULL) {
320 printf("** dos_create: out of memory\n");
321 return NULL;
324 boot->partition = partition;
326 boot->buff = (void *)&boot[1];
327 boot->data = (void *)(boot->buff + partition->info->blksz);
329 buffer = boot->buff;
330 loadsector(boot->partition->info->start, boot->partition->info->blksz,
331 1, buffer);
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);
335 free(boot);
336 return NULL;
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);
350 free(boot);
351 return NULL;
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;