Warning, cross-references for /kernel/fs/iso9660/fsys_iso9660.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "kernel.h"
0019 #include "mem/mem.h"
0020 #include "fs/filesys.h"
0021 #include "arch/i386.h"
0022 #include "util/printf.h"
0023 #include "drivers/ata/ata.h"
0024
0025 void
0026 iso9660_date_record (uint8 * buf)
0027 {
0028 com1_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%.2s.%.2s %02d",
0029 buf, buf + 4, buf + 6,
0030 buf + 8, buf + 10, buf + 12, buf + 14,
0031 *((signed char *) buf + 16) / 4);
0032 }
0033
0034
0035 void
0036 iso9660_show_dir_record (uint8 * r)
0037 {
0038 iso9660_dir_record *d = (iso9660_dir_record *) r;
0039 int i;
0040 com1_printf ("dir_record\n length=%d first_sector=%X data_length=%d\n",
0041 d->length, d->first_sector, d->data_length);
0042 com1_printf (" %d-%02d-%02d %02d:%02d:%02d\n",
0043 d->years_since_1900 + 1900, d->month, d->day,
0044 d->hour, d->minute, d->second);
0045 com1_printf (" flags: %s %s %s %s %s %s\n",
0046 d->flag_hidden ? "hidden" : "regular",
0047 d->flag_dir ? "dir" : "file",
0048 d->flag_assoc ? "assoc" : "noassoc",
0049 d->flag_recfmtspec ? "recfmtspec" : "norecfmtspec",
0050 d->flag_permspec ? "permspec" : "nopermspec",
0051 d->flag_notfinal ? "notfinal" : "final");
0052 com1_printf (" id len=%d: ", d->identifier_length);
0053 for (i = 0; i < d->identifier_length; i++)
0054 if (d->identifier[i])
0055 com1_putc (d->identifier[i]);
0056 com1_putc ('\n');
0057 }
0058
0059 void
0060 iso9660_walk_tree (uint32 bus, uint32 drive,
0061 iso9660_dir_record * d, int depth)
0062 {
0063 int i, len;
0064
0065 for (i = 0; i < depth; i++)
0066 com1_puts (" ");
0067
0068 if (d->identifier[0] == 0) {
0069 com1_puts (".\n");
0070 if (depth > 0)
0071 return;
0072 } else if (d->identifier[0] == 1) {
0073 com1_puts ("..\n");
0074 if (depth > 0)
0075 return;
0076 } else {
0077 for (i = 0; i < d->identifier_length; i++)
0078 if (d->identifier[i])
0079 com1_putc (d->identifier[i]);
0080 com1_puts ("\n");
0081 }
0082
0083 if (d->flag_dir) {
0084 uint32 frame = alloc_phys_frame ();
0085 uint8 *sector = map_virtual_page (frame | 3);
0086
0087 uint32 secnum = d->first_sector;
0088 uint32 num_bytes = d->data_length;
0089 uint32 count;
0090
0091 for (count = 0; count < num_bytes;) {
0092 if (count % ATAPI_SECTOR_SIZE == 0) {
0093
0094 len = atapi_drive_read_sector (bus, drive, secnum, sector);
0095 if (len < 0) {
0096 panic ("CD ROM READ ERROR\n");
0097 }
0098 secnum++;
0099 d = (iso9660_dir_record *) sector;
0100 }
0101
0102 iso9660_walk_tree (bus, drive, d, depth + 1);
0103
0104 count += d->length;
0105 d = (iso9660_dir_record *) ((uint8 *) d + d->length);
0106
0107
0108 while (*((uint8 *)d) == 0 && (count % ATAPI_SECTOR_SIZE) != 0) {
0109 d = (iso9660_dir_record *) (((uint8 *)d) + 1);
0110 count++;
0111 }
0112 }
0113 unmap_virtual_page (sector);
0114 free_phys_frame (frame);
0115 }
0116 }
0117
0118
0119 int
0120 iso9660_mount (uint32 bus, uint32 drive, iso9660_mounted_info * mi)
0121 {
0122 uint32 frame = alloc_phys_frame ();
0123 uint8 *page = map_virtual_page (frame | 3);
0124 int len;
0125
0126
0127
0128
0129 len = atapi_drive_read_sector (bus, drive, 16, page);
0130
0131 if (len < 0) {
0132 com1_printf ("CD-ROM read error\n");
0133 return -1;
0134 }
0135 #if 0
0136 {
0137 int i, j;
0138 com1_printf ("Read %d bytes.\n", len);
0139
0140 for (i = 0; i < 128; i++) {
0141 for (j = 0; j < 16; j++) {
0142 com1_printf ("%.2X ", page[i * 16 + j]);
0143 }
0144 com1_printf ("\n");
0145 }
0146 }
0147
0148 com1_printf ("Sys ID: %.32s\n", page + 8);
0149 com1_printf ("Vol ID: %.32s\n", page + 40);
0150 com1_printf ("# Sectors: %.8X\n", *(uint32 *) (page + 80));
0151 com1_printf ("Path Table: len=%.8X fst=", *(uint32 *) (page + 132));
0152 com1_printf ("%.8X snd=%.8X\n", *(uint32 *) (page + 140),
0153 *(uint32 *) (page + 144));
0154
0155 iso9660_show_dir_record (page + 156);
0156 com1_printf ("Vol Set ID: %.128s\n", page + 190);
0157 com1_printf ("Pub ID: %.128s\n", page + 318);
0158 com1_printf ("Preparer ID: %.128s\n", page + 318 + 128);
0159 com1_printf ("Application ID: %.128s\n", page + 318 + 256);
0160 com1_printf ("Copyright File ID: %.37s\n", page + 318 + 384);
0161 com1_printf ("Abstract File ID: %.37s\n", page + 318 + 384 + 37);
0162 com1_printf ("Bib File ID: %.37s\n", page + 318 + 384 + 37 + 37);
0163 com1_printf ("Creation Date: ");
0164 iso9660_date_record (page + 318 + 384 + 37 + 37 + 37);
0165 com1_printf ("\n");
0166 com1_printf ("Modification Date: ");
0167 iso9660_date_record (page + 318 + 384 + 37 + 37 + 37 + 17);
0168 com1_printf ("\n");
0169 com1_printf ("Expiration Date: ");
0170 iso9660_date_record (page + 318 + 384 + 37 + 37 + 37 + 34);
0171 com1_printf ("\n");
0172 com1_printf ("Effective Date: ");
0173 iso9660_date_record (page + 318 + 384 + 37 + 37 + 37 + 51);
0174 com1_printf ("\n");
0175
0176 iso9660_walk_tree (bus, drive, (iso9660_dir_record *) (page + 156), 0);
0177
0178 #endif
0179
0180 mi->bus = bus;
0181 mi->drive = drive;
0182 mi->root_dir_sector = ((iso9660_dir_record *) (page + 156))->first_sector;
0183 mi->root_dir_data_length =
0184 ((iso9660_dir_record *) (page + 156))->data_length;
0185
0186 unmap_virtual_page (page);
0187 free_phys_frame (frame);
0188 return 0;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197 static int
0198 iso9660_parse_first_component (char *pathname, int *start, int *end)
0199 {
0200 int i;
0201
0202
0203 for (; pathname[*start] == PATHSEP; (*start)++);
0204
0205 for (i = *start; pathname[i] != PATHSEP && pathname[i] != '\0' && i < *end;
0206 i++);
0207 *end = i;
0208
0209 return (pathname[*end] == '\0' ? 0 : 1);
0210 }
0211
0212 #define TOUPPER(c) ('a' <= c && c <= 'z' ? c + ('A' - 'a') : c)
0213
0214 static int
0215 iso9660_filename_compare (char *a, int a_len, char *b, int b_len)
0216 {
0217 int i = 0;
0218 while (i < a_len && i < b_len) {
0219 if (TOUPPER (a[i]) != TOUPPER (b[i]))
0220 return -1;
0221 i++;
0222 if (a[i] == '.' && i == b_len)
0223 return 0;
0224 else if (i == a_len && b[i] == '.')
0225 return 0;
0226 else if (a[i] == ';' && i == b_len)
0227 return 0;
0228 else if (i == a_len && b[i] == ';')
0229 return 0;
0230 else if (i == a_len && i < b_len)
0231 return -1;
0232 else if (i < a_len && i == b_len)
0233 return -1;
0234 }
0235 return 0;
0236 }
0237
0238
0239 static int
0240 iso9660_search_dir (iso9660_mounted_info * mi,
0241 iso9660_dir_record * d,
0242 char *pathname, int start, int end,
0243 iso9660_dir_record * de)
0244 {
0245 uint32 frame;
0246 uint8 *page;
0247 int len = end - start;
0248
0249 frame = alloc_phys_frame ();
0250 page = map_virtual_page (frame | 3);
0251
0252 uint32 secnum = d->first_sector;
0253 uint32 num_bytes = d->data_length;
0254 uint32 count;
0255
0256 for (count = 0; count < num_bytes;) {
0257 if (count % ATAPI_SECTOR_SIZE == 0) {
0258
0259 if (atapi_drive_read_sector (mi->bus, mi->drive, secnum, page) < 0) {
0260 panic ("CD ROM READ ERROR\n");
0261 }
0262 secnum++;
0263 d = (iso9660_dir_record *) page;
0264 }
0265
0266 if (iso9660_filename_compare (pathname + start, len,
0267 (char *) d->identifier,
0268 d->identifier_length) == 0)
0269 break;
0270
0271
0272 count += d->length;
0273 d = (iso9660_dir_record *) ((uint8 *) d + d->length);
0274
0275
0276 while (*((uint8 *)d) == 0 && (count % ATAPI_SECTOR_SIZE) != 0) {
0277 d = (iso9660_dir_record *) (((uint8 *)d) + 1);
0278 count++;
0279 }
0280 }
0281
0282 if (count >= num_bytes)
0283 goto error;
0284
0285 *de = *d;
0286
0287 unmap_virtual_page (page);
0288 free_phys_frame (frame);
0289 return 0;
0290 error:
0291 unmap_virtual_page (page);
0292 free_phys_frame (frame);
0293 return -1;
0294 }
0295
0296
0297 int
0298 iso9660_open (iso9660_mounted_info * mi, char *pathname, iso9660_handle * h)
0299 {
0300 int len = 0, start = 0, end;
0301 iso9660_dir_record d, de;
0302 d.first_sector = mi->root_dir_sector;
0303 d.data_length = mi->root_dir_data_length;
0304
0305 if (pathname[0] != PATHSEP)
0306 return -1;
0307 while (pathname[len])
0308 len++;
0309
0310 for (;;) {
0311 end = len;
0312 if (iso9660_parse_first_component (pathname, &start, &end) == 0) {
0313 if (start == end)
0314 return -1;
0315
0316 if ((iso9660_search_dir (mi, &d, pathname, start, end, &de)) < 0) {
0317 return -1;
0318 }
0319
0320 h->mount = mi;
0321 h->sector = de.first_sector;
0322 h->offset = 0;
0323 h->length = de.data_length;
0324 return 0;
0325 } else {
0326
0327 if ((iso9660_search_dir (mi, &d, pathname, start, end, &de)) < 0) {
0328 return -1;
0329 } else {
0330 d = de;
0331 }
0332 start = end;
0333 }
0334 }
0335 }
0336
0337 int
0338 iso9660_read (iso9660_handle * h, uint8 * buf, uint32 len)
0339 {
0340 int n, count = 0, rem = len, curlen;
0341 iso9660_mounted_info *mi = h->mount;
0342 uint32 frame;
0343 uint8 *page;
0344
0345 frame = alloc_phys_frame ();
0346 page = map_virtual_page (frame | 3);
0347
0348 while (count < len) {
0349 n = atapi_drive_read_sector (mi->bus, mi->drive, h->sector, page);
0350 if (n < 0)
0351 goto error;
0352
0353 curlen = rem > (n - h->offset) ? (n - h->offset) : rem;
0354
0355 memcpy (buf + count, page + h->offset, curlen);
0356
0357 rem -= curlen;
0358 count += curlen;
0359 h->offset += curlen;
0360 h->length -= curlen;
0361 if (h->offset == 2048) {
0362 h->sector++;
0363 h->offset = 0;
0364 }
0365 }
0366
0367
0368 unmap_virtual_page (page);
0369 free_phys_frame (frame);
0370 return count;
0371 error:
0372 unmap_virtual_page (page);
0373 free_phys_frame (frame);
0374 return -1;
0375 }
0376
0377 static iso9660_mounted_info eziso_mount_info;
0378
0379 #if 0
0380 uint8 test1_buf[2958];
0381 #endif
0382
0383 static bool mounted = FALSE;
0384
0385 int
0386 eziso_mount (uint32 bus, uint32 drive)
0387 {
0388 int v;
0389
0390 v = iso9660_mount (bus, drive, &eziso_mount_info);
0391
0392 #if 0
0393 if (iso9660_open (&eziso_mount_info, "/boot/test1", &h) == 0) {
0394 int i, j;
0395 iso9660_handle h;
0396 com1_printf ("OPEN SUCCEEDED\n");
0397
0398 if (iso9660_read (&h, test1_buf, 2958) < 0) {
0399 com1_printf ("READ FAILED\n");
0400 } else {
0401 for (i = 0; i < 8; i++) {
0402 for (j = 0; j < 8; j++)
0403 com1_printf (" %.2X", (test1_buf + (2958 - 64))[i * 8 + j]);
0404 com1_printf ("\n");
0405 }
0406 }
0407
0408 } else
0409 com1_printf ("OPEN FAILED\n");
0410 #endif
0411
0412 if (v == 0) {
0413 mounted = TRUE;
0414 return 1;
0415 } else
0416 return 0;
0417 }
0418
0419 static iso9660_handle eziso_handle;
0420 int
0421 eziso_dir (char *pathname)
0422 {
0423 if (!mounted) {
0424 int i;
0425 for (i=0; i<4; i++) {
0426 if (pata_drives[i].ata_type == ATA_TYPE_PATAPI) {
0427 if (eziso_mount (pata_drives[i].ata_bus,
0428 pata_drives[i].ata_drive))
0429 break;
0430 }
0431 }
0432 }
0433 if (iso9660_open (&eziso_mount_info, pathname, &eziso_handle) == 0)
0434 return eziso_handle.length;
0435 else
0436 return -1;
0437 }
0438
0439 int
0440 eziso_read (char *buf, int len)
0441 {
0442 int n;
0443 if ((n = iso9660_read (&eziso_handle, (uint8 *) buf, len)) < 0)
0444 return 0;
0445 return n;
0446 }
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457