d2a82c36e2f102ea4da4559d530e8a6182fdd6ea
[profile/ivi/syslinux.git] / core / fs.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "fs.h"
4 #include "cache.h"
5
6
7 /* The this fs pointer */
8 struct fs_info *this_fs;
9 struct fs_info fs;
10 struct device dev;
11
12
13 void load_config(com32sys_t *regs)
14 {
15     this_fs->fs_ops->load_config(regs);
16 }
17
18 void mangle_name(com32sys_t *regs)
19 {
20     char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]);
21     char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]);
22
23     this_fs->fs_ops->mangle_name(dst, src);
24 }
25
26 /****
27 void unmangle_name(com32sys_t *regs)
28 {
29     
30 }
31 ****/
32
33 void getfssec(com32sys_t *regs)
34 {
35     int sectors;
36     int have_more;
37     uint32_t bytes_read;
38     char *buf;
39     struct file file;
40     
41     sectors = regs->ecx.w[0];
42     buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]);
43     file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); 
44     file.fs = this_fs;
45
46     bytes_read = this_fs->fs_ops->getfssec(file.fs, buf, file.open_file, sectors, &have_more);
47     
48     /* if we reach the EOF, set the si to be NULL */
49     if (!have_more)
50         regs->esi.w[0] = 0;
51     
52     regs->ecx.l = bytes_read;
53 }
54
55
56 void searchdir(com32sys_t *regs)
57 {
58     char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]);
59     struct file file;
60
61 #if 0    
62     printf("filename: %s\n", filename);
63 #endif
64
65     memset(&file, 0, sizeof file);
66     file.fs = this_fs;
67     
68     this_fs->fs_ops->searchdir(filename, &file);
69     regs->esi.w[0] = OFFS_WRT(file.open_file, 0);
70     regs->eax.l = file.file_len;
71     if (file.file_len)
72         regs->eflags.l &= ~EFLAGS_ZF;
73     else
74         regs->eflags.l |= EFLAGS_ZF;
75 }
76
77 /*
78  * well, I find that in the diskstart.inc, there's no room fow us to
79  * get the edd check result, so we implement a new one here.
80  */
81 uint8_t detect_edd(uint8_t device_num)
82 {
83     com32sys_t iregs, oregs;
84     
85     /* Sending int 13h func 41h to query EBIOS information */
86     memset(&iregs, 0, sizeof iregs);
87     memset(&oregs, 0, sizeof oregs);
88     
89     /* Get EBIOS support */
90     iregs.eax.w[0] = 0x4100;
91     iregs.ebx.w[0] = 0x55aa;
92     iregs.edx.b[0] = device_num;
93     iregs.eflags.b[0] = 0x3; /* CF set */
94     
95     __intcall(0x13, &iregs, &oregs);
96     
97     /* Detecting EDD support */
98     if (!(oregs.eflags.l & EFLAGS_CF) &&
99         oregs.ebx.w[0] == 0xaa55 && (oregs.ecx.b[0] & 1))
100         return 1;
101     else
102         return 0;
103 }
104
105 /* 
106  * initialize the device structure 
107  */
108 void device_init(struct device *dev, uint8_t device_num, sector_t offset)
109 {
110     dev->device_number = device_num;
111     dev->part_start = offset;
112
113     dev->type = detect_edd(device_num);
114         
115     /* 
116      * check if we use cache or not, for now I just know ISO fs 
117      * does not use the cache, and I hope the USE_CACHE can detect
118      * it correctly.
119      *
120      */    
121     if ( USE_CACHE(dev->device_number) ) {
122         /* I can't use __lowmem here, 'cause it will cause the error:
123            "auxseg/lowmem region collides with xfer_buf_seg" */
124         //static __lowmem char cache_buf[65536];
125         dev->cache_data = core_cache_buf;
126         dev->cache_size = sizeof core_cache_buf;
127     } else 
128         dev->cache_data = NULL;
129 }
130
131
132 /* debug function */
133 void dump_dev(struct device *dev)
134 {
135     printf("device type:%s\n", dev->type ? "CHS" : "EDD");
136     printf("cache_data: %p\n", dev->cache_data);
137     printf("cache_head: %p\n", dev->cache_head);
138     printf("cache_block_size: %d\n", dev->cache_block_size);
139     printf("cache_entries: %d\n", dev->cache_entries);
140     printf("cache_size: %d\n", dev->cache_size);
141 }
142
143 /*
144  * it will do:
145  *    initialize the device structure;
146  *    set up the vfs fs structure;
147  *    invoke the fs-specific init function;
148  *    finally, initialize the cache
149  *
150  */
151 void fs_init(com32sys_t *regs)
152 {
153     int blk_shift;
154     struct fs_ops *ops = (struct fs_ops*)regs->eax.l;
155     
156     device_init(&dev, regs->edx.b[0], regs->ecx.l);
157     
158     /* set up the fs stucture */    
159     fs.fs_name = ops->fs_name;
160     fs.fs_ops = ops;
161     fs.fs_dev = &dev;
162     this_fs = &fs;
163
164     /* invoke the fs-specific init code */
165     blk_shift = fs.fs_ops->fs_init();    
166
167     /* initialize the cache */
168     if (dev.cache_data)
169         cache_init(&dev, blk_shift);
170 }