3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <partition.h>
32 #define ISOFS_SUPERBLOCK_SECTOR 16 // NOTE: sector is 2kB length
34 #define ISOFS_DIR_FLAGS_HIDDEN 0x1
35 #define ISOFS_DIR_FLAGS_DIR 0x2
37 #define __PACKED__ __attribute__ ((__packed__))
43 unsigned char sys_id
[32];
44 unsigned char vol_id
[32];
45 unsigned char zeros
[8];
46 unsigned long sectors
[2];
47 unsigned char zeros2
[32];
48 unsigned short set_size
[2];
49 unsigned short seq_num
[2];
50 unsigned short sector_size
[2];
51 unsigned long path_tbl
[2];
52 unsigned first_sec_fle_ptbl
;
53 unsigned first_sec_sle_ptbl
;
54 unsigned first_sec_fbe_ptbl
;
55 unsigned first_sec_sbe_ptbl
;
56 unsigned char root_dir_rec
[34]; // 158
57 unsigned char set_id
[128];
58 unsigned char pub_id
[128];
59 unsigned char datap_id
[128]; // 542
60 unsigned char app_id
[128];
61 unsigned char copy_id
[37];
62 unsigned char abst_id
[37];
63 unsigned char bibl_id
[37];
64 unsigned char date_volcr
[17];
65 unsigned char date_mod
[17];
66 unsigned char date_expir
[17];
67 unsigned char date_eff
[17];
70 unsigned char reserved
[512];
71 unsigned char zeros3
[653];
72 } __PACKED__ isofs_volume_t
; // 1395
75 unsigned char name_len
;
76 unsigned char sect_num
;
78 unsigned short rec_num
;
80 } __PACKED__ isofs_path_t
;
83 unsigned char rec_len
;
84 unsigned char sec_num
;
85 unsigned long data_sec
[2];
86 unsigned long data_len
[2];
93 unsigned char time_offset
;
95 unsigned char unit_size
;
96 unsigned char gap_size
;
97 unsigned short vol_seq_num
[2];
100 } __PACKED__ isofs_dir_t
;
102 typedef struct isofs_path_context
{
103 struct isofs_path_context
*next
, *prev
;
105 unsigned char name_len
;
106 unsigned char sect_num
;
108 unsigned short rec_num
;
112 isofs_pathtbl_t path_table_list
;
114 /* FIXME: limit for one mounted iso fs */
115 static isofs_pathtbl_t
*path_curr
;
116 static isofs_pathtbl_t
*path_prev
;
118 unsigned isofs_sector_read (partition_t
*p
, unsigned sector
, unsigned char *buffer
)
120 /* iso9660 sector is 2kB length */
121 unsigned address
= sector
* 4;
123 /* lba28_drive_read () read 512 bytes from drive 4 times +512 bytes */
124 lba28_drive_read (p
, address
, (unsigned char *) buffer
);
125 lba28_drive_read (p
, address
+1, (unsigned char *) buffer
+512);
126 lba28_drive_read (p
, address
+2, (unsigned char *) buffer
+1024);
127 lba28_drive_read (p
, address
+3, (unsigned char *) buffer
+1536);
132 isofs_pathtbl_t
*isofs_path_find (char *name
)
134 isofs_pathtbl_t
*path
;
135 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
136 if (!strcmp (path
->name
, name
))
143 unsigned isofs_dir_scan (partition_t
*p
, char *block
)
145 /*dir = (isofs_dir_t *) (block + dir->rec_len);
147 dir = (isofs_dir_t *) (block + dir->rec_len);*/
149 unsigned dir_next
= 0;
153 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
155 if (!isodir
->rec_len
)
158 //kprintf ("dir -> %d:%d:%d:%d:%d - %d - %d - %s\n", dir->year+1900, dir->month, dir->day, dir->hour, dir->minute, dir->rec_len, dir->id_len, dir->id);
159 /* clear name for prevent */
160 memset (dir
[entry
].name
, 0, 10);
162 /* there are directories and files */
164 if (isodir
->id_len
> 9)
165 memcpy (dir
[entry
].name
, isodir
->id
, 9);
167 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
)
168 memcpy (dir
[entry
].name
, isodir
->id
, isodir
->id_len
);
170 memcpy (dir
[entry
].name
, isodir
->id
, isodir
->id_len
-2);
173 // "." and ".." directories are not correctly named in iso9660
177 memcpy (dir
[entry
].name
, ".", 1);
179 memcpy (dir
[entry
].name
, "..", 2);
183 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
)
188 dir_next
+= isodir
->rec_len
;
192 /* for prevent clear last+1 entry of dir[] */
193 memset (dir
[entry
].name
, 0, 10);
198 isofs_dir_t
*isofs_dir_find (partition_t
*p
, char *block
, char *name
)
200 unsigned dir_next
= 0;
202 unsigned name_len
= strlen (name
);
205 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
207 if (!isodir
->rec_len
)
210 if (!strncmp (name
, isodir
->id
, name_len
))
213 dir_next
+= isodir
->rec_len
;
220 unsigned isofs_path_gettable (partition_t
*p
)
222 char *block
= (char *) kmalloc (sizeof (char) * 2048);
227 unsigned path_prev
= 0;
228 unsigned path_num
= 0;
230 isofs_sector_read (p
, 19, (unsigned char *) block
);
233 isofs_path_t
*path
= (isofs_path_t
*) (block
+ path_prev
);
241 /* alloc and init context */
242 isofs_pathtbl_t
*table
= (isofs_pathtbl_t
*) kmalloc (sizeof (isofs_pathtbl_t
));
247 table
->name_len
= path
->name_len
;
248 table
->sect_num
= path
->sect_num
;
249 table
->sect_data
= path
->sect_data
;
250 table
->rec_num
= path
->rec_num
;
252 table
->name
= (unsigned char *) kmalloc (sizeof (unsigned char) * path
->name_len
);
257 memcpy (table
->name
, &path
->name
, path
->name_len
);
258 kprintf ("dd: %s\n", table
->name
);
259 //memcpy (table->path, path, sizeof (isofs_path_t)+path->name_len);
262 table
->next
= &path_table_list
;
263 table
->prev
= path_table_list
.prev
;
264 table
->prev
->next
= table
;
265 table
->next
->prev
= table
;
267 path_prev
+= 9 + path
->name_len
;
270 if (!block
[path_prev
+path
->name_len
+1])
281 unsigned isofs_cd_root (partition_t
*p
)
283 isofs_pathtbl_t
*path
;
284 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
285 /* we need find root dir (ussualy it is first in list) */
286 if (path
->name_len
== 1) {
287 char *block
= (char *) kmalloc (sizeof (char) * 2048);
292 path_prev
= path_curr
;
295 isofs_sector_read (p
, path
->sect_data
, block
);
297 isofs_dir_scan (p
, block
);
308 /* go to next directory placed in current directory */
309 unsigned isofs_cd (partition_t
*p
, unsigned char *name
)
311 isofs_pathtbl_t
*path
;
313 if (!strcmp (name
, "..")) {
316 char *block
= (char *) kmalloc (sizeof (char) * 2048);
321 path_prev
= path_curr
;
324 isofs_sector_read (p
, path
->sect_data
, block
);
326 isofs_dir_scan (p
, block
);
333 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
334 /* we need to find wanted dir */
335 if (!strncmp (path
->name
, name
, path
->name_len
)) {
336 char *block
= (char *) kmalloc (sizeof (char) * 2048);
341 path_prev
= path_curr
;
344 isofs_sector_read (p
, path
->sect_data
, block
);
346 isofs_dir_scan (p
, block
);
357 extern unsigned long file_cache_id
;
358 unsigned isofs_cat (partition_t
*p
, unsigned char *name
)
363 isofs_pathtbl_t
*path
= path_curr
;
365 char *block
= (char *) kmalloc (sizeof (char) * 2048);
370 isofs_sector_read (p
, path
->sect_data
, block
);
372 isofs_dir_t
*isodir
= isofs_dir_find (p
, block
, name
);
379 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
||
380 !isodir
->data_sec
[0] ||
381 !isodir
->data_len
[0]) {
386 unsigned long len
= 0;
387 file_cache_id
= 2048;
391 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
396 isofs_sector_read (p
, isodir
->data_sec
[0]+i
, file_cache
+len
);
398 if ((len
+2048) > isodir
->data_len
[0])
405 file_cache_id
= isodir
->data_len
[0];
412 /* iso9660 filesystem initialization function */
413 unsigned isofs_init (partition_t
*p
)
415 isofs_volume_t
*volume
= (isofs_volume_t
*) kmalloc (sizeof (isofs_volume_t
));
420 isofs_sector_read (p
, ISOFS_SUPERBLOCK_SECTOR
, (unsigned char *) volume
);
423 kprintf ("isofs -> %d, %d:%d:%s:%s:%d:%s:%s:%s:%d\n", sizeof (isofs_volume_t
), volume
->one
, volume
->zero
, volume
->sys_id
, volume
->vol_id
, volume
->sector_size
[0], volume
->pub_id
, volume
->root_dir_rec
, volume
->zeros
, volume
->seq_num
[0]);
425 path_table_list
.next
= &path_table_list
;
426 path_table_list
.prev
= &path_table_list
;
428 isofs_path_gettable (p
);
433 /*char *block = (char *) kmalloc (sizeof (char) * 2048);
438 /*isofs_pathtbl_t *path;
439 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
440 kprintf ("path - %s - %d\n", path->name, path->sect_data);
442 isofs_sector_read (p, path->sect_data, block);
444 isofs_dir_scan (p, block);
454 /* handler which is used by device management and pretty needed
455 for communication between zexos and this filesystem */
456 bool isofs_handler (unsigned act
, char *block
, unsigned n
, unsigned long l
)
466 isofs_cat (curr_part
, dir
[n
].name
);
480 isofs_cd_root (curr_part
);
484 /* go to another directory */
485 isofs_cd (curr_part
, dir
[n
].name
);