aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-06-06 05:54:00 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-06-06 05:54:00 +0800
commit1e1622cb4377e7ac5ba7b9164891df5a121c2720 (patch)
treea0f02241f6321ac3663e53ca25ad81c6d1a1962a
parent1be29e2cdba4e406e3a7ca78e3959caacb925e75 (diff)
downloadsyslinux-1e1622cb4377e7ac5ba7b9164891df5a121c2720.tar.gz
syslinux-1e1622cb4377e7ac5ba7b9164891df5a121c2720.tar.xz
syslinux-1e1622cb4377e7ac5ba7b9164891df5a121c2720.zip
Core:EXTLINUX: convert the getfssec function to C
the main file read function (getfssec) has been converted to C. Fow now, abort 90% stuff have been converted to C. The next is to clean the code and convert the rest.
-rw-r--r--core/comboot.inc4
-rw-r--r--core/ext2.c164
-rw-r--r--core/extern.inc2
-rw-r--r--core/extlinux.asm114
-rw-r--r--core/getc.inc2
-rw-r--r--core/include/core.h3
-rw-r--r--core/loadhigh.inc2
-rw-r--r--core/runkernel.inc2
8 files changed, 128 insertions, 165 deletions
diff --git a/core/comboot.inc b/core/comboot.inc
index 1cb5ac6e..dee8405b 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -126,7 +126,7 @@ is_comboot_image:
mov bx,100h ; Load at <seg>:0100h
mov cx,10000h >> SECTOR_SHIFT
; Absolute maximum # of sectors
- call getfssec
+ pm_call getfssec
cmp ecx,65536-256-2 ; Maximum size
ja comboot_too_large
@@ -535,7 +535,7 @@ comapi_read:
mov bx,P_BX
mov si,P_SI
mov cx,P_CX
- call getfssec
+ pm_call getfssec
jnc .noteof
xor si,si ; SI <- 0 on EOF, CF <- 0
.noteof: mov P_SI,si
diff --git a/core/ext2.c b/core/ext2.c
index b7f61419..709c1f4e 100644
--- a/core/ext2.c
+++ b/core/ext2.c
@@ -5,9 +5,10 @@
#include "disk.h"
#include "ext2_fs.h"
-
#define MAX_OPEN_LG2 6
#define MAX_OPEN (1 << MAX_OPEN_LG2)
+#define MAX_SYMLINKS 64
+#define SYMLINK_SECTORS 2
/*
* File structure, This holds the information for each currently open file
@@ -21,25 +22,17 @@ struct open_file_t {
};
extern char Files[MAX_OPEN * sizeof(struct open_file_t)];
-
-
extern char ThisInode[128];
struct ext2_inode *this_inode = ThisInode;
+struct ext2_super_block *sb;
extern uint16_t ClustByteShift, ClustShift;
extern uint32_t SecPerClust, ClustSize, ClustMask;
extern uint32_t PtrsPerBlock1, PtrsPerBlock2;
uint32_t PtrsPerBlock3;
-
int DescPerBlock, InodePerBlock;
-struct ext2_super_block *sb;
-
-
-extern char trackbuf[8192];
-
-#define MAX_SYMLINKS 64
-#define SYMLINK_SECTORS 2
+extern char trackbuf[8192];
extern char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64];
@@ -355,9 +348,8 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode)
*
* @return: physic sector number
*/
-void linsector(com32sys_t *regs)
+sector_t linsector(sector_t lin_sector)
{
- sector_t lin_sector = regs->eax.l;
block_t block = lin_sector >> ClustShift;
struct ext2_inode *inode;
@@ -371,12 +363,11 @@ void linsector(com32sys_t *regs)
if (!block) {
printf("ERROR: something error happend at linsector..\n");
- regs->eax.l = 0;
- return;
+ return 0;
}
/* finally convert it to sector */
- regs->eax.l = ((block << ClustShift) + (lin_sector & ClustMask));
+ return ((block << ClustShift) + (lin_sector & ClustMask));
}
@@ -402,24 +393,122 @@ inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p)
return (struct ext2_dir_entry *)((char*)p + p->d_rec_len);
}
+/**
+ * getlinsec_ext:
+ *
+ * same as getlinsec, except load any sector from the zero
+ * block as all zeros; use to load any data derived from
+ * n ext2 block pointer, i.e. anything *except the superblock
+ *
+ */
+void getlinsec_ext(char *buf, sector_t sector, int sector_cnt)
+{
+ int ext_cnt = 0;
+
+ if ( sector < SecPerClust ) {
+ ext_cnt = SecPerClust - sector;
+ memset(buf, 0, ext_cnt << SECTOR_SHIFT);
+ buf += ext_cnt << SECTOR_SHIFT;
+ }
+
+ sector += ext_cnt;
+ sector_cnt -= ext_cnt;
+ read_sectors(buf, sector, sector_cnt);
+}
+
+/**
+ * getfssec:
+ *
+ * Get multiple sectors from a file
+ *
+ * Alought we have made the buffer data based on block size,
+ * we use sector for implemention; because reading multiple
+ * sectors (then can be multiple blocks) is what the function
+ * do. So, let it be based on sectors.
+ *
+ * This function can be called from C function, and either from
+ * ASM function.
+ *
+ * @param: ES:BX(of regs), the buffer to store data
+ * @param: DS:SI(of regs), the pointer to open_file_t
+ * @param: CX(of regs), number of sectors to read
+ *
+ * @return: ECX(of regs), number of bytes read
+ *
+ */
+void getfssec(com32sys_t *regs)
+{
+ 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]);
+
+ sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ if ( sectors > sector_left )
+ sectors = sector_left;
+
+ while (sectors) {
+ /*
+ * get the frament
+ */
+ sector_idx = file->file_sector;
+ next_sector = frag_start = linsector(sector_idx);
+ con_sec_cnt = 0;
+
+ /* get the consective sectors count */
+ do {
+ con_sec_cnt ++;
+ sectors --;
+ if ( sectors <= 0 )
+ break;
+
+ /* if sectors >= the sectors left in the 64K block, break and read */
+ if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1) )
+ break;
+
+ sector_idx ++;
+ next_sector ++;
+ }while( next_sector == linsector(sectors) );
+
+#if 0
+ printf("You are reading stores at sector --0x%x--0x%x\n",
+ frag_start, frag_start + con_sec_cnt -1);
+#endif
+ getlinsec_ext(buf, frag_start, con_sec_cnt);
+ buf += con_sec_cnt << 9;
+ file->file_sector += con_sec_cnt; /* next sector index */
+ }while(sectors);
+
+ if ( bytes_read >= file->file_bytesleft )
+ bytes_read = file->file_bytesleft;
+ 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, out_regs;
+ com32sys_t regs;
memset(&regs, 0, sizeof regs);
- memset(&out_regs, 0, sizeof out_regs);
-
+
/*
- * for now, the buf and file structure are stored at low
- * address, so we can reference it safely by SEG() and
- * OFFS() operation.
+ * for now, even though the buf and file structure are stored
+ * at low address, BUT find:
*
- * !find we can't use SEG stuff here, say the address of buf
- * is 0x800(found in debug), the addres would be broken like
+ * 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, the one that still be asm code now.
+ * function need.
*
* so we just do like:
* regs.ebx.w[0] = buf;
@@ -427,13 +516,12 @@ void getfssec_ext(char *buf, struct open_file_t *file,
regs.ebx.w[0] = buf;
regs.esi.w[0] = file;
regs.ecx.w[0] = sectors;
-
- call16(getfssec, &regs, &out_regs);
+ getfssec(&regs);
*have_more = 1;
/* the file is closed ? */
- if( !out_regs.esi.w[0] )
+ if( !file->file_bytesleft )
*have_more = 0;
}
@@ -456,11 +544,10 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename)
while ( 1 ) {
if ( (char *)de >= (char *)EndBlock ) {
- if (have_more) {
- getfssec_ext(trackbuf, file,SecPerClust,&have_more);
- de = (struct ext2_dir_entry *)trackbuf;
- } else
+ if (!have_more)
return NULL;
+ getfssec_ext(trackbuf, file,SecPerClust,&have_more);
+ de = (struct ext2_dir_entry *)trackbuf;
}
/* Zero inode == void entry */
@@ -491,8 +578,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename)
char *lnk_end;
char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64;
- flag = this_inode->i_file_acl ? SecPerClust : 0;
-
+ flag = this_inode->i_file_acl ? SecPerClust : 0;
if ( this_inode->i_blocks == flag ) {
/* fast symlink */
close_file(file); /* we've got all we need */
@@ -505,12 +591,6 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename)
lnk_end = SymlinkTmpBuf + file_len;
}
- /*
- * well, this happens like:
- * "/boot/xxx/y/z.abc" where xxx is a symlink to "/other/here"
- * so, we should get a new path name like:
- * "/other/here/y/z.abc"
- */
if ( *filename != 0 )
*lnk_end++ = '/';
@@ -538,8 +618,8 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename)
*
* @param: filename, the filename we want to search.
*
- * @out : a file pointer
- * @out : file lenght in bytes
+ * @out : a file pointer, stores in DS:SI ( NOTE, DS == 0)
+ * @out : file lenght in bytes, stores in eax
*
*/
void searchdir(com32sys_t * regs)
diff --git a/core/extern.inc b/core/extern.inc
index e8e0a697..255a91f8 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -19,6 +19,6 @@
extern load_config
; ext2.c
- extern init_fs, linsector, searchdir
+ extern init_fs, searchdir, getfssec
%endif ; EXTERN_INC
diff --git a/core/extlinux.asm b/core/extlinux.asm
index 9e9b6521..4a4d8ac2 100644
--- a/core/extlinux.asm
+++ b/core/extlinux.asm
@@ -167,36 +167,6 @@ Files resb MAX_OPEN*open_file_t_size
;
%include "ui.inc"
-;
-; getlinsec_ext: same as getlinsec, except load any sector from the zero
-; block as all zeros; use to load any data derived
-; from an ext2 block pointer, i.e. anything *except the
-; superblock.*
-;
-getonesec_ext:
- mov bp,1
-
-getlinsec_ext:
- cmp eax,[SecPerClust]
- jae getlinsec ; Nothing fancy
-
- ; If we get here, at least part of what we want is in the
- ; zero block. Zero one sector at a time and loop.
- push eax
- push cx
- xchg di,bx
- xor eax,eax
- mov cx,SECTOR_SIZE >> 2
- rep stosd
- xchg di,bx
- pop cx
- pop eax
- inc eax
- dec bp
- jnz getlinsec_ext
- ret
-
-
section .bss16
alignb 4
@@ -309,90 +279,6 @@ kaboom2:
-;
-; getfssec: Get multiple sectors from a file
-;
-; Same as above, except SI is a pointer to a open_file_t
-;
-; ES:BX -> Buffer
-; DS:SI -> Pointer to open_file_t
-; CX -> Sector count (0FFFFh = until end of file)
-; Must not exceed the ES segment
-; Returns CF=1 on EOF (not necessarily error)
-; On return ECX = number of bytes read
-; All arguments are advanced to reflect data read.
-;
- global getfssec
-getfssec:
- push ebp
- push eax
- push edx
- push edi
-
- movzx ecx,cx
- push ecx ; Sectors requested read
- mov eax,[si+file_bytesleft]
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- cmp ecx,eax ; Number of sectors left
- jbe .lenok
- mov cx,ax
-.lenok:
-.getfragment:
- mov eax,[si+file_sector] ; Current start index
- mov edi,eax
- pm_call linsector
- push eax ; Fragment start sector
- mov edx,eax
- xor ebp,ebp ; Fragment sector count
-.getseccnt:
- inc bp
- dec cx
- jz .do_read
- xor eax,eax
- mov ax,es
- shl ax,4
- add ax,bx ; Now DI = how far into 64K block we are
- not ax ; Bytes left in 64K block
- inc eax
- shr eax,SECTOR_SHIFT ; Sectors left in 64K block
- cmp bp,ax
- jnb .do_read ; Unless there is at least 1 more sector room...
- inc edi ; Sector index
- inc edx ; Linearly next sector
- mov eax,edi
- pm_call linsector
- ; jc .do_read
- cmp edx,eax
- je .getseccnt
-.do_read:
- pop eax ; Linear start sector
- pushad
- call getlinsec_ext
- popad
- push bp
- shl bp,9
- add bx,bp ; Adjust buffer pointer
- pop bp
- add [si+file_sector],ebp ; Next sector index
- jcxz .done
- jnz .getfragment
- ; Fall through
-.done:
- pop ecx ; Sectors requested read
- shl ecx,SECTOR_SHIFT
- sub [si+file_bytesleft],ecx
- jnbe .noteof ; CF=0 in this case
- add ecx,[si+file_bytesleft] ; Actual number of bytes read
- call close_file
- stc ; We hit EOF
-.noteof:
- pop edi
- pop edx
- pop eax
- pop ebp
- ret
-
build_curdir_str:
ret
diff --git a/core/getc.inc b/core/getc.inc
index b40a4200..a8b49549 100644
--- a/core/getc.inc
+++ b/core/getc.inc
@@ -136,7 +136,7 @@ getc:
mov [di+gc_bufbytes],si ; In case SI == 0
jz .empty
mov cx,bytes_per_getc >> SECTOR_SHIFT
- call getfssec
+ pm_call getfssec
mov [di+gc_bufbytes],cx
mov [di+gc_file],si
jcxz .empty
diff --git a/core/include/core.h b/core/include/core.h
index a57dac29..574fd7af 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -14,9 +14,6 @@ extern char ConfigName[];
/* diskstart.inc */
extern void getlinsec(void);
-/* extlinux.asm */
-extern void getfssec(void);
-
/* getc.inc */
extern void core_open(void);
diff --git a/core/loadhigh.inc b/core/loadhigh.inc
index 5c9969f6..63ab0010 100644
--- a/core/loadhigh.inc
+++ b/core/loadhigh.inc
@@ -69,7 +69,7 @@ load_high:
push edi ; <C> Target buffer
mov cx,ax
xor bx,bx ; ES:0
- call getfssec ; Load the data into xfer_buf_seg
+ pm_call getfssec ; Load the data into xfer_buf_seg
pop edi ; <C> Target buffer
pushf ; <C> EOF status
lea ebx,[edi+ecx] ; End of data
diff --git a/core/runkernel.inc b/core/runkernel.inc
index 71302108..65c19932 100644
--- a/core/runkernel.inc
+++ b/core/runkernel.inc
@@ -58,7 +58,7 @@ is_linux_kernel:
mov cx,8000h >> SECTOR_SHIFT ; Half a moby (32K)
xor bx,bx
pop si ; <A> file pointer
- call getfssec
+ pm_call getfssec
cmp cx,1024
jb kernel_corrupt
cmp word [es:bs_bootsign],0AA55h