From 5e45fe5a4284dd362bbccd71bebaa3838d77591b Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 2 Jun 2009 08:32:36 +0800 Subject: [PATCH] Convert the cache code to C and implement the core printf function for the cahce part, I do get the error message says that undefined reference to `getlinsec'. I'm abort to implement a C version one. for the printf function, it works somehow, but doesn't work well. With the test, it seems it can handle the format output correctly. And I haven't debugged it, so I have no idea for now. --- core/cache.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ core/cache.h | 27 ++++++++++ core/diskstart.inc | 1 + core/extern.inc | 3 ++ core/extlinux.asm | 16 +++--- core/ldlinux.asm | 10 ++-- core/printf.c | 27 ++++++++++ core/types.h | 17 +++++++ 8 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 core/cache.c create mode 100644 core/cache.h create mode 100644 core/printf.c create mode 100644 core/types.h diff --git a/core/cache.c b/core/cache.c new file mode 100644 index 0000000..aaa9000 --- /dev/null +++ b/core/cache.c @@ -0,0 +1,145 @@ +#include "core.h" + +#include "cache.h" +#include + + +/* + * Each CachePtr contains: + * - Block pointer + * - LRU previous pointer + * - LRU next pointer + * - Block data buffer address + * + * The cache buffer are pointed to by a cache_head structure. + */ + + +static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; +static __u8 cache_data[65536]; +static int cache_block_size; +static int cache_entries; + +/** + * cache_init: + * + * Initialize the cache data structres. + * regs->eax.l stores the block size + * + */ +void cache_init(com32sys_t * regs) +{ + struct cache_struct *prev, *cur; + __u8 *data = cache_data; + int block_size = regs->eax.l; + int i; + + cache_block_size = block_size; + cache_entries = sizeof cache_data / block_size; + if (cache_entries > MAX_CACHE_ENTRIES) + cache_entries = MAX_CACHE_ENTRIES; + + cache_head.prev = &cache[cache_entries-1]; + cache_head.prev->next = &cache_head; + prev = &cache_head; + + for (i = 0; i < cache_entries; i++) { + cur = &cache[i]; + cur->block = 0; + cur->prev = prev; + prev->next = cur; + cur->data = data; + data += block_size; + prev = cur++; + } +} + + +extern void getlinsec(void); + +void getoneblk(char *buf, __u32 block, int block_size) +{ + int sec_per_block = block_size / 512; /* 512==sector size */ + com32sys_t regs; + + + + regs.eax.l = block * sec_per_block; + regs.ebp.l = sec_per_block; + regs.es = SEG(buf); + regs.ebx.w[0] = OFFS(buf); + + call16(getlinsec, ®s, NULL); +} + + + +/** + * get_cache_block: + * + * Check for a particular BLOCK in the block cache, + * and if it is already there, just do nothing and return; + * otherwise load it and updata the relative cache + * structre with data pointer. + * + * it's a test version for my start of merging extlinux into core. + * and after I have figured out how to handle the relations between + * rm and pm, c and asm, we call call it from C file, so no need + * com32sys_t *regs any more. + * + * @return: the data stores at gs:si + * + */ +void get_cache_block(com32sys_t * regs) +{ + /* let's find it from the end, 'cause the endest is the freshest */ + struct cache_struct *cs = cache_head.prev; + struct cache_struct *head, *last; + __u32 block = regs->eax.l; + int i; + + if ( !block ) { + extern void myputs(const char *); + myputs("ERROR: we got a ZERO block number that's not we want!\n"); + return; + } + + /* it's aleardy the freshest, so nothing we need do , just return it */ + if ( cs->block == block ) + goto out; + + for ( i = 0; i < cache_entries; i ++ ) { + if ( cs->block == block ) + break; + else + cs = cs->prev; + } + + if ( i == cache_entries ) { + /* missed, so we need to load it */ + + /* store it at the head of real cache */ + cs = cache_head.next; + + cs->block = block; + getoneblk(cs->data, block, cache_block_size); + } + + /* remove cs from current position in list */ + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + + + /* add to just before head node */ + last = cache_head.prev; + head = &cache_head; + + last->next = cs; + cs->prev = last; + head->prev = cs; + cs->next = head; + + out: + regs->gs = SEG(cs->data); + regs->esi.w[0]= OFFS(cs->data); +} diff --git a/core/cache.h b/core/cache.h new file mode 100644 index 0000000..89892a0 --- /dev/null +++ b/core/cache.h @@ -0,0 +1,27 @@ +#ifndef _CACHE_H +#define _CACHE_H + +#include "types.h" +#include + + +#define MAX_CACHE_ENTRIES 0x064 /* I'm not sure it's the max */ + + + +/* The cache structure */ +struct cache_struct { + __u32 block; + struct cache_struct *prev; + struct cache_struct *next; + void *data; +}; + + + +/* functions defined in cache.c */ +void cache_init(com32sys_t *regs); + +void get_cache_block(com32sys_t *regs); + +#endif /* cache.h */ diff --git a/core/diskstart.inc b/core/diskstart.inc index b804726..4b570bc 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -252,6 +252,7 @@ getonesec: ; that is dead from that point; this saves space. However, please keep ; the order to dst,src to keep things sane. ; + global getlinsec getlinsec: add eax,[bsHidden] ; Add partition offset xor edx,edx ; Zero-extend LBA (eventually allow 64 bits) diff --git a/core/extern.inc b/core/extern.inc index f765cff..e6321d1 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -12,4 +12,7 @@ ; hello.c extern hello + ; cache.c + extern cache_init, get_cache_block + %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 3a054b2..2273ae1 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -153,7 +153,8 @@ Files resb MAX_OPEN*open_file_t_size ; ; Initialize the metadata cache ; - call initcache + mov eax, [ClustSize] + pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more @@ -308,7 +309,7 @@ open_inode: add eax,edx pop edx and dx,SECTOR_SIZE-1 - call getcachesector ; Get the group descriptor + pm_call get_cache_block ; Get the group descriptor add si,dx mov esi,[gs:si+bg_inode_table] ; Get inode table block # pop eax ; Get inode within group @@ -327,7 +328,7 @@ open_inode: and dx,SECTOR_SIZE-1 mov [bx+file_in_off],dx - call getcachesector + pm_call get_cache_block add si,dx mov cx,EXT2_GOOD_OLD_INODE_SIZE >> 2 mov di,ThisInode @@ -693,7 +694,7 @@ linsector: push eax mov eax,[si+file_in_sec] mov bx,si - call getcachesector ; Get inode + pm_call get_cache_block ; Get inode add si,[bx+file_in_off] ; Get *our* inode pop eax lea ebx,[i_block+4*eax] @@ -724,7 +725,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -742,7 +743,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -757,7 +758,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -874,7 +875,6 @@ build_curdir_str: %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output %include "strecpy.inc" ; strcpy with end pointer check -%include "cache.inc" ; Metadata disk cache %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- diff --git a/core/ldlinux.asm b/core/ldlinux.asm index c08799f..4511009 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -211,7 +211,8 @@ getfattype: ; ; Initialize the metadata cache ; - call initcache + mov eax, [ClustSize] + pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more @@ -392,7 +393,7 @@ search_dos_dir: .scansector: ; EAX <- directory sector to scan - call getcachesector + pm_call get_cache_block ; GS:SI now points to this sector mov cx,SECTOR_SIZE/32 ; 32 == directory entry size @@ -745,7 +746,7 @@ readdir: cmp eax,0 jz .fail .fetch_cache: - call getcachesector + pm_call get_cache_block .move_current: add si,bx ; Resume last position in sector mov ecx,SECTOR_SIZE ; 0 out high part @@ -1358,7 +1359,7 @@ nextsector: ; getfatsector: add eax,[FAT] ; FAT starting address - jmp getcachesector + pm_call get_cache_block ; ----------------------------------------------------------------------------- ; Common modules @@ -1368,7 +1369,6 @@ getfatsector: %include "plaincon.inc" ; writechr %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output -%include "cache.inc" ; Metadata disk cache %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- diff --git a/core/printf.c b/core/printf.c new file mode 100644 index 0000000..3872e92 --- /dev/null +++ b/core/printf.c @@ -0,0 +1,27 @@ +#include +#include + + + + +#define BUF_SIZE 1024 + +char buf[BUF_SIZE]; + + +extern void myputs(const char *); + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = sprintf(buf, format, ap); + va_end(ap); + + myputs(buf); + + return rv; + +} diff --git a/core/types.h b/core/types.h new file mode 100644 index 0000000..4cd3902 --- /dev/null +++ b/core/types.h @@ -0,0 +1,17 @@ +#ifndef _TYPES_H +#define _TYPES_H + +typedef unsigned long long __u64; +typedef unsigned int __u32; +typedef unsigned short __u16; +typedef unsigned char __u8; + + +typedef int __s32; +typedef short __s16; +typedef char __s8; + + + + +#endif /* types.h */ -- 2.7.4