From 543c6543392cc81f9f35904c7b814112b2eb5b97 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 11 Jun 2009 15:54:43 +0800 Subject: [PATCH] Core: make vfs do the work it works, but it broke somewhere; it can't display the menu correctly. --- core/cache.c | 66 +++++++++++------- core/cache.h | 9 +-- core/diskstart.inc | 28 +++++++- core/ext2.c | 191 +++++++++++++++++++++++++++-------------------------- core/extern.inc | 10 +-- core/extlinux.asm | 15 ----- core/fs.c | 74 +++++++++++++++++---- core/include/fs.h | 17 +++-- core/load_config.c | 26 -------- 9 files changed, 242 insertions(+), 194 deletions(-) delete mode 100644 core/load_config.c diff --git a/core/cache.c b/core/cache.c index 4198420..b0fbee7 100644 --- a/core/cache.c +++ b/core/cache.c @@ -14,10 +14,6 @@ * The cache buffer are pointed to by a cache_head structure. */ -static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; -static int cache_block_size; -static int cache_entries; - /** * cache_init: * @@ -25,29 +21,30 @@ static int cache_entries; * regs->eax.l stores the block size(in bits not bytes) * */ -void cache_init(com32sys_t * regs) +void cache_init(struct device *dev, int block_size_shift) { struct cache_struct *prev, *cur; - char *data = core_cache_buf; - int block_size_shift = regs->eax.l; + char *data = dev->cache_data; + static __lowmem struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; int i; + + dev->cache_head = &cache_head; + dev->cache_block_size = 1 << block_size_shift; + dev->cache_entries = dev->cache_size >> block_size_shift; + if (dev->cache_entries > MAX_CACHE_ENTRIES) + dev->cache_entries = MAX_CACHE_ENTRIES; - cache_block_size = 1 << block_size_shift; - cache_entries = sizeof(core_cache_buf) >> block_size_shift; - if (cache_entries > MAX_CACHE_ENTRIES) - cache_entries = MAX_CACHE_ENTRIES; - - cache_head.prev = &cache[cache_entries-1]; + cache_head.prev = &cache[dev->cache_entries-1]; cache_head.prev->next = &cache_head; prev = &cache_head; - for (i = 0; i < cache_entries; i++) { + for (i = 0; i < dev->cache_entries; i++) { cur = &cache[i]; cur->block = 0; cur->prev = prev; prev->next = cur; cur->data = data; - data += cache_block_size; + data += dev->cache_block_size; prev = cur++; } } @@ -74,10 +71,10 @@ void cache_init(com32sys_t * regs) * @return: the data stores at gs:si * */ -struct cache_struct* get_cache_block(block_t block) +struct cache_struct* get_cache_block(struct device *dev, block_t block) { /* let's find it from the end, 'cause the endest is the freshest */ - struct cache_struct *cs = cache_head.prev; + struct cache_struct *cs = dev->cache_head->prev; struct cache_struct *head, *last; int i; @@ -97,7 +94,7 @@ struct cache_struct* get_cache_block(block_t block) if (cs->block == block) goto out; - for (i = 0; i < cache_entries; i ++) { + for (i = 0; i < dev->cache_entries; i ++) { if (cs->block == block) break; else @@ -105,11 +102,11 @@ struct cache_struct* get_cache_block(block_t block) } /* missed, so we need to load it */ - if (i == cache_entries) { + if (i == dev->cache_entries) { /* store it at the head of real cache */ - cs = cache_head.next; + cs = dev->cache_head->next; cs->block = block; - getoneblk(cs->data, block, cache_block_size); + getoneblk(cs->data, block, dev->cache_block_size); missed ++; } @@ -119,8 +116,8 @@ struct cache_struct* get_cache_block(block_t block) cs->next->prev = cs->prev; /* add to just before head node */ - last = cache_head.prev; - head = &cache_head; + last = dev->cache_head->prev; + head = dev->cache_head; last->next = cs; cs->prev = last; @@ -128,15 +125,34 @@ struct cache_struct* get_cache_block(block_t block) cs->next = head; out: -#if 0 /* testing how efficiency the cache is */ total_read ++; +#if 0 /* testing how efficiency the cache is */ if (total_read % 5 == 0) printf("total_read %d\tmissed %d\n", total_read, missed); #endif /* in fact, that would never be happened */ if ((char *)(cs->data) > (char*)0x100000) - printf("the buffer addres higher than 1M limit\n\r"); + printf("the buffer addres higher than 1M limit\n"); return cs; } + + +/** + * Just print the sector, and according the LRU algorithm, + * Left most value is the most least secotr, and Right most + * value is the most Recent sector. I see it's a Left Right Used + * (LRU) algorithm; Just kidding:) + */ +void print_cache(struct device *dev) +{ + int i = 0; + struct cache_struct *cs = dev->cache_head; + for (; i < dev->cache_entries; i++) { + cs = cs->next; + printf("%d(%p) ", cs->block, cs->data); + } + + printf("\n"); +} diff --git a/core/cache.h b/core/cache.h index 65df6cd..7518bc8 100644 --- a/core/cache.h +++ b/core/cache.h @@ -4,8 +4,9 @@ #include #include #include "disk.h" +#include "fs.h" -#define MAX_CACHE_ENTRIES 0x064 /* I'm not sure it's the max */ +#define MAX_CACHE_ENTRIES 0x10 /* I find even this is enough:) */ /* The cache structure */ struct cache_struct { @@ -17,8 +18,8 @@ struct cache_struct { /* functions defined in cache.c */ -void cache_init(com32sys_t *regs); - -struct cache_struct* get_cache_block(block_t); +void cache_init(struct device *, int); +struct cache_struct* get_cache_block(struct device *, block_t); +void print_cache(struct device *); #endif /* cache.h */ diff --git a/core/diskstart.inc b/core/diskstart.inc index 38222e0..a08aa28 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -706,6 +706,30 @@ expand_super: stosd ; Store expanded byte loop .loop + ; -; Fall through to the mainline code... -; +; Common initialization code +; +%include "init.inc" +%include "cpuinit.inc" + + +%if IS_PXELINUX + extern pxe_fs_ops + mov eax,pxe_fs_ops +%else + %if IS_EXTLINUX + extern ext2_fs_ops + mov eax,ext2_fs_ops + %elif IS_SYSLINUX + extern vfat_fs_ops + mov eax,vfat_fs_ops + %elif IS_ISOLINUX + extern iso_fs_ops + mov eax,iso_fs_ops + %endif + mov dl,[DriveNumber] + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] +%endif + pm_call fs_init diff --git a/core/ext2.c b/core/ext2.c index 7980930..b89541c 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -4,6 +4,7 @@ #include "core.h" #include "disk.h" #include "ext2_fs.h" +#include "fs.h" #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) @@ -106,10 +107,8 @@ void close_file(struct open_file_t *file) * any whitespace. * */ -void mangle_name(com32sys_t *regs) +void ext2_mangle_name(char *dst, char *src) { - char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); char *p = dst; int i = FILENAME_MAX -1; @@ -150,7 +149,7 @@ void mangle_name(com32sys_t *regs) * @return: the pointer of the group's descriptor * */ -struct ext2_group_desc *get_group_desc(uint32_t group_num) +struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) { block_t block_num; uint32_t offset; @@ -161,7 +160,7 @@ struct ext2_group_desc *get_group_desc(uint32_t group_num) offset = group_num % DescPerBlock; block_num += sb->s_first_data_block + 1; - cs = get_cache_block(block_num); + cs = get_cache_block(fs->fs_dev, block_num); desc = (struct ext2_group_desc *)cs->data + offset; @@ -181,7 +180,7 @@ struct ext2_group_desc *get_group_desc(uint32_t group_num) * @param: offset, same as block * */ -void read_inode(uint32_t inode_offset, +void read_inode(struct fs_info *fs, uint32_t inode_offset, struct ext2_inode *dst, struct ext2_group_desc *desc, block_t *block, uint32_t *offset) { @@ -191,7 +190,7 @@ void read_inode(uint32_t inode_offset, *block = inode_offset / InodePerBlock + desc->bg_inode_table; *offset = inode_offset % InodePerBlock; - cs = get_cache_block(*block); + cs = get_cache_block(fs->fs_dev, *block); /* well, in EXT4, the inode structure usually be 256 */ inode = (struct ext2_inode *)(cs->data + (*offset * (sb->s_inode_size))); @@ -213,7 +212,7 @@ void read_inode(uint32_t inode_offset, * the first 128 bytes of the inode, stores in ThisInode * */ -struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) +struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) { struct open_file_t *file; struct ext2_group_desc *desc; @@ -232,10 +231,10 @@ struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) inode_group = inr / sb->s_inodes_per_group; /* get the group desc */ - desc = get_group_desc(inode_group); + desc = get_group_desc(fs, inode_group); inode_offset = inr % sb->s_inodes_per_group; - read_inode(inode_offset, this_inode, desc, &block_num, &block_off); + read_inode(fs, inode_offset, this_inode, desc, &block_num, &block_off); /* Finally, we need to convet it to sector for now */ file->file_in_sec = (block_num<>SECTOR_SHIFT); @@ -252,7 +251,7 @@ struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) struct ext4_extent_header * -ext4_find_leaf (struct ext4_extent_header *eh, block_t block) +ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) { struct ext4_extent_idx *index; struct cache_struct *cs; @@ -279,20 +278,20 @@ ext4_find_leaf (struct ext4_extent_header *eh, block_t block) blk = (blk << 32) + index[i].ei_leaf_lo; /* read the blk to memeory */ - cs = get_cache_block(blk); + cs = get_cache_block(fs->fs_dev, blk); eh = (struct ext4_extent_header *)(cs->data); } } /* handle the ext4 extents to get the phsical block number */ -uint64_t linsector_extent(block_t block, struct ext2_inode *inode) +uint64_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct ext4_extent_header *leaf; struct ext4_extent *ext; int i; uint64_t start; - leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_block,block); + leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); if (! leaf) { printf("ERROR, extent leaf not found\n"); return 0; @@ -329,7 +328,7 @@ uint64_t linsector_extent(block_t block, struct ext2_inode *inode) * * @return: the physic block number */ -block_t linsector_direct(block_t block, struct ext2_inode *inode) +block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct cache_struct *cs; @@ -342,7 +341,7 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= EXT2_NDIR_BLOCKS; if (block < PtrsPerBlock1) { block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; - cs = get_cache_block(ind_block); + cs = get_cache_block(fs->fs_dev, ind_block); return ((block_t *)cs->data)[block]; } @@ -351,10 +350,10 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= PtrsPerBlock1; if (block < PtrsPerBlock2) { block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; - cs = get_cache_block(dou_block); + cs = get_cache_block(fs->fs_dev, dou_block); dou_block = ((block_t *)cs->data)[block / PtrsPerBlock1]; - cs = get_cache_block(dou_block); + cs = get_cache_block(fs->fs_dev, dou_block); return ((block_t*)cs->data)[block % PtrsPerBlock1]; } @@ -363,13 +362,13 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= PtrsPerBlock2; if (block < PtrsPerBlock3) { block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); tri_block = ((block_t *)cs->data)[block / PtrsPerBlock2]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); tri_block = ((block_t *)cs->data)[block % PtrsPerBlock2]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; } @@ -392,7 +391,7 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) * * @return: physic sector number */ -sector_t linsector(sector_t lin_sector) +sector_t linsector(struct fs_info *fs, sector_t lin_sector) { block_t block = lin_sector >> ClustShift; struct ext2_inode *inode; @@ -401,9 +400,9 @@ sector_t linsector(sector_t lin_sector) inode = this_inode; if (inode->i_flags & EXT4_EXTENTS_FLAG) - block = linsector_extent(block, inode); + block = linsector_extent(fs, block, inode); else - block = (uint32_t)linsector_direct(block, inode); + block = (uint32_t)linsector_direct(fs, block, inode); if (!block) { printf("ERROR: something error happend at linsector..\n"); @@ -480,17 +479,13 @@ void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) * @return: ECX(of regs), number of bytes read * */ -void getfssec(com32sys_t *regs) +uint32_t ext2_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) { int sector_left, next_sector, sector_idx; int frag_start, con_sec_cnt; - int sectors = regs->ecx.w[0]; int bytes_read = sectors << SECTOR_SHIFT; - char *buf; - struct open_file_t *file; - - buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); - file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); + struct open_file_t *file = (struct open_file_t *)open_file; sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; if (sectors > sector_left) @@ -501,7 +496,7 @@ void getfssec(com32sys_t *regs) * get the frament */ sector_idx = file->file_sector; - next_sector = frag_start = linsector(sector_idx); + next_sector = frag_start = linsector(fs, sector_idx); con_sec_cnt = 0; /* get the consective sectors count */ @@ -517,7 +512,7 @@ void getfssec(com32sys_t *regs) sector_idx ++; next_sector ++; - }while(next_sector == linsector(sectors)); + }while(next_sector == linsector(fs, sectors)); #if 0 printf("You are reading stores at sector --0x%x--0x%x\n", @@ -528,49 +523,17 @@ void getfssec(com32sys_t *regs) file->file_sector += con_sec_cnt; /* next sector index */ }while(sectors); - if (bytes_read >= file->file_bytesleft) { + if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; - regs->esi.w[0] = 0; /* do close the file for asm function*/ - } + *have_more = 0; + } else + *have_more = 1; file->file_bytesleft -= bytes_read; - - regs->ecx.l = bytes_read; -} - - -/* This is the gefssec function that should be called from C function */ -void getfssec_ext(char *buf, struct open_file_t *file, - int sectors, int *have_more) -{ - com32sys_t regs; - - memset(®s, 0, sizeof regs); - - /* - * for now, even though the buf and file structure are stored - * at low address, BUT find: - * - * we can't use SEG stuff here, say the address of buf - * is 0x800(found in debug), the address would be broken like - * this: es = 0x80, bx = 0, while that's not the getfssec - * function need. - * - * so we just do like: - * regs.ebx.w[0] = buf; - */ - regs.ebx.w[0] = OFFS_WRT(buf, 0); - regs.esi.w[0] = OFFS_WRT(file, 0); - regs.ecx.w[0] = sectors; - getfssec(®s); - - *have_more = 1; - - /* the file is closed ? */ - if(!file->file_bytesleft) - *have_more = 0; + return bytes_read; } - + + /** * find_dir_entry: @@ -578,21 +541,21 @@ void getfssec_ext(char *buf, struct open_file_t *file, * find a dir entry, if find return it or return NULL * */ -struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) +struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) { int have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; struct ext2_dir_entry *de; /* read a clust at a time */ - getfssec_ext(trackbuf, file, SecPerClust, &have_more); + ext2_getfssec(fs, trackbuf, file, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; while (1) { if ((char *)de >= (char *)EndBlock) { if (!have_more) return NULL; - getfssec_ext(trackbuf, file,SecPerClust,&have_more); + ext2_getfssec(fs, trackbuf, file,SecPerClust,&have_more); de = (struct ext2_dir_entry *)trackbuf; } @@ -616,7 +579,8 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) } -char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) +char* do_symlink(struct fs_info *fs, struct open_file_t *file, + uint32_t file_len, char *filename) { int flag, have_more; @@ -633,7 +597,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) } else { /* slow symlink */ - getfssec_ext(SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); + ext2_getfssec(fs, SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); lnk_end = SymlinkTmpBuf + file_len; } @@ -668,29 +632,28 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) * @out : file lenght in bytes, stores in eax * */ -void searchdir(com32sys_t * regs) +void ext2_searchdir(char *filename, struct file *file) { extern int CurrentDir; - struct open_file_t *file; + struct open_file_t *open_file; struct ext2_dir_entry *de; uint8_t file_mode; uint8_t SymlinkCtr = MAX_SYMLINKS; uint32_t inr = CurrentDir; uint32_t ThisDir = CurrentDir; uint32_t file_len; - char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); - + begin_path: while (*filename == '/') { /* Absolute filename */ inr = EXT2_ROOT_INO; filename ++; } open: - if ((file = open_inode(inr, &file_len)) == NULL) + if ((open_file = open_inode(file->fs, inr, &file_len)) == NULL) goto err_noclose; - file_mode = file->file_mode >> S_IFSHIFT; + file_mode = open_file->file_mode >> S_IFSHIFT; /* It's a file */ if (file_mode == T_IFREG) { @@ -710,13 +673,13 @@ void searchdir(com32sys_t * regs) while (*filename == '/') filename ++; - de = find_dir_entry(file, filename); + de = find_dir_entry(file->fs, open_file, filename); if (!de) goto err; inr = de->d_inode; filename += de->d_name_len; - close_file(file); + close_file(open_file); goto open; } @@ -732,7 +695,7 @@ void searchdir(com32sys_t * regs) if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) goto err; /* too many links or symlink too long */ - filename = do_symlink(file, file_len, filename); + filename = do_symlink(file->fs, open_file, file_len, filename); if (!filename) goto err_noclose;/* buffer overflow */ @@ -742,22 +705,52 @@ void searchdir(com32sys_t * regs) /* Otherwise, something bad ... */ err: - close_file(file); + close_file(open_file); err_noclose: file_len = 0; - file = NULL; - regs->eflags.l |= EFLAGS_ZF; + open_file = NULL; done: - regs->eax.l = file_len; - regs->esi.w[0] = OFFS_WRT(file, 0); + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 1 + if (open_file) { + printf("file bytesleft: %d\n", open_file->file_bytesleft); + printf("file sector : %d\n", open_file->file_sector); + printf("file in sector: %d\n", open_file->file_in_sec); + printf("file offsector: %d\n", open_file->file_in_off); + } +#endif + +} + +void ext2_load_config(com32sys_t *regs) +{ + char *config_name = "extlinux.conf"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + *(uint32_t *)CurrentDirName = 0x00002f2e; + + regs->edi.w[0] = ConfigName; + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); + + regs->eax.w[0] = out_regs.eax.w[0]; + +#if 0 + printf("the zero flag is %s\n", regs->eax.w[0] ? \ + "CLEAR, means we found the config file" : + "SET, menas we didn't find the config file"); +#endif } /** - * init. the fs meta data, return the block size in eax + * init. the fs meta data, return the block size bits. */ -void init_fs(com32sys_t *regs) +int ext2_fs_init(void) { extern char SuperBlock[1024]; @@ -779,5 +772,15 @@ void init_fs(com32sys_t *regs) PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2); PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3); - regs->eax.l = ClustByteShift; + return ClustByteShift; } + +const struct fs_ops ext2_fs_ops = { + .fs_name = "ext2", + .fs_init = ext2_fs_init, + .searchdir = ext2_searchdir, + .getfssec = ext2_getfssec, + .mangle_name = ext2_mangle_name, + .unmangle_name = NULL, + .load_config = ext2_load_config +}; diff --git a/core/extern.inc b/core/extern.inc index 086f1dd..fdbe264 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -12,13 +12,7 @@ ; hello.c extern hello - ; cache.c - extern cache_init - - ; load_config.c - extern load_config - - ; ext2.c - extern init_fs, searchdir, getfssec, mangle_name + ; fs.c + extern fs_init, searchdir, getfssec, mangle_name, load_config %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 741566c..be256cf 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -113,21 +113,6 @@ Files resb MAX_OPEN*open_file_t_size ; %include "diskstart.inc" -; -; Common initialization code -; -%include "init.inc" -%include "cpuinit.inc" - -; -; Initialize the ext2 fs meta data -; - pm_call init_fs ; will return the block size shift in eax(for now, is the sector shift) - -; -; Initialize the metadata cache -; - pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more diff --git a/core/fs.c b/core/fs.c index f094690..18f0337 100644 --- a/core/fs.c +++ b/core/fs.c @@ -4,7 +4,7 @@ #include "cache.h" -/* The this pointer */ +/* The this fs pointer */ struct fs_info *this_fs; struct fs_info fs; struct device dev; @@ -43,7 +43,7 @@ void getfssec(com32sys_t *regs) file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); file.fs = this_fs; - bytes_read = this_fs->fs_ops->getfssec(buf, file.open_file, sectors, &have_more); + bytes_read = this_fs->fs_ops->getfssec(file.fs, buf, file.open_file, sectors, &have_more); /* if we reach the EOF, set the si to be NULL */ if (!have_more) @@ -58,33 +58,68 @@ void searchdir(com32sys_t *regs) char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); struct file file; + printf("filename: %s\n", filename); + memset(&file, 0, sizeof file); file.fs = this_fs; this_fs->fs_ops->searchdir(filename, &file); regs->esi.w[0] = OFFS_WRT(file.open_file, 0); regs->eax.l = file.file_len; + if (!file.file_len) + regs->eflags.l |= EFLAGS_ZF; +} + +/* + * well, I find that in the diskstart.inc, there's no room fow us to + * get the edd check result, so we implement a new one here. + */ +uint8_t detect_edd(uint8_t device_num) +{ + com32sys_t iregs, oregs; + + /* Sending int 13h func 41h to query EBIOS information */ + memset(&iregs, 0, sizeof iregs); + memset(&oregs, 0, sizeof oregs); + + /* Get EBIOS support */ + iregs.eax.w[0] = 0x4100; + iregs.ebx.w[0] = 0x55aa; + iregs.edx.b[0] = device_num; + iregs.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &iregs, &oregs); + + /* Detecting EDD support */ + if (!(oregs.eflags.l & EFLAGS_CF) && + oregs.ebx.w[0] == 0xaa55 && (oregs.ecx.b[0] & 1)) + return 1; + else + return 0; } /* * initialize the device structure */ -void device_init(struct device *dev, uint8_t drive_num, - uint8_t type, sector_t offset) +void device_init(struct device *dev, uint8_t device_num, sector_t offset) { - dev->device_number = drive_num; + dev->device_number = device_num; dev->part_start = offset; - dev->type = type; - + + dev->type = detect_edd(device_num); + /* * check if we use cache or not, for now I just know ISO fs * does not use the cache, and I hope the USE_CACHE can detect * it correctly. * - */ + */ if ( USE_CACHE(dev->device_number) ) { - static __lowmem char cache_buf[65536]; - dev->cache_data = cache_buf; + /* I can't use __lowmem here, 'cause it will cause the error: + "auxseg/lowmem region collides with xfer_buf_seg" */ + //static __lowmem char cache_buf[65536]; + dev->cache_data = core_cache_buf; + dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; @@ -93,6 +128,17 @@ void device_init(struct device *dev, uint8_t drive_num, } +/* debug function */ +void dump_dev(struct device *dev) +{ + printf("device type:%s\n", dev->type ? "CHS" : "EDD"); + printf("cache_data: %p\n", dev->cache_data); + printf("cache_head: %p\n", dev->cache_head); + printf("cache_block_size: %d\n", dev->cache_block_size); + printf("cache_entries: %d\n", dev->cache_entries); + printf("cache_size: %d\n", dev->cache_size); +} + /* * it will do: * initialize the device structure; @@ -106,7 +152,7 @@ void fs_init(com32sys_t *regs) int blk_shift; struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - device_init(&dev, regs->edx.b[0], regs->edx.b[1], regs->ecx.l); + device_init(&dev, regs->edx.b[0], regs->ecx.l); /* set up the fs stucture */ fs.fs_name = ops->fs_name; @@ -115,9 +161,9 @@ void fs_init(com32sys_t *regs) this_fs = &fs; /* invoke the fs-specific init code */ - blk_shift = fs.fs_ops->fs_init(); - + blk_shift = fs.fs_ops->fs_init(); + /* initialize the cache */ if (dev.cache_data) - cache_init(&dev, blk_shift); + cache_init(&dev, blk_shift); } diff --git a/core/include/fs.h b/core/include/fs.h index 6805b3b..0cb1bfc 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -5,7 +5,8 @@ #include "core.h" #include "disk.h" -#define USE_CACHE(device_num) (device_num > 0x00 && device_num < 0xfe) +/* I don't know it's right or not */ +#define USE_CACHE(device_num) (device_num >= 0x00 && device_num < 0xfe) struct fs_info { @@ -27,13 +28,13 @@ struct fs_ops { int (*fs_init)(void); void (*searchdir)(char *, struct file *); - uint32_t (*getfssec)(char *, void * , int, int *); + uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); void (*mangle_name)(char *, char *); void (*unmangle_name)(void); void (*load_config)(com32sys_t *); }; -//enum dev_type {CHS, EDD}; +enum dev_type {CHS, EDD}; /* * Struct device should have all the information about a specific disk @@ -65,10 +66,14 @@ struct device { /* * I think we still need the cache_data filed here, 'cause hpa said - * different device has diffrent cache buffer + * different device has diffrent cache buffer, and the following filed + * are quite for cache parts. */ - void *cache_data; - struct cache_struct *cache_head; + char* cache_data; + struct cache_struct *cache_head; + uint16_t cache_block_size; + uint16_t cache_entries; + uint32_t cache_size; }; diff --git a/core/load_config.c b/core/load_config.c deleted file mode 100644 index 2c81946..0000000 --- a/core/load_config.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -#include "core.h" - - -void load_config(com32sys_t *regs) -{ - char *config_name = "extlinux.conf"; - com32sys_t out_regs; - - strcpy(ConfigName, config_name); - *(uint32_t *)CurrentDirName = 0x00002f2e; - - regs->edi.w[0] = ConfigName; - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); - - regs->eax.w[0] = out_regs.eax.w[0]; - -#if 0 - printf("the zero flag is %s\n", regs->eax.w[0] ? \ - "CLEAR, means we found the config file" : - "SET, menas we didn't find the config file"); -#endif -} -- 2.7.4