From: Liu Aleaxander Date: Sun, 21 Jun 2009 06:59:46 +0000 (+0800) Subject: Core:ISOLINUX: convert the isolinux.asm to C X-Git-Tag: syslinux-4.00-pre1~16^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=afa8f040dba2e7b90a953d5ff00fe19b42d444a2;p=profile%2Fivi%2Fsyslinux.git Core:ISOLINUX: convert the isolinux.asm to C --- diff --git a/core/Makefile b/core/Makefile index c41b423..0f257f1 100644 --- a/core/Makefile +++ b/core/Makefile @@ -33,7 +33,8 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ - extlinux.bin extlinux.bss extlinux.sys + extlinux.bin extlinux.bss extlinux.sys \ + isolinux.bin isolinux-debug.bin # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) diff --git a/core/disk.c b/core/disk.c index 8ec880c..69a9c0b 100644 --- a/core/disk.c +++ b/core/disk.c @@ -6,7 +6,7 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) { com32sys_t regs; - static __lowmem char low_buf[65536]; + //static __lowmem char low_buf[65536]; /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ int high_addr = (buf + (sectors << SECTOR_SHIFT)) > (char *)0x100000; @@ -15,17 +15,17 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) regs.ebp.l = sectors; if (high_addr) { - regs.es = SEG(low_buf); - regs.ebx.w[0] = OFFS(low_buf); + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); } else { regs.es = SEG(buf); - regs.ebx.w[0] = OFFS(buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); } call16(getlinsec, ®s, NULL); if (high_addr) - memcpy(buf, low_buf, sectors << SECTOR_SHIFT); + memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); } diff --git a/core/diskstart.inc b/core/diskstart.inc index a08aa28..3dc8f8a 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -729,6 +729,7 @@ expand_super: mov eax,iso_fs_ops %endif mov dl,[DriveNumber] + mov dh,0 ; it's a disk not cdrom mov ecx,[bsHidden] mov ebx,[bsHidden+4] %endif diff --git a/core/fs.c b/core/fs.c index 617e3e5..5dc767a 100644 --- a/core/fs.c +++ b/core/fs.c @@ -1,4 +1,5 @@ #include +#include #include #include "fs.h" #include "cache.h" @@ -105,30 +106,24 @@ uint8_t detect_edd(uint8_t device_num) /* * initialize the device structure */ -void device_init(struct device *dev, uint8_t device_num, sector_t offset) +void device_init(struct device *dev, uint8_t device_num, + bool cdrom, sector_t offset) { dev->device_number = device_num; dev->part_start = offset; 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) ) { + if (!cdrom) { /* 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]; + "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; - - /* I just considered the floppy and disk now */ - dev->read_sectors = read_sectors; } @@ -156,7 +151,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->ecx.l); + device_init(&dev, regs->edx.b[0], regs->edx.b[1], regs->ecx.l); /* set up the fs stucture */ fs.fs_name = ops->fs_name; diff --git a/core/include/core.h b/core/include/core.h index 574fd7a..f7a7262 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -11,7 +11,7 @@ extern char CurrentDirName[]; extern char ConfigName[]; -/* diskstart.inc */ +/* diskstart.inc isolinux.asm*/ extern void getlinsec(void); /* getc.inc */ diff --git a/core/include/fs.h b/core/include/fs.h index 0cb1bfc..208b22d 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -5,10 +5,6 @@ #include "core.h" #include "disk.h" -/* I don't know it's right or not */ -#define USE_CACHE(device_num) (device_num >= 0x00 && device_num < 0xfe) - - struct fs_info { char *fs_name; struct fs_ops *fs_ops; diff --git a/core/include/iso9660_fs.h b/core/include/iso9660_fs.h new file mode 100644 index 0000000..ca123b1 --- /dev/null +++ b/core/include/iso9660_fs.h @@ -0,0 +1,21 @@ +#ifndef ISO9660_FS_H +#define ISO9660_FS_H + +#include + +struct iso_dir_entry { + uint8_t length; /* 00 */ + uint8_t ext_attr_length; /* 01 */ + uint8_t extent[8]; /* 02 */ + uint8_t size[8]; /* 0a */ + uint8_t date[7]; /* 12 */ + uint8_t flags; /* 19 */ + uint8_t file_unit_size; /* 1a */ + uint8_t interleave; /* 1b */ + uint8_t volume_sequence_number[4]; /* 1c */ + uint8_t name_len; /* 20 */ + //uint8_t name[]; /* 21 */ +}; + + +#endif /* iso9660_fs.h */ diff --git a/core/iso9660.c b/core/iso9660.c new file mode 100644 index 0000000..267b8cd --- /dev/null +++ b/core/iso9660.c @@ -0,0 +1,580 @@ +#include +#include +//#include "cache.h" +#include "core.h" +#include "disk.h" +#include "iso9660_fs.h" +#include "fs.h" + +#define DEBUG 1 + +#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 +#define TRACKBUF_SIZE 8192 + + +struct open_file_t { + uint32_t file_sector; + uint32_t file_bytesleft; + uint32_t file_left; + uint32_t pad; +}; +extern char Files[]; + +struct dir_t { + uint32_t dir_lba; /* Directory start (LBA) */ + uint32_t dir_len; /* Length in bytes */ + uint32_t dir_clust; /* Length in clusters */ +}; +struct dir_t RootDir; +struct dir_t CurrentDir; + + +extern char trackbuf[TRACKBUF_SIZE]; +uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; +uint16_t BufSafeBytes = TRACKBUF_SIZE; + +char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ +char *ISOFileNameEnd = &ISOFileName[64]; + +uint32_t FirstSecSum; /* checksum of bytes 64-2048 */ +uint32_t ImageDwords; /* isolinux.bin size, dwords */ +uint32_t InitStack; /* Initial stack pointer (SS:SP) */ +uint16_t DiskSys; /* Last INT 13h call */ +uint16_t ImageSectors; /* isolinux.bin size, sectors */ + +/* These following two are accessed as a single dword ... */ +uint16_t GetlinsecPtr; /* the sector-read pointer */ +uint16_t BIOSType; +uint8_t DiskError; /* Error code for disk I/O */ +uint8_t DriveNumber; /* CD-ROM BIOS drive number */ +uint8_t ISOFlags; /* Flags for ISO directory search */ +uint8_t RetryCount; /* Used for ISO directory search */ +uint16_t bsSecPerTrack; /* Used in hybrid mode */ +uint16_t bsHeads; /* Used in hybrid mode */ + + +/** + * allocate_file: + * + * allocate a file structure + * + */ +struct open_file_t *allocate_file() +{ + struct open_file_t *file; + int i = 0; + + file = (struct open_file_t *)Files; + for (; i < MAX_OPEN; i ++ ) { + if ( file->file_sector == 0 ) /* found it */ + return file; + file ++; + } + + return NULL; /* not found */ +} + + +/** + * close_file: + * + * Deallocates a file structure + * + */ +void close_file(struct open_file_t *file) +{ + if (file) + file->file_sector = 0; +} + +void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) +{ + com32sys_t regs; + //static __lowmem char low_buf[65536]; + /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ + int high_addr = (buf + (sectors << ISO_SECTOR_SHIFT)) > (char *)0x100000; + + memset(®s, 0, sizeof regs); + regs.eax.l = sector_num; + regs.ebp.l = sectors; + + if (high_addr) { + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); + } else { + regs.es = SEG(buf); + regs.ebx.w[0] = OFFS(buf); + } + + call16(getlinsec, ®s, NULL); + + if (high_addr) + memcpy(buf, core_xfer_buf, sectors << ISO_SECTOR_SHIFT); +} + + + + +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed + * to by dst; ends on encountering any whitespace. + * dst is preserved. + * + * This verifies that a filename is < FilENAME_MAX characters, + * doesn't contain whitespace, zero-pads the output buffer, + * and removes trailing dots and redumndant slashes, so "repe + * cmpsb" can do a compare, and the path-searching routine gets + * a bit of an easier job. + * + */ +void iso_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX - 1; + + while ( *src > ' ' ) { + if ( *src == '/' ) { + if ( *(src+1) == '/' ) { + i --; + src ++; + continue; + } + } + + *dst++ = *src ++; + i --; + } + + while ( 1 ) { + if ( dst == p ) + break; + + if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i -- ) + *dst++ = '\0'; +} + + +/** + * compare the names si and di and report if they are + * equal from an ISO 9600 perspective. + * + * @param: de_name, the name from the file system. + * @param: len, the length of de_name, and will return the real name of the de_name + * ';' and other terminates excluded. + * @param: file_name, the name we want to check, is expected to end with a null + * + * @return: 1 on match, or 0. + * + */ +int iso_compare_names(char *de_name, int *len, char *file_name) +{ + char *p = ISOFileName; + char c1, c2; + + int i = 0; + + while ( (i < *len) && *de_name && (*de_name != ';') && (p < ISOFileNameEnd - 1) ) { + *p++ = *de_name++; + i++; + } + + /* Remove terminal dots */ + while ( *(p-1) == '.' ) { + if ( *len <= 2 ) + break; + + if ( p <= ISOFileName ) + break; + p --; + i--; + } + + if ( i <= 0 ) + return 0; + + *p = '\0'; + + /* return the 'real' length of de_name */ + *len = i; + + p = ISOFileName; + + /* i is the 'real' name length of file_name */ + while ( i ) { + c1 = *p++; + c2 = *file_name++; + + if ( (c1 == 0) && (c2 == 0) ) + return 1; /* success */ + + else if ( (c1 == 0) || ( c2 == 0 ) ) + return 0; + + c1 |= 0x20; + c2 |= 0x20; /* convert to lower case */ + if ( c1 != c2 ) + return 0; + i --; + } + + return 1; +} + + +/** + * iso_getfssec: + * + * Get multiple clusters from a file, given the file pointer. + * + * we don't use the fs struct for now + * + * @param: buf + * @param: file, the address of the open file structure + * @param: sectors, how many we want to read at once + * @param: have_more, to indicate if we have reach the end of the file + * + */ +uint32_t iso_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) +{ + uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; + struct open_file_t *file = (struct open_file_t *)open_file; + + if ( sectors > file->file_left ) + sectors = file->file_left; + + getlinsec_cdrom(buf, file->file_sector, sectors); + + file->file_sector += sectors; + file->file_left -= sectors; + + if ( bytes_read >= file->file_bytesleft ) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else + *have_more = 1; + file->file_bytesleft -= bytes_read; + + return bytes_read; +} + + + +/** + * do_search_dir: + * + * find a file or directory with name within the _dir_ directory. + * + * the return value will tell us what we find, it's a file or dir? + * on 1 be dir, 2 be file, 0 be error. + * + * res will return the result. + * + */ +int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) +{ + struct open_file_t *file; + struct iso_dir_entry *de; + struct iso_dir_entry tmpde; + + uint32_t offset = 0; /* let's start it with the start */ + uint32_t file_pos = 0; + char *de_name; + int de_len; + int de_name_len; + int have_more; + + file = allocate_file(); + if ( !file ) + return 0; + + file->file_left = dir->dir_clust; + file->file_sector = dir->dir_lba; + + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + de = (struct iso_dir_entry *)trackbuf; + + while ( file_pos < dir->dir_len ) { + int found = 0; + + if ( (char *)de >= (char *)(trackbuf + TRACKBUF_SIZE) ) { + if ( !have_more ) + return 0; + + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + offset = 0; + } + + de = (struct iso_dir_entry *) (trackbuf + offset); + + de_len = de->length; + + if ( de_len == 0) { + offset = file_pos = (file_pos+ISO_SECTOR_SIZE) & ~(ISO_SECTOR_SIZE-1); + continue; + } + + + offset += de_len; + + /* Make sure we have a full directory entry */ + if ( offset >= TRACKBUF_SIZE ) { + int slop = TRACKBUF_SIZE - offset + de_len; + memcpy(&tmpde, de, slop); + offset &= TRACKBUF_SIZE - 1; + file->file_sector ++; + if ( offset ) { + if ( !have_more ) + return 0; + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + memcpy((void*)&tmpde + slop, trackbuf, offset); + } + de = &tmpde; + } + + if ( de_len < 33 ) { + printf("Corrutped directory entry in sector %d\n", file->file_sector); + return 0; + } + + de_name_len = de->name_len; + de_name = (char *)((void *)de + 0x21); + + + if ( (de_name_len == 1) && (*de_name == 0) ) { + found = iso_compare_names(".", &de_name_len, name); + + } else if ( (de_name_len == 1) && (*de_name == 1) ) { + de_name_len = 2; + found = iso_compare_names("..", &de_name_len, name); + + } else + found = iso_compare_names(de_name, &de_name_len, name); + + if (found) + break; + + file_pos += de_len; + } + + if ( file_pos >= dir->dir_len ) + return 0; /* not found */ + + + if ( *(name+de_name_len) && (*(name+de_name_len) != '/' ) ) { + printf("Something wrong happened during searching file %s\n", name); + + *res = NULL; + return 0; + } + + if ( de->flags & 0x02 ) { + /* it's a directory */ + dir = &CurrentDir; + dir->dir_lba = *(uint32_t *)de->extent; + dir->dir_len = *(uint32_t *)de->size; + dir->dir_clust = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = dir->dir_len; + *res = dir; + + /* we can close it now */ + close_file(file); + + /* Mark we got a directory */ + return 1; + } else { + /* it's a file */ + file->file_sector = *(uint32_t *)de->extent; + file->file_bytesleft = *(uint32_t *)de->size; + file->file_left = (file->file_bytesleft + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = file->file_bytesleft; + *res = file; + + /* Mark we got a file */ + return 2; + } +} + + +/** + * iso_searchdir: + * + * open a file + * + * searchdir_iso is a special entry point for ISOLINUX only. In addition + * to the above, searchdir_iso passes a file flag mask in AL. This is + * useful for searching for directories. + * + * well, it's not like the searchidr function in EXT fs or FAT fs; it also + * can read a diretory.(Just thought of mine, liu) + * + */ +void iso_searchdir(char *filename, struct file *file) +{ + struct open_file_t *open_file = NULL; + struct dir_t *dir; + uint32_t file_len; + int ret; + void *res; + + dir = &CurrentDir; + if ( *filename == '/' ) { + dir = &RootDir; + filename ++; + } + + while ( *filename ) { + + ret = do_search_dir(dir, filename, &file_len, &res); + if ( ret == 1 ) + dir = (struct dir_t *)res; + else if ( ret == 2 ) + break; + else + goto err; + + /* find the end */ + while ( *filename && (*filename != '/') ) + filename ++; + + /* skip the slash */ + while ( *filename && (*filename == '/') ) + filename++; + } + + /* well , we need recheck it , becuase it can be a directory */ + if ( ret == 2 ) { + open_file = (struct open_file_t *)res; + goto found; + } else { + open_file = allocate_file(); + if ( !open_file ) + goto err; + + open_file->file_sector = dir->dir_lba; + open_file->file_bytesleft = dir->dir_len; + open_file->file_left = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + goto found; + } + err: + close_file(open_file); + file_len = 0; + open_file = NULL; + + found: + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 0 + 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 iso_load_config(com32sys_t *regs) +{ + char *config_name = "isolinux.cfg"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + + regs->edi.w[0] = ConfigName; + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); +} + + +int iso_fs_init() +{ + char *iso_dir; + char *boot_dir = "/boot/isolinux"; + char *isolinux_dir = "/isolinux"; + + struct file file; + struct open_file_t *open_file; + int len; + int bi_pvd = 16; + + getlinsec_cdrom(trackbuf, bi_pvd, 1); + + CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); + +#ifdef DEBUG + printf("Root directory at LBA = 0x%x\n", RootDir.dir_lba); +#endif + + CurrentDir.dir_len = RootDir.dir_len = *(uint32_t*)(trackbuf + 156 + 10); + CurrentDir.dir_clust = RootDir.dir_clust = (RootDir.dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + /* + * Look for an isolinux directory, and if found, + * make it the current directory instead of the + * root directory. + * + * Also copy the name of the directory to CurrrentDirName + */ + *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; + + iso_dir = boot_dir; + iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ + if ( !file.file_len ) { + iso_dir = isolinux_dir; + iso_searchdir(isolinux_dir, &file); /* search for /isolinux */ + if ( !file.file_len ) + goto no_isolinux_dir; + } + + strcpy(CurrentDirName, iso_dir); + len = strlen(CurrentDirName); + CurrentDirName[len] = '/'; + CurrentDirName[len+1] = '\0'; + + open_file = (struct open_file_t *)file.open_file; + 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); + +#ifdef DEBUG + printf("isolinux directory at LBA = %0x%x\n", CurrentDir.dir_lba); +#endif + + no_isolinux_dir: + printf("No isolinux directory found\n"); + + /* we do not use cache for now, so we can just return 0 */ + return 0; +} + + +const struct fs_ops iso_fs_ops = { + .fs_name = "iso", + .fs_init = iso_fs_init, + .searchdir = iso_searchdir, + .getfssec = iso_getfssec, + .mangle_name = iso_mangle_name, + .unmangle_name = NULL, + .load_config = iso_load_config +}; diff --git a/core/isolinux.asm b/core/isolinux.asm index b2c9c98..1a1cae9 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -86,6 +86,7 @@ dir_clust resd 1 ; Length in clusters ; Memory below this point is reserved for the BIOS and the MBR ; section .earlybss + global trackbuf trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h @@ -191,6 +192,7 @@ _spec_end equ $ _spec_len equ _spec_end - _spec_start section .bss16 + global Files alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size @@ -767,6 +769,7 @@ getonesec: ; ES:BX - Target buffer ; BP - Sector count ; + global getlinsec getlinsec: jmp word [cs:GetlinsecPtr] %ifndef DEBUG_MESSAGES @@ -1160,90 +1163,25 @@ all_read: ; (which will be at 16 only for a single-session disk!); from the PVD ; we should be able to find the rest of what we need to know. ; -get_fs_structures: - mov eax,[bi_pvd] - mov bx,trackbuf - call getonesec - - mov eax,[trackbuf+156+2] - mov [RootDir+dir_lba],eax - mov [CurrentDir+dir_lba],eax -%ifdef DEBUG_MESSAGES - mov si,dbg_rootdir_msg - call writemsg - call writehex8 - call crlf -%endif - mov eax,[trackbuf+156+10] - mov [RootDir+dir_len],eax - mov [CurrentDir+dir_len],eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [RootDir+dir_clust],eax - mov [CurrentDir+dir_clust],eax - - ; Look for an isolinux directory, and if found, - ; make it the current directory instead of the root - ; directory. - ; Also copy the name of the directory to CurrentDirName - mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName - mov di,boot_dir ; Search for /boot/isolinux - mov al,02h - push di - call searchdir_iso - pop di - jnz .found_dir - mov di,isolinux_dir - mov al,02h ; Search for /isolinux - push di - call searchdir_iso - pop di - jz .no_isolinux_dir -.found_dir: - ; Copy current directory name to CurrentDirName - push si - push di - mov si,di - mov di,CurrentDirName - call strcpy - mov byte [di],0 ;done in case it's not word aligned - dec di - mov byte [di],'/' - pop di - pop si - - mov [CurrentDir+dir_len],eax - mov eax,[si+file_left] - mov [CurrentDir+dir_clust],eax - xor eax,eax ; Free this file pointer entry - xchg eax,[si+file_sector] - mov [CurrentDir+dir_lba],eax -%ifdef DEBUG_MESSAGES - push si - mov si,dbg_isodir_msg - call writemsg - pop si - call writehex8 - call crlf -%endif -.no_isolinux_dir: + pushad + extern iso_fs_ops + mov eax,iso_fs_ops + mov dl,[DriveNumber] + mov dh,1 ; it's cdrom + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] + pm_call fs_init + popad ; ; Locate the configuration file ; -load_config: %ifdef DEBUG_MESSAGES mov si,dbg_config_msg call writemsg %endif - mov si,config_name - mov di,ConfigName - call strcpy - - mov di,ConfigName - call open - jz no_config_file ; Not found or empty + pm_call load_config %ifdef DEBUG_MESSAGES mov si,dbg_configok_msg @@ -1289,7 +1227,7 @@ is_disk_image: mov bx,trackbuf mov cx,1 ; Load 1 sector - call getfssec + pm_call getfssec cmp word [trackbuf+510],0aa55h ; Boot signature jne .bad_image ; Image not bootable @@ -1386,284 +1324,6 @@ is_disk_image: mov al,bl .done_sector: 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_left - xor si,si -.closed: ret - -; -; searchdir: -; -; Open a file -; -; On entry: -; DS:DI = filename -; If successful: -; ZF clear -; SI = file pointer -; EAX = file length in bytes -; If unsuccessful -; ZF set -; -; Assumes CS == DS == ES, and trashes BX and CX. -; -; searchdir_iso is a special entry point for ISOLINUX only. In addition -; to the above, searchdir_iso passes a file flag mask in AL. This is useful -; for searching for directories. -; -alloc_failure: - xor ax,ax ; ZF <- 1 - ret - -searchdir: - xor al,al -searchdir_iso: - mov [ISOFlags],al - TRACER 'S' - call allocate_file ; Temporary file structure for directory - jnz alloc_failure - push es - push ds - pop es ; ES = DS - mov si,CurrentDir - cmp byte [di],'/' ; If filename begins with slash - jne .not_rooted - inc di ; Skip leading slash - mov si,RootDir ; Reference root directory instead -.not_rooted: - mov eax,[si+dir_clust] - mov [bx+file_left],eax - shl eax,SECTOR_SHIFT - mov [bx+file_bytesleft],eax - mov eax,[si+dir_lba] - mov [bx+file_sector],eax - mov edx,[si+dir_len] - -.look_for_slash: - mov ax,di -.scan: - mov cl,[di] - inc di - and cl,cl - jz .isfile - cmp cl,'/' - jne .scan - mov [di-1],byte 0 ; Terminate at directory name - mov cl,02h ; Search for directory - xchg cl,[ISOFlags] - - push di ; Save these... - push cx - - ; Create recursion stack frame... - push word .resume ; Where to "return" to - push es -.isfile: xchg ax,di - -.getsome: - ; Get a chunk of the directory - ; This relies on the fact that ISOLINUX doesn't change SI - mov si,trackbuf - TRACER 'g' - pushad - xchg bx,si - mov cx,[BufSafe] - call getfssec - popad - -.compare: - movzx eax,byte [si] ; Length of directory entry - cmp al,33 - jb .next_sector - TRACER 'c' - mov cl,[si+25] - xor cl,[ISOFlags] - test cl, byte 8Eh ; Unwanted file attributes! - jnz .not_file - pusha - movzx cx,byte [si+32] ; File identifier length - add si,byte 33 ; File identifier offset - TRACER 'i' - call iso_compare_names - popa - je .success -.not_file: - sub edx,eax ; Decrease bytes left - jbe .failure - add si,ax ; Advance pointer - -.check_overrun: - ; Did we finish the buffer? - cmp si,trackbuf+trackbufsize - jb .compare ; No, keep going - - jmp short .getsome ; Get some more directory - -.next_sector: - ; Advance to the beginning of next sector - lea ax,[si+SECTOR_SIZE-1] - and ax,~(SECTOR_SIZE-1) - sub ax,si - jmp short .not_file ; We still need to do length checks - -.failure: xor eax,eax ; ZF = 1 - mov [bx+file_sector],eax - pop es - ret - -.success: - mov eax,[si+2] ; Location of extent - mov [bx+file_sector],eax - mov eax,[si+10] ; Data length - mov [bx+file_bytesleft],eax - push eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [bx+file_left],eax - pop eax - jz .failure ; Empty file? - ; ZF = 0 - mov si,bx - pop es - ret - -.resume: ; We get here if we were only doing part of a lookup - ; This relies on the fact that .success returns bx == si - xchg edx,eax ; Directory length in edx - pop cx ; Old ISOFlags - pop di ; Next filename pointer - mov byte [di-1], '/' ; Restore slash - mov [ISOFlags],cl ; Restore the flags - jz .failure ; Did we fail? If so fail for real! - jmp .look_for_slash ; Otherwise, next level - -; -; allocate_file: Allocate a file structure -; -; If successful: -; ZF set -; BX = file pointer -; In unsuccessful: -; ZF clear -; -allocate_file: - TRACER 'a' - push cx - mov bx,Files - mov cx,MAX_OPEN -.check: cmp dword [bx], byte 0 - je .found - add bx,open_file_t_size ; ZF = 0 - loop .check - ; ZF = 0 if we fell out of the loop -.found: pop cx - ret - -; -; iso_compare_names: -; Compare the names DS:SI and DS:DI and report if they are -; equal from an ISO 9660 perspective. SI is the name from -; the filesystem; CX indicates its length, and ';' terminates. -; DI is expected to end with a null. -; -; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment -; - -iso_compare_names: - ; First, terminate and canonicalize input filename - push di - mov di,ISOFileName -.canon_loop: jcxz .canon_end - lodsb - dec cx - cmp al,';' - je .canon_end - and al,al - je .canon_end - stosb - cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun - jb .canon_loop -.canon_end: - cmp di,ISOFileName - jbe .canon_done - cmp byte [di-1],'.' ; Remove terminal dots - jne .canon_done - dec di - jmp short .canon_end -.canon_done: - mov [di],byte 0 ; Null-terminate string - pop di - mov si,ISOFileName -.compare: - lodsb - mov ah,[di] - inc di - and ax,ax - jz .success ; End of string for both - and al,al ; Is either one end of string? - jz .failure ; If so, failure - and ah,ah - jz .failure - or ax,2020h ; Convert to lower case - cmp al,ah - je .compare -.failure: and ax,ax ; ZF = 0 (at least one will be nonzero) -.success: ret - -; -; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace. -; DI is preserved. -; -; This verifies that a filename is < FILENAME_MAX characters, -; doesn't contain whitespace, zero-pads the output buffer, -; and removes trailing dots and redundant slashes, -; so "repe cmpsb" can do a compare, and the -; path-searching routine gets a bit of an easier job. -; -mangle_name: - push di - push bx - xor ax,ax - mov cx,FILENAME_MAX-1 - mov bx,di - -.mn_loop: - lodsb - cmp al,' ' ; If control or space, end - jna .mn_end - cmp al,ah ; Repeated slash? - je .mn_skip - xor ah,ah - cmp al,'/' - jne .mn_ok - mov ah,al -.mn_ok stosb -.mn_skip: loop .mn_loop -.mn_end: - cmp bx,di ; At the beginning of the buffer? - jbe .mn_zero - cmp byte [es:di-1],'.' ; Terminal dot? - je .mn_kill - cmp byte [es:di-1],'/' ; Terminal slash? - jne .mn_zero -.mn_kill: dec di ; If so, remove it - inc cx - jmp short .mn_end -.mn_zero: - inc cx ; At least one null byte - xor ax,ax ; Zero-fill name - rep stosb - pop bx - pop di - ret ; Done ; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled @@ -1680,56 +1340,6 @@ unmangle_name: call strcpy dec di ; Point to final null byte ret -; -; getfssec: Get multiple clusters from a file, given the file pointer. -; -; On entry: -; ES:BX -> Buffer -; SI -> File pointer -; CX -> Cluster count -; On exit: -; SI -> File pointer (or 0 on EOF) -; CF = 1 -> Hit EOF -; ECX -> Bytes actually read -; -getfssec: - TRACER 'F' - push ds - push cs - pop ds ; DS <- CS - - movzx ecx,cx - cmp ecx,[si+file_left] - jna .ok_size - mov ecx,[si+file_left] -.ok_size: - - pushad - mov eax,[si+file_sector] - mov bp,cx - TRACER 'l' - call getlinsec - popad - - ; ECX[31:16] == 0 here... - add [si+file_sector],ecx - sub [si+file_left],ecx - shl ecx,SECTOR_SHIFT ; Convert to bytes - cmp ecx,[si+file_bytesleft] - jb .not_all - mov ecx,[si+file_bytesleft] -.not_all: sub [si+file_bytesleft],ecx - jnz .ret ; CF = 0 in this case... - push eax - xor eax,eax - mov [si+file_sector],eax ; Unused - mov si,ax - pop eax - stc -.ret: - pop ds - TRACER 'f' - ret ; ----------------------------------------------------------------------------- ; Common modules