📄 isolinux.asm
字号:
mov dl,[DriveNo] lss sp,[InitStack] TRACER 'X' int 13h ; If this returns, we have problems.bad_image: mov si,err_disk_image call cwritestr jmp enter_command;; Look for the highest seen H/S geometry; We compute cylinders separately;.hs_check: mov bl,[si] ; Head # cmp bl,ah jna .done_track mov ah,bl ; New highest head #.done_track: mov bl,[si+1] and bl,3Fh ; Sector # cmp bl,al jna .done_sector mov al,bl.done_sector: ret;; Boot a specified local disk. AX specifies the BIOS disk number; or; 0xFFFF in case we should execute INT 18h ("next device.");local_boot: call vgaclearmode lss sp,[cs:Stack] ; Restore stack pointer xor dx,dx mov ds,dx mov es,dx mov fs,dx mov gs,dx mov si,localboot_msg call writestr cmp ax,-1 je .int18 ; Load boot sector from the specified BIOS device and jump to it. mov dl,al xor dh,dh push dx xor ax,ax ; Reset drive call xint13 mov ax,0201h ; Read one sector mov cx,0001h ; C/H/S = 0/0/1 (first sector) mov bx,trackbuf call xint13 pop dx cli ; Abandon hope, ye who enter here mov si,trackbuf mov di,07C00h mov cx,512 ; Probably overkill, but should be safe rep movsd lss sp,[cs:InitStack] jmp 0:07C00h ; Jump to new boot sector.int18: int 18h ; Hope this does the right thing... jmp kaboom ; If we returned, oh boy...;; Abort loading code;%include "abort.inc";; searchdir:;; Open a file;; On entry:; DS:DI = filename; If successful:; ZF clear; SI = file pointer; DX:AX or 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 retsearchdir: xor al,alsearchdir_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,CurDir 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 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 push eax add eax,SECTOR_SIZE-1 shr eax,SECTOR_SHIFT mov [bx+file_left],eax pop eax mov edx,eax shr edx,16 and bx,bx ; 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.;; 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 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 dot? je .mn_kill 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;; 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;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: mov bp,cx push cx push si mov eax,[si+file_sector] TRACER 'l' call getlinsec xor ecx,ecx pop si pop cx add [si+file_sector],ecx sub [si+file_left],ecx ja .not_eof ; CF = 0 xor ecx,ecx mov [si+file_sector],ecx ; Mark as unused xor si,si stc.not_eof: pop ds TRACER 'f' ret; -----------------------------------------------------------------------------; Common modules; -----------------------------------------------------------------------------%include "getc.inc" ; getc et al%include "conio.inc" ; Console I/O%include "parseconfig.inc" ; High-level config file handling%include "parsecmd.inc" ; Low-level config file handling%include "bcopy32.inc" ; 32-bit bcopy%include "loadhigh.inc" ; Load a file into high memory%include "font.inc" ; VGA font stuff%include "graphics.inc" ; VGA graphics%include "highmem.inc" ; High memory sizing%include "strcpy.inc" ; strcpy()%include "rawcon.inc" ; Console I/O w/o using the console functions; -----------------------------------------------------------------------------; Begin data section; ----------------------------------------------------------------------------- section .databoot_prompt db 'boot: ', 0wipe_char db BS, ' ', BS, 0err_notfound db 'Could not find kernel image: ',0err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0err_noram db 'It appears your computer has less than ' asciidec dosram_k db 'K of low ("DOS")' db CR, LF db 'RAM. Linux needs at least this amount to boot. If you get' db CR, LF db 'this message in error, hold down the Ctrl key while' db CR, LF db 'booting, and I will take your word for it.', CR, LF, 0err_badcfg db 'Unknown keyword in config file.', CR, LF, 0err_noparm db 'Missing parameter in config file.', CR, LF, 0err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db CR, LF, 0err_notdos db ': attempted DOS system call', CR, LF, 0err_comlarge db 'COMBOOT image too large.', CR, LF, 0err_bssimage db 'BSS images not supported.', CR, LF, 0err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0notfound_msg db 'not found', CR, LF, 0localboot_msg db 'Booting from local disk...', CR, LF, 0cmdline_msg db 'Command line: ', CR, LF, 0ready_msg db 'Ready.', CR, LF, 0trying_msg db 'Trying to load: ', 0crlfloading_msg db CR, LF ; Fall throughloading_msg db 'Loading ', 0dotdot_msg db '.'dot_msg db '.', 0fourbs_msg db BS, BS, BS, BS, 0aborted_msg db ' aborted.', CR, LF, 0crff_msg db CR, FF, 0default_str db 'default', 0default_len equ ($-default_str)boot_dir db '/boot' ; /boot/isolinuxisolinux_dir db '/isolinux', 0ConfigName equ $isolinux_cfg db 'isolinux.cfg', 0err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0%ifdef DEBUG_MESSAGESdbg_rootdir_msg db 'Root directory at LBA = ', 0dbg_isodir_msg db 'isolinux directory at LBA = ', 0dbg_config_msg db 'About to load config file...', CR, LF, 0dbg_configok_msg db 'Configuration file opened...', CR, LF, 0%endif;; Command line options we'd like to take a look at;; mem= and vga= are handled as normal 32-bit integer valuesinitrd_cmd db 'initrd='initrd_cmd_len equ 7;; Config file keyword table;%include "keywords.inc";; Extensions to search for (in *forward* order).; align 4, db 0exten_table: db '.cbt' ; COMBOOT (specific) db '.img' ; Disk image db '.bin' ; CD boot sector db '.com' ; COMBOOT (same as DOS) db '.c32' ; COM32exten_table_end: dd 0, 0 ; Need 8 null bytes here;; Floppy image table; align 4, db 0img_table_count equ 3img_table: dd 1200*1024 ; 1200K floppy db 1 ; Emulation type db 80-1 ; Max cylinder db 15 ; Max sector db 2-1 ; Max head dd 1440*1024 ; 1440K floppy db 2 ; Emulation type db 80-1 ; Max cylinder db 18 ; Max sector db 2-1 ; Max head dd 2880*1024 ; 2880K floppy db 3 ; Emulation type db 80-1 ; Max cylinder db 36 ; Max sector db 2-1 ; Max head;; Misc initialized (data) variables;;; Variables that are uninitialized in SYSLINUX but initialized here;; **** ISOLINUX:: We may have to make this flexible, based on what the; **** BIOS expects our "sector size" to be.; alignb 4, db 0BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbufBufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?BufSafeBytes dw trackbufsize ; = how many bytes?EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes%ifndef DEPEND%if ( trackbufsize % SECTOR_SIZE ) != 0%error trackbufsize must be a multiple of SECTOR_SIZE%endif%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -