📄 isolinux.asm
字号:
call writehex8 ; mov si,award_not_crlf ; call writestr ;%endif ; mov ax,4B01h ; try to read the spec packet mov dl,[DriveNo] ; now ... it should not fail mov si,spec_packet ; any longer int 13h ; jc award_fail2 ; ;%ifdef DEBUG_MESSAGES ; ; mov si,award_not_succ ; display our SUCCESS call writemsg ;%endif ; jmp found_drive ; and leave error recovery code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; INT 13h, AX=4B01h, DL=<passed in value> failed. ; Try to scan the entire 80h-FFh from the end.spec_query_failed: ; some code moved to BrokenAwardHack mov dl,0FFh.test_loop: pusha mov ax,4B01h mov si,spec_packet mov byte [si],13 ; Size of buffer int 13h popa jc .still_broken mov si,maybe_msg call writemsg mov al,dl call writehex2 call crlf cmp byte [sp_drive],dl jne .maybe_broken ; Okay, good enough... mov si,alright_msg call writemsg mov [DriveNo],dl.found_drive: jmp found_drive ; Award BIOS 4.51 apparently passes garbage in sp_drive, ; but if this was the drive number originally passed in ; DL then consider it "good enough".maybe_broken: cmp byte [DriveNo],dl je .found_drive.still_broken: dec dx cmp dl, 80h jnb .test_loop ; No spec packet anywhere. Some particularly pathetic ; BIOSes apparently don't even implement function ; 4B01h, so we can't query a spec packet no matter ; what. If we got a drive number in DL, then try to ; use it, and if it works, then well... mov dl,[DriveNo] cmp dl,81h ; Should be 81-FF at least jb fatal_error ; If not, it's hopeless ; Write a warning to indicate we're on *very* thin ice now mov si,nospec_msg call writemsg mov al,dl call writehex2 call crlf mov si,trysbm_msg call writemsg jmp .found_drive ; Pray that this works...fatal_error: mov si,nothing_msg call writemsg.norge: jmp short .norge ; Information message (DS:SI) output ; Prefix with "isolinux: " ;writemsg: push ax push si mov si,isolinux_str call writestr pop si call writestr pop ax ret;; Write a character to the screen. There is a more "sophisticated"; version of this in the subsequent code, so we patch the pointer; when appropriate.;writechr: jmp near writechr_simple ; 3-byte jumpwritechr_simple: pushfd pushad mov ah,0Eh xor bx,bx int 10h popad popfd ret;; Get one sector. Convenience entry point.;getonesec: mov bp,1 ; Fall through to getlinsec;; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.;; Note that we can't always do this as a single request, because at least; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick; to 32 sectors (64K) per request.;; Input:; EAX - Linear sector number; ES:BX - Target buffer; BP - Sector count;getlinsec: mov si,dapa ; Load up the DAPA mov [si+4],bx mov bx,es mov [si+6],bx mov [si+8],eax.loop: push bp ; Sectors left cmp bp,[MaxTransfer] jbe .bp_ok mov bp,[MaxTransfer].bp_ok: mov [si+2],bp push si mov dl,[DriveNo] mov ah,42h ; Extended Read call xint13 pop si pop bp movzx eax,word [si+2] ; Sectors we read add [si+8],eax ; Advance sector pointer sub bp,ax ; Sectors left shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment add [si+6],ax ; Advance buffer pointer and bp,bp jnz .loop mov eax,[si+8] ; Next sector ret ; INT 13h with retryxint13: mov byte [RetryCount],retry_count.try: pushad int 13h jc .error add sp,byte 8*4 ; Clean up stack ret.error: mov [DiskError],ah ; Save error code popad mov [DiskSys],ax ; Save system call number dec byte [RetryCount] jz .real_error push ax mov al,[RetryCount] mov ah,[dapa+2] ; Sector transfer count cmp al,2 ; Only 2 attempts left ja .nodanger mov ah,1 ; Drop transfer size to 1 jmp short .setsize.nodanger: cmp al,retry_count-2 ja .again ; First time, just try again shr ah,1 ; Otherwise, try to reduce adc ah,0 ; the max transfer size, but not to 0.setsize: mov [MaxTransfer],ah mov [dapa+2],ah.again: pop ax jmp .try.real_error: mov si,diskerr_msg call writemsg mov al,[DiskError] call writehex2 mov si,oncall_str call writestr mov ax,[DiskSys] call writehex4 mov si,ondrive_str call writestr mov al,dl call writehex2 call crlf ; Fall through to kaboom;; kaboom: write a message and bail out. Wait for a user keypress,; then do a hard reboot.;kaboom: lss sp,[cs:StackPtr] mov ax,cs mov ds,ax mov es,ax mov fs,ax mov gs,ax sti mov si,err_bootfailed call cwritestr call getchar cli mov word [BIOS_magic],0 ; Cold reboot jmp 0F000h:0FFF0h ; Reset vector address; -----------------------------------------------------------------------------; Common modules needed in the first sector; -----------------------------------------------------------------------------%include "writestr.inc" ; String outputwritestr equ cwritestr%include "writehex.inc" ; Hexadecimal output; -----------------------------------------------------------------------------; Data that needs to be in the first sector; -----------------------------------------------------------------------------syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin' db CR, LF, 0isolinux_str db 'isolinux: ', 0%ifdef DEBUG_MESSAGESstartup_msg: db 'Starting up, DL = ', 0spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0secsize_msg: db 'Sector size appears to be ', 0offset_msg: db 'Loading main image from LBA = ', 0size_msg: db 'Sectors to load = ', 0loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0verify_msg: db 'Image checksum verified.', CR, LF, 0allread_msg db 'Main image read, jumping to main code...', CR, LF, 0%endifnoinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0maybe_msg: db 'Found something at drive = ', 0alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LFtrysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0diskerr_msg: db 'Disk error ', 0oncall_str: db ', AX = ',0ondrive_str: db ', drive ', 0checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'bailmsg equ err_bootfailedcrlf_msg db CR, LFnull_msg db 0 alignb 4, db 0StackPtr dw StackBuf, 0 ; SS:SP for stack resetMaxTransfer dw 32 ; Max sectors per transferrl_checkpt equ $ ; Must be <= 800hrl_checkpt_off equ ($-$$);%ifndef DEPEND;%if rl_checkpt_off > 0x800;%error "Sector 0 overflow";%endif;%endif; ----------------------------------------------------------------------------; End of code and data that have to be in the first sector; ----------------------------------------------------------------------------all_read:;; Initialize screen (if we're using one); ; Now set up screen parameters call adjust_screen ; Wipe the F-key area mov al,NULLFILE mov di,FKeyName mov cx,10*(1 << FILENAME_MAX_LG2) rep stosb ; Patch the writechr routine to point to the full code mov word [writechr+1], writechr_full-(writechr+3); Tell the user we got this far...%ifndef DEBUG_MESSAGES ; Gets messy with debugging on mov si,copyright_str call writestr%endif; Test tracers TRACER 'T' TRACER '>';; Common initialization code;%include "init.inc"%include "cpuinit.inc";; Now we're all set to start with our *real* business. First load the; configuration file (if any) and parse it.;; In previous versions I avoided using 32-bit registers because of a; rumour some BIOSes clobbered the upper half of 32-bit registers at; random. I figure, though, that if there are any of those still left; they probably won't be trying to install Linux on them...;; The code is still ripe with 16-bitisms, though. Not worth the hassle; to take'm out. In fact, we may want to put them back if we're going; to boot ELKS at some point.;;; Now, we need to sniff out the actual filesystem data structures.; mkisofs gave us a pointer to the primary volume descriptor; (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 [CurDir+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 [CurDir+dir_len],eax add eax,SECTOR_SIZE-1 shr eax,SECTOR_SHIFT mov [RootDir+dir_clust],eax mov [CurDir+dir_clust],eax ; Look for an isolinux directory, and if found, ; make it the current directory instead of the root ; directory. mov di,boot_dir ; Search for /boot/isolinux mov al,02h call searchdir_iso jnz .found_dir mov di,isolinux_dir mov al,02h ; Search for /isolinux call searchdir_iso jz .no_isolinux_dir.found_dir: mov [CurDir+dir_len],eax mov eax,[si+file_left] mov [CurDir+dir_clust],eax xor eax,eax ; Free this file pointer entry xchg eax,[si+file_sector] mov [CurDir+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:;; Locate the configuration file;load_config:%ifdef DEBUG_MESSAGES mov si,dbg_config_msg call writemsg%endif mov di,isolinux_cfg call open jz no_config_file ; Not found or empty%ifdef DEBUG_MESSAGES mov si,dbg_configok_msg call writemsg%endif;; Now we have the config file open. Parse the config file and; run the user interface.;%include "ui.inc";; Linux kernel loading code is common.;%include "runkernel.inc";; COMBOOT-loading code;%include "comboot.inc"%include "com32.inc"%include "cmdline.inc";; Boot sector loading code;%include "bootsect.inc";; Enable disk emulation. The kind of disk we emulate is dependent on the size of; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.;is_disk_image: TRACER CR TRACER LF TRACER 'D' TRACER ':' shl edx,16 mov dx,ax ; Set EDX <- file size mov di,img_table mov cx,img_table_count mov eax,[si+file_sector] ; Starting LBA of file mov [dsp_lba],eax ; Location of file mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk.search_table: TRACER 't' mov eax,[di+4] cmp edx,[di] je .type_found add di,8 loop .search_table ; Hard disk image. Need to examine the partition table ; in order to deduce the C/H/S geometry. Sigh..hard_disk_image: TRACER 'h' cmp edx,512 jb .bad_image mov bx,trackbuf mov cx,1 ; Load 1 sector call getfssec cmp word [trackbuf+510],0aa55h ; Boot signature jne .bad_image ; Image not bootable mov cx,4 ; 4 partition entries mov di,trackbuf+446 ; Start of partition table xor ax,ax ; Highest sector(al) head(ah).part_scan: cmp byte [di+4], 0 jz .part_loop lea si,[di+1] call .hs_check add si,byte 4 call .hs_check.part_loop: add di,byte 16 loop .part_scan push eax ; H/S push edx ; File size mov bl,ah xor bh,bh inc bx ; # of heads in BX xor ah,ah ; # of sectors in AX cwde ; EAX[31:16] <- 0 mul bx shl eax,9 ; Convert to bytes ; Now eax contains the number of bytes per cylinder pop ebx ; File size xor edx,edx div ebx and edx,edx jz .no_remainder inc eax ; Fractional cylinder... ; Now (e)ax contains the number of cylinders.no_remainder: cmp eax,1024 jna .ok_cyl mov ax,1024 ; Max possible #.ok_cyl: dec ax ; Convert to max cylinder no pop ebx ; S(bl) H(bh) shl ah,6 or bl,ah xchg ax,bx shl eax,16 mov ah,bl mov al,4 ; Hard disk boot mov byte [dsp_drive], 80h ; Drive 80h = hard disk.type_found: TRACER 'T' mov bl,[sp_media] and bl,0F0h ; Copy controller info bits or al,bl mov [dsp_media],al ; Emulation type shr eax,8 mov [dsp_chs],eax ; C/H/S geometry mov ax,[sp_devspec] ; Copy device spec mov [dsp_devspec],ax mov al,[sp_controller] ; Copy controller index mov [dsp_controller],al TRACER 'V' call vgaclearmode ; Reset video mov ax,4C00h ; Enable emulation and boot mov si,dspec_packet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -