From f4d1f2e18fa3b255acfe1802f50e9beca6a60a3d Mon Sep 17 00:00:00 2001 From: hpa Date: Sun, 19 Dec 2004 10:25:07 +0000 Subject: [PATCH] A lot more work on extlinux. Should have most of the pieces now; just missing some initialization code, and, of course, debugging. --- Makefile | 15 +++- ext2_fs.inc | 27 +++++++ extlinux.asm | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 258 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 6a35539..1e3a191 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ SOURCES = $(CSRC) *.h $(NASMSRC) *.inc # mingw suite installed BTARGET = kwdhash.gen version.gen ldlinux.bss ldlinux.sys ldlinux.bin \ pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin \ + extlinux.bin extlinux.bss extlinux.sys \ bootsect_bin.c ldlinux_bin.c # libsyslinux.a $(LIB_SO) BOBJECTS = $(BTARGET) dos/syslinux.com win32/syslinux.exe memdisk/memdisk @@ -132,6 +133,10 @@ isolinux.bin: isolinux.asm kwdhash.gen version.gen checksumiso.pl -l isolinux.lst -o isolinux.bin isolinux.asm $(PERL) checksumiso.pl isolinux.bin +extlinux.bin: extlinux.asm kwdhash.gen version.gen + $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ + -l extlinux.lst -o extlinux.bin extlinux.asm + pxelinux.0: pxelinux.bin cp pxelinux.bin pxelinux.0 @@ -143,10 +148,16 @@ isolinux-debug.bin: isolinux.asm kwdhash.gen version.gen checksumiso.pl $(PERL) checksumiso.pl $@ ldlinux.bss: ldlinux.bin - dd if=ldlinux.bin of=ldlinux.bss bs=512 count=1 + dd if=$< of=$@ bs=512 count=1 ldlinux.sys: ldlinux.bin - dd if=ldlinux.bin of=ldlinux.sys bs=512 skip=1 + dd if=$< of=$@ bs=512 skip=1 + +extlinux.bss: extlinux.bin + dd if=$< of=$@ bs=512 count=1 + +extlinux.sys: extlinux.bin + dd if=$< of=$@ bs=512 skip=1 mbr.bin: mbr.asm $(NASM) -f bin -l mbr.lst -o mbr.bin mbr.asm diff --git a/ext2_fs.inc b/ext2_fs.inc index 6d85596..4cedd12 100644 --- a/ext2_fs.inc +++ b/ext2_fs.inc @@ -21,6 +21,23 @@ %define EXT2_GOOD_OLD_REV 0 ; The good old (original) format %define EXT2_DYNAMIC_REV 1 ; V2 format w/ dynamic inode sizes +%define EXT2_GOOD_OLD_INODE_SIZE 128 + +; Special inode numbers +%define EXT2_BAD_INO 1 ; Bad blocks inode +%define EXT2_ROOT_INO 2 ; Root inode +%define EXT2_BOOT_LOADER_INO 5 ; Boot loader inode +%define EXT2_UNDEL_DIR_INO 6 ; Undelete directory inode +%define EXT3_RESIZE_INO 7 ; Reserved group descriptors inode +%define EXT3_JOURNAL_INO 8 ; Journal inode + +; We're readonly, so we only care about incompat features. +%define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +%define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +%define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +%define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +%define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +%define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff %define EXT2_NDIR_BLOCKS 12 %define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS @@ -128,3 +145,13 @@ bg_reserved resd 3 %define ext2_group_desc_lg2size 5 +; +; Structure definition for ext2 directory entry +; + struc ext2_dir_entry +d_inode resd 1 ; Inode number +d_rec_len resw 1 ; Directory entry length +d_name_len resb 1 ; Name length +d_file_type resb 1 ; File type +d_name equ $ + endstruc diff --git a/extlinux.asm b/extlinux.asm index e12edb7..d9feb97 100644 --- a/extlinux.asm +++ b/extlinux.asm @@ -85,8 +85,8 @@ comboot_seg equ real_mode_seg ; COMBOOT image loading zone ; File structure. This holds the information for each currently open file. ; struc open_file_t +file_left resd 1 ; Number of sectors left (0 = free) file_sector resd 1 ; Next linear sector to read -file_left resd 1 ; Number of sectors left file_in_sec resd 1 ; Sector where inode lives file_in_off resw 1 resw 1 @@ -126,8 +126,6 @@ TotalSectors resd 1 ; Total number of sectors EndSector resd 1 ; Location of filesystem end ClustSize resd 1 ; Bytes/cluster ClustMask resd 1 ; Sectors/cluster - 1 -CachePtrs resw 65536/SECTOR_SIZE ; Cached sector pointers -NextCacheSlot resw 1 ; Next cache slot to occupy CopySuper resb 1 ; Distinguish .bs versus .bss DriveNumber resb 1 ; BIOS drive number ClustShift resb 1 ; Shift count for sectors/cluster @@ -908,6 +906,92 @@ allocate_file: ; ZF = 0 if we fell out of the loop .found: pop cx ret +; +; open_inode: +; Open a file indicated by an inode number in EAX +; +; NOTE: This file considers finding a zero-length file an +; error. This is so we don't have to deal with that special +; case elsewhere in the program (most loops have the test +; at the end). +; +; If successful: +; ZF clear +; SI = file pointer +; DX:AX = EAX = file length in bytes +; If unsuccessful +; ZF set +; +open_inode.allocate_failure: + xor eax,eax + ret + +open_inode: + call allocate_file + jnz .allocate_failure + + push gs + ; First, get the appropriate inode group and index + dec eax ; There is no inode 0 + xor edx,edx + mov [bx+file_sector],edx + div dword [SuperBlock+s_inodes_per_group] + ; EAX = inode group; EDX = inode within group + push edx + + ; Now, we need the block group descriptor. + ; To get that, we first need the relevant descriptor block. + + shl eax, ext2_group_desc_lg2size ; Get byte offset in desc table + xor edx,edx + div dword [BlockSize] + ; eax = block #, edx = offset in block + add eax,dword [SuperBlock+s_first_data_block] + inc eax ; s_first_data_block+1 + mov cl,[ClustShift] + shl eax,cl + call getcachesec ; Get the group descriptor + add si,dx + mov esi,[gs:si+bg_inode_table] ; Get inode table block # + pop eax ; Get inode within group + movzx edx, word [SuperBlock+s_inode_size] + mul edx + ; edx:eax = byte offset in inode table + div dword [BlockSize] + ; eax = block # versus inode table, edx = offset in block + add eax,esi + shl eax,cl ; Turn into sector + push dx + shr edx,SECTOR_SHIFT + add eax,edx + mov [bx+file_in_sec],eax + pop dx + and dx,SECTOR_SIZE-1 + mov [bx+file_in_off],dx + + call getcachesec + add si,dx + mov eax,[gs:si+i_size] + push eax + add eax,SECTOR_SIZE-1 + shr eax,SECTOR_SHIFT + mov [bx+file_left],eax + pop eax + mov si,bx + mov edx,eax + shr edx,16 ; 16-bitism, sigh + and eax,eax ; ZF clear unless zero-length file + pop gs + ret + +; +; close: +; Deallocates a file structure (pointer in SI) +; Assumes CS == DS. +; +close: + mov dword [si],0 ; First dword == file_left + ret ; ; searchdir: @@ -920,17 +1004,143 @@ allocate_file: ; ; If successful: ; ZF clear -; SI = file pointer -; DX:AX = file length in bytes +; SI = file pointer +; DX:AX = EAX = file length in bytes ; If unsuccessful ; ZF set ; - +; Assumes CS == DS == ES; *** IS THIS CORRECT ***? +; searchdir: - call allocate_file - jnz .alloc_failure + mov eax,[CurrentDir] +.leadingslash: + cmp byte [di],'/' ; Absolute filename? + jne .searchloop + mov eax,EXT2_ROOT_INO + inc di ; Skip slash + +.searchloop: + ; At this point, EAX contains the directory inode, + ; and DS:DI contains a pathname tail. + call open_inode + +.readdir: + mov bx,trackbuf + push bx + mov cx,[SecPerBlock] + call getfssec + pop bx + pushf ; Save EOF flag +.getent: + cmp dword [bx+d_inode],0 + je .endblock + + push di + push si + mov cx,[bx+d_name_len] + lea si,[bx+d_name] + repe cmpsb + pop si + je .maybe +.nope: + pop di + + add bx,[bx+d_rec_len] + jmp .getent + +.endblock: + popf + jnc .readdir ; There is more +.failure: + xor eax,eax + ret +.maybe: + mov eax,[si+d_inode] + + cmp byte [di],0 + je .finish ; It's a real file; done + cmp byte [di],'/' + jne .nope ; False alarm + + ; It's a match, but it's a directory. + ; Repeat operation. + call close + pop si ; Adjust stack (di) + pop si ; Adjust stack (flags) + inc di ; Skip slash + jmp .searchloop + +.finish: ; We found it; now we need to open the file + call close ; Close directory + pop si ; Adjust stack (di) + pop si ; Adjust stack (flags) + call open_inode ret + +; +; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed +; to by ES:DI; ends on encountering any whitespace. +; +; This verifies that a filename is < FILENAME_MAX characters, +; doesn't contain whitespace, zero-pads the output buffer, +; and removes redundant slashes, +; so "repe cmpsb" can do a compare, and the +; path-searching routine gets a bit of an easier job. +; +; FIX: we may want to support \-escapes here (and this would +; be the place.) +; +mangle_name: + 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 [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 + ret ; Done + +; +; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled +; filename to the conventional representation. This is needed +; for the BOOT_IMAGE= parameter for the kernel. +; NOTE: A 13-byte buffer is mandatory, even if the string is +; known to be shorter. +; +; DS:SI -> input mangled file name +; ES:DI -> output buffer +; +; On return, DI points to the first byte after the output name, +; which is set to a null byte. +; +unmangle_name: call strcpy + dec di ; Point to final null byte + ret + ; ; writechr: Write a single character in AL to the console without ; mangling any registers; handle video pages correctly. @@ -960,30 +1170,6 @@ kaboom2: int 19h ; And try once more to boot... .norge: jmp short .norge ; If int 19h returned; this is the end -; -; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace -; - -mangle_name: - ret - -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; NOTE: A 13-byte buffer is mandatory, even if the string is -; known to be shorter. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: - ret - ; ; linsector: Convert a linear sector index in a file to a linear sector number @@ -1255,7 +1441,6 @@ exten_table_end: %ifdef debug ; This code for debugging only debug_magic dw 0D00Dh ; Debug code sentinel %endif -ScrollAttribute db 07h ; White on black (for text mode) alignb 4, db 0 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf -- 2.7.4