From f2fa4525e58ba414220c9f62587b7e7aff35347f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 Aug 2009 17:25:43 -0700 Subject: [PATCH] core: VFS cleanups: add a persistent generic struct file Major cleanups to the VFS layer: - add a persistent generic "struct file" - pass "struct file *" to getfssec - add a close_file method - use VFS-assigned indicies instead of pointers as file handles. This allows the file structures to be allocated from high memory. Signed-off-by: H. Peter Anvin --- core/comboot.inc | 4 +- core/diskfs.inc | 3 -- core/ext2.c | 71 +++++++++++++++++------------ core/extern.inc | 2 +- core/fat.c | 56 ++++++++++++----------- core/fs.c | 133 +++++++++++++++++++++++++++++++++++++++++------------- core/getc.inc | 17 +------ core/include/fs.h | 27 ++++++++--- core/iso9660.c | 22 +++++---- core/isolinux.asm | 2 - core/pxe.c | 32 +++++++------ core/pxelinux.asm | 32 ------------- 12 files changed, 232 insertions(+), 169 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index 007c383..fb0f57f 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -63,7 +63,7 @@ ; Looks like a COMBOOT image but too large comboot_too_large: - call close_file + pm_call close_file mov si,err_comlarge call writestr jmp enter_command @@ -547,7 +547,7 @@ comapi_read: ; comapi_close: mov si,P_SI - call close_file + pm_call close_file clc ret diff --git a/core/diskfs.inc b/core/diskfs.inc index 87e1bfe..474657a 100644 --- a/core/diskfs.inc +++ b/core/diskfs.inc @@ -28,9 +28,6 @@ retry_count equ 16 ; How patient are we with the disk? %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) -MAX_OPEN equ (1 << MAX_OPEN_LG2) - SECTOR_SHIFT equ 9 SECTOR_SIZE equ (1 << SECTOR_SHIFT) diff --git a/core/ext2.c b/core/ext2.c index b57f1e7..91eff8f 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -8,9 +8,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -/* The size of open_file_t in extlinux is double of in others */ -#define MAX_OPEN_LG2 (6 - 1) -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define MAX_SYMLINKS 64 #define SYMLINK_SECTORS 2 @@ -26,7 +23,7 @@ struct open_file_t { uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; @@ -84,19 +81,22 @@ static struct open_file_t *allocate_file(void) /** - * close_file: + * ext2_close_file: * * Deallocates a file structure point by FILE * * @param: file, the file structure we want deallocate * */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *of) { - if (file) - file->file_bytesleft = 0; + of->file_bytesleft = 0; } +static void ext2_close_file(struct file *file) +{ + close_pvt(file->open_file); +} /** * mangle_name: @@ -495,13 +495,14 @@ static void getlinsec_ext(struct fs_info *fs, char *buf, * @return: ECX(of regs), number of bytes read * */ -static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) +static uint32_t ext2_getfssec(struct file *gfile, char *buf, + int sectors, bool *have_more) { int sector_left, next_sector, sector_idx; int frag_start, con_sec_cnt; int bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; if (sectors > sector_left) @@ -528,7 +529,7 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, sector_idx ++; next_sector ++; - }while(next_sector == linsector(fs, sector_idx)); + } while (next_sector == linsector(fs, sector_idx)); #if 0 printf("You are reading data stored at sector --0x%x--0x%x\n", @@ -537,13 +538,14 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, getlinsec_ext(fs, buf, frag_start, con_sec_cnt); buf += con_sec_cnt << 9; file->file_sector += con_sec_cnt; /* next sector index */ - }while(sectors); + } while(sectors); if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; - *have_more = 0; - } else - *have_more = 1; + *have_more = 0; + } else { + *have_more = 1; + } file->file_bytesleft -= bytes_read; return bytes_read; @@ -557,21 +559,28 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, * find a dir entry, if find return it or return NULL * */ -static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) +static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, + struct open_file_t *file, + char *filename) { - int have_more; + bool have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; struct ext2_dir_entry *de; + struct file xfile; + + /* Fake out a VFS file structure */ + xfile.fs = fs; + xfile.open_file = file; /* read a clust at a time */ - ext2_getfssec(fs, trackbuf, file, SecPerClust, &have_more); + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; while (1) { if ((char *)de >= (char *)EndBlock) { if (!have_more) return NULL; - ext2_getfssec(fs, trackbuf, file,SecPerClust,&have_more); + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; } @@ -595,25 +604,29 @@ static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_fil } -static char* do_symlink(struct fs_info *fs, struct open_file_t *file, - uint32_t file_len, char *filename) +static char *do_symlink(struct fs_info *fs, struct open_file_t *file, + uint32_t file_len, char *filename) { - int flag, have_more; + int flag; + bool have_more; char *SymlinkTmpBuf = trackbuf; char *lnk_end; - char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + struct file xfile; + xfile.fs = fs; + xfile.open_file = file; 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 */ + close_pvt(file); /* we've got all we need */ memcpy(SymlinkTmpBuf, this_inode.i_block, file_len); lnk_end = SymlinkTmpBuf + file_len; } else { /* slow symlink */ - ext2_getfssec(fs, SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); + ext2_getfssec(&xfile, SymlinkTmpBuf, SYMLINK_SECTORS, &have_more); lnk_end = SymlinkTmpBuf + file_len; } @@ -695,7 +708,7 @@ static void ext2_searchdir(char *filename, struct file *file) inr = de->d_inode; filename += de->d_name_len; - close_file(open_file); + close_pvt(open_file); goto open; } @@ -721,7 +734,7 @@ static void ext2_searchdir(char *filename, struct file *file) /* Otherwise, something bad ... */ err: - close_file(open_file); + close_pvt(open_file); err_noclose: file_len = 0; open_file = NULL; @@ -794,9 +807,11 @@ static int ext2_fs_init(struct fs_info *fs) const struct fs_ops ext2_fs_ops = { .fs_name = "ext2", + .fs_flags = 0, .fs_init = ext2_fs_init, .searchdir = ext2_searchdir, .getfssec = ext2_getfssec, + .close_file = ext2_close_file, .mangle_name = ext2_mangle_name, .unmangle_name = ext2_unmangle_name, .load_config = ext2_load_config diff --git a/core/extern.inc b/core/extern.inc index eb238be..d944bb1 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -14,7 +14,7 @@ ; fs.c extern fs_init, searchdir, getfssec, mangle_name, load_config - extern unmangle_name + extern unmangle_name, close_file %if IS_SYSLINUX ; fat.c diff --git a/core/fat.c b/core/fat.c index c184730..83dc908 100644 --- a/core/fat.c +++ b/core/fat.c @@ -9,8 +9,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_OPEN_LG2 6 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define ROOT_DIR_WORD 0x002f /* file structure. This holds the information for each currently open file */ @@ -20,7 +18,7 @@ struct open_file_t { uint32_t file_left; /* number of sectors left */ }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; extern uint8_t SecPerClust; @@ -105,12 +103,15 @@ static struct open_file_t *alloc_fill_dir(sector_t sector) /* Deallocates a file structure */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *of) { - if ( file ) - file->file_sector = 0; + of->file_sector = 0; } +static void vfat_close_file(struct file *file) +{ + close_pvt(file->open_file); +} /* Deallocates a directory structure */ @@ -321,11 +322,12 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, * @return: number of bytes read * */ -static uint32_t vfat_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) +static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, + bool *have_more) { uint32_t bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; if ( sectors > file->file_left ) sectors = file->file_left; @@ -669,8 +671,7 @@ static void vfat_searchdir(char *filename, struct file *file) char *p; struct open_file_t *open_file = NULL; - if (file->fs != this_fs) - this_fs = file->fs; + this_fs = file->fs; dir_sector = CurrentDir; if ( *filename == '/' ) { @@ -699,9 +700,10 @@ static void vfat_searchdir(char *filename, struct file *file) mangle_dos_name(MangleBuf, filename); /* close it before open a new dir file */ - close_file(open_file); + if (open_file) + close_pvt(open_file); open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); - if (! open_file) + if (!open_file) goto fail; dir_sector = open_file->file_sector; @@ -721,8 +723,8 @@ static void vfat_searchdir(char *filename, struct file *file) open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; } - file->file_len = file_len; - file->open_file = (void *)open_file; + file->file_len = file_len; + file->open_file = open_file; } @@ -869,13 +871,13 @@ void vfat_readdir(com32sys_t *regs)/* static void vfat_load_config(com32sys_t *regs) { - char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; - char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; - char syslinux_cfg3[] = "/syslinux.cfg"; - char config_name[] = "syslinux.cfg"; + static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; + static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; + static const char syslinux_cfg3[] = "/syslinux.cfg"; + static const char config_name[] = "syslinux.cfg"; - - char *syslinux_cfg[]= {syslinux_cfg1, syslinux_cfg2, syslinux_cfg3}; + const char * const syslinux_cfg[] = + { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 }; com32sys_t oregs; int i = 0; @@ -907,12 +909,10 @@ static void vfat_load_config(com32sys_t *regs) CurrentDir = PrevDir; } -static inline void bsr(uint8_t *res, int num) +static inline __constfunc uint32_t bsr(uint32_t num) { - int i = 0; - while (num >>= 1) - i ++; - *res = i; + asm("bsrl %1,%0" : "=r" (num) : "rm" (num)); + return num; } /* init. the fs meta data, return the block size in bits */ @@ -934,7 +934,7 @@ static int vfat_fs_init(struct fs_info *fs) RootDirSize = (fat.bxRootDirEnts+SECTOR_SIZE/32-1) >> (SECTOR_SHIFT-5); DataArea = RootDirArea + RootDirSize; - bsr(&ClustShift, fat.bxSecPerClust); + ClustShift = bsr(fat.bxSecPerClust); ClustByteShift = ClustShift + SECTOR_SHIFT; ClustMask = fat.bxSecPerClust - 1; ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; @@ -953,9 +953,11 @@ static int vfat_fs_init(struct fs_info *fs) const struct fs_ops vfat_fs_ops = { .fs_name = "vfat", + .fs_flags = 0, .fs_init = vfat_fs_init, .searchdir = vfat_searchdir, .getfssec = vfat_getfssec, + .close_file = vfat_close_file, .mangle_name = vfat_mangle_name, .unmangle_name = vfat_unmangle_name, .load_config = vfat_load_config diff --git a/core/fs.c b/core/fs.c index 0bfa155..c4bf038 100644 --- a/core/fs.c +++ b/core/fs.c @@ -4,11 +4,55 @@ #include "fs.h" #include "cache.h" - -/* The this fs pointer */ +/* The currently mounted filesystem */ struct fs_info *this_fs = NULL; struct fs_info fs; +/* Actual file structures (we don't have malloc yet...) */ +static struct file Files[MAX_OPEN]; + +/* + * Get an empty file structure + */ +static struct file *alloc_file(void) +{ + int i; + struct file *file = Files; + + for (i = 0; i < MAX_OPEN; i++) { + if (!file->open_file) + return file; + } + + return NULL; +} + +/* + * Close and free a file structure + */ +static inline void free_file(struct file *file) +{ + memset(file, 0, sizeof *file); +} + +static void _close_file(struct file *file) +{ + if (file->open_file) + file->fs->fs_ops->close_file(file); + free_file(file); +} + +/* + * Convert between a 16-bit file handle and a file structure + */ +static inline uint16_t file_to_handle(struct file *file) +{ + return file ? (file - Files)+1 : 0; +} +static inline struct file *handle_to_file(uint16_t handle) +{ + return handle ? &Files[handle-1] : NULL; +} void load_config(com32sys_t *regs) { @@ -17,8 +61,8 @@ void load_config(com32sys_t *regs) void mangle_name(com32sys_t *regs) { - char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); + char *src = MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = MK_PTR(regs->es, regs->edi.w[0]); this_fs->fs_ops->mangle_name(dst, src); } @@ -39,21 +83,28 @@ void unmangle_name(com32sys_t *regs) void getfssec(com32sys_t *regs) { int sectors; - int have_more; + bool have_more; uint32_t bytes_read; char *buf; - struct file file; + struct file *file; + uint16_t handle; sectors = regs->ecx.w[0]; - buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); - file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); - file.fs = this_fs; - bytes_read = this_fs->fs_ops->getfssec(file.fs, buf, file.open_file, sectors, &have_more); + handle = regs->esi.w[0]; + file = handle_to_file(handle); + + buf = MK_PTR(regs->es, regs->ebx.w[0]); + bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more); - /* if we reach the EOF, set the si to be NULL */ - if (!have_more) + /* + * If we reach EOF, the filesystem driver will have already closed + * the underlying file... this really should be cleaner. + */ + if (!have_more) { + _close_file(file); regs->esi.w[0] = 0; + } regs->ecx.l = bytes_read; } @@ -62,24 +113,42 @@ void getfssec(com32sys_t *regs) void searchdir(com32sys_t *regs) { char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]);; - struct file file; + struct file *file; -#if 1 +#if 0 printf("filename: %s\n", filename); #endif - 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.open_file) - regs->eflags.l &= ~EFLAGS_ZF; - else - regs->eflags.l |= EFLAGS_ZF; + file = alloc_file(); + + if (file) { + file->fs = this_fs; + file->fs->fs_ops->searchdir(filename, file); + + if (file->open_file) { + regs->esi.w[0] = file_to_handle(file); + regs->eax.l = file->file_len; + regs->eflags.l &= ~EFLAGS_ZF; + return; + } + } + + /* failure... */ + regs->esi.w[0] = 0; + regs->eax.l = 0; + regs->eflags.l |= EFLAGS_ZF; } +void close_file(com32sys_t *regs) +{ + uint16_t handle = regs->esi.w[0]; + struct file *file; + + if (handle) { + file = handle_to_file(handle); + _close_file(file); + } +} /* * it will do: @@ -92,16 +161,18 @@ void searchdir(com32sys_t *regs) void fs_init(com32sys_t *regs) { int blk_shift; - struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - + const struct fs_ops *ops = (const struct fs_ops *)regs->eax.l; + /* set up the fs stucture */ - fs.fs_name = ops->fs_name; fs.fs_ops = ops; - if (!strcmp(fs.fs_name, "pxe")) - fs.fs_dev = NULL; + + /* this is a total hack... */ + if (ops->fs_flags & FS_NODEV) + fs.fs_dev = NULL; /* Non-device filesystem */ else - fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, \ - regs->esi.w[0], regs->edi.w[0]); + fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, + regs->esi.w[0], regs->edi.w[0]); + this_fs = &fs; /* invoke the fs-specific init code */ diff --git a/core/getc.inc b/core/getc.inc index 0aa140b..48b9f77 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -83,24 +83,11 @@ openfd: .ret: ret .stack_full: - call close_file + pm_call close_file xor ax,ax ; ZF <- 1 pop bx ret -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -close_file: - and si,si - jz .closed - mov dword [si],0 ; First dword == file_bytesleft - xor si,si -.closed: ret - - getc: push bx push si @@ -191,7 +178,7 @@ close: push si mov bx,[CurrentGetC] mov si,[bx+gc_file] - call close_file + pm_call close_file add bx,getc_file_size mov [CurrentGetC],bx pop si diff --git a/core/include/fs.h b/core/include/fs.h index ca4e281..21e1349 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -7,26 +7,41 @@ #include "core.h" #include "disk.h" +/* + * Maximum number of open files. This is *currently* constrained by the + * fact that PXE needs to be able to fit all its packet buffers into a + * 64K segment; this should be fixed by moving the packet buffers to high + * memory. + */ +#define MAX_OPEN_LG2 5 +#define MAX_OPEN (1 << MAX_OPEN_LG2) + struct fs_info { - char *fs_name; - struct fs_ops *fs_ops; + const struct fs_ops *fs_ops; struct device *fs_dev; }; +struct open_file_t; /* Filesystem private structure */ + struct file { - void* open_file; /* points to the fs-specific open_file_t */ - struct fs_info *fs; + struct open_file_t *open_file; /* Filesystem private data */ + struct fs_info *fs; uint32_t file_len; }; +enum fs_flags { + FS_NODEV = 1, +}; struct fs_ops { /* in fact, we use fs_ops structure to find the right fs */ - char *fs_name; + const char *fs_name; + enum fs_flags fs_flags; int (*fs_init)(struct fs_info *); void (*searchdir)(char *, struct file *); - uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); + uint32_t (*getfssec)(struct file *, char *, int, bool *); + void (*close_file)(struct file *); void (*mangle_name)(char *, char *); int (*unmangle_name)(char *, char *); void (*load_config)(com32sys_t *); diff --git a/core/iso9660.c b/core/iso9660.c index c7e4041..583513c 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -10,8 +10,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_OPEN_LG2 6 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define ISO_SECTOR_SHIFT 11 #define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) #define ROOT_DIR_WORD 0x002f @@ -24,7 +22,7 @@ struct open_file_t { uint32_t file_left; }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; struct dir_t { uint32_t dir_lba; /* Directory start (LBA) */ @@ -73,10 +71,14 @@ static struct open_file_t *allocate_file(void) * Deallocates a file structure * */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *file) { - if (file) - file->file_sector = 0; + file->file_sector = 0; +} + +static void iso_close_file(struct file *file) +{ + close_pvt(file->open_file); } /** @@ -373,7 +375,7 @@ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, *res = dir; /* we can close it now */ - close_file(file); + close_pvt(file); /* Mark we got a directory */ return 1; @@ -452,7 +454,7 @@ static void iso_searchdir(char *filename, struct file *file) goto found; } err: - close_file(open_file); + close_pvt(open_file); file_len = 0; open_file = NULL; @@ -535,7 +537,7 @@ static int iso_fs_init(struct fs_info *fs) CurrentDir.dir_len = open_file->file_bytesleft; CurrentDir.dir_clust = open_file->file_left; CurrentDir.dir_lba = open_file->file_sector; - close_file(open_file); + close_pvt(open_file); #ifdef DEBUG printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); @@ -548,9 +550,11 @@ static int iso_fs_init(struct fs_info *fs) const struct fs_ops iso_fs_ops = { .fs_name = "iso", + .fs_flags = 0, .fs_init = iso_fs_init, .searchdir = iso_searchdir, .getfssec = iso_getfssec, + .close_file = iso_close_file, .mangle_name = iso_mangle_name, .unmangle_name = iso_unmangle_name, .load_config = iso_load_config diff --git a/core/isolinux.asm b/core/isolinux.asm index 91541bc..2816dd8 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -32,8 +32,6 @@ NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 0 ; Position in which to look retry_count equ 6 ; How patient are we with the BIOS? %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) -MAX_OPEN equ (1 << MAX_OPEN_LG2) SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement) SECTOR_SIZE equ (1 << SECTOR_SHIFT) diff --git a/core/pxe.c b/core/pxe.c index 033e9ba..0b5102a 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -6,15 +6,13 @@ #include #include -#define MAX_OPEN_LG2 5 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define FILENAME_MAX_LG2 7 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define GPXE 1 #define USE_PXE_PROVIDED_STACK 0 -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; static char *err_pxefailed = "PXE API call failed, error "; @@ -99,10 +97,20 @@ static struct open_file_t *allocate_socket(void) */ static void free_socket(struct open_file_t *file) { - /* tftp_pktbuf is not cleared */ + /* tftp_nextport and tftp_pktbuf are not cleared */ memset(file, 0, offsetof(struct open_file_t, tftp_nextport)); } +static void pxe_close_file(struct file *file) +{ + /* + * XXX: we really should see if the connection is open as send + * a courtesy ERROR packet so the server knows the connection is + * dead. + */ + free_socket(file->open_file); +} + /** * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal * @@ -650,17 +658,14 @@ static void fill_buffer(struct open_file_t *file) * @return: the bytes read * */ -static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, - void *open_file, int blocks, int *have_more) +static uint32_t pxe_getfssec(struct file *gfile, char *buf, + int blocks, bool *have_more) { - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; int count = blocks; int chunk; int bytes_read = 0; - sti(); - fs = NULL; /* drop the compile warning message */ - count <<= TFTP_BLOCKSIZE_LG2; while (count) { fill_buffer(file); /* If we have no 'fresh' buffer, get it */ @@ -684,10 +689,9 @@ static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, *have_more = 1; } else if (file->tftp_goteof) { /* - * The socket is closed and the buffer dranined - * close socket structure and re-init for next user + * The socket is closed and the buffer drained; the caller will + * call close_file and therefore free the socket. */ - free_socket(file); *have_more = 0; } @@ -1544,9 +1548,11 @@ static int pxe_fs_init(struct fs_info *fs) const struct fs_ops pxe_fs_ops = { .fs_name = "pxe", + .fs_flags = FS_NODEV, .fs_init = pxe_fs_init, .searchdir = pxe_searchdir, .getfssec = pxe_getfssec, + .close_file = pxe_close_file, .mangle_name = pxe_mangle_name, .unmangle_name = pxe_unmangle_name, .load_config = pxe_load_config diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 06e5206..2e8b319 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -35,17 +35,7 @@ NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 4 ; Position in which to look REBOOT_TIME equ 5*60 ; If failure, time until full reset %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -MAX_OPEN_LG2 equ 5 ; log2(Max number of open sockets) -MAX_OPEN equ (1 << MAX_OPEN_LG2) -PKTBUF_SIZE equ (65536/MAX_OPEN) ; Per-socket packet buffer size TFTP_PORT equ htons(69) ; Default TFTP port -; Desired TFTP block size -; For Ethernet MTU is normally 1500. Unfortunately there seems to -; be a fair number of networks with "substandard" MTUs which break. -; The code assumes TFTP_LARGEBLK <= 2K. -TFTP_MTU equ 1440 -TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr -; Standard TFTP block size TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block) TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2) @@ -764,30 +754,8 @@ BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack KeepPXE db 0 ; Should PXE be kept around? -; -; TFTP commands -; -tftp_tail db 'octet', 0 ; Octet mode -tsize_str db 'tsize' ,0 ; Request size -tsize_len equ ($-tsize_str) - db '0', 0 -blksize_str db 'blksize', 0 ; Request large blocks -blksize_len equ ($-blksize_str) - asciidec TFTP_LARGEBLK - db 0 -tftp_tail_len equ ($-tftp_tail) - alignz 2 ; -; Options negotiation parsing table (string pointer, string len, offset -; into socket structure) -; -tftp_opt_table: - dw tsize_str, tsize_len, tftp_filesize - dw blksize_str, blksize_len, tftp_blksize -tftp_opts equ ($-tftp_opt_table)/6 - -; ; Error packet to return on TFTP protocol error ; Most of our errors are OACK parsing errors, so use that error code ; -- 2.7.4