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