📄 isolinux.asm
字号:
award_loop: push di ; save DI mov si,award_string ; scan for award_string mov cx,7 ; length of award_string = 7dw repz cmpsw ; compare pop di ; restore DI jcxz award_found ; jmp if found inc di ; not found, inc di jno award_loop ; ;award_failed: pop es ; No, not this way :-((award_fail2: ; ;%ifdef DEBUG_MESSAGES ; ; mov si,award_not_fail ; display failure ... call writemsg ;%endif ; mov eax,[award_oldint13] ; restore the original int or eax,eax ; 13 vector if there is one jz spec_query_failed ; and try other workarounds mov [13h*4],eax ; jmp spec_query_failed ; ;award_found: mov eax,[es:di+0eh] ; load possible int 13 addr pop es ; restore ES ; cmp eax,[award_oldint13] ; give up if this is the jz award_failed ; active int 13 vector, mov [13h*4],eax ; otherwise change 0:13h*4 ; ;%ifdef DEBUG_MESSAGES ; ; push eax ; display message and mov si,award_not_new ; new vector address call writemsg ; pop eax ; 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 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,SECTORSIZE_LG2-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:Stack] 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%endifspec_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 = ', 0nosecsize_msg: db 'Failed to get sector size, assuming 0800', CR, LF, 0diskerr_msg: db 'Disk error ', 0oncall_str: db ', AX = ',0ondrive_str: db ', drive ', 0nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 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;; El Torito spec packet; align 8, db 0spec_packet: db 13h ; Size of packetsp_media: db 0 ; Media typesp_drive: db 0 ; Drive numbersp_controller: db 0 ; Controller indexsp_lba: dd 0 ; LBA for emulated disk imagesp_devspec: dw 0 ; IDE/SCSI informationsp_buffer: dw 0 ; User-provided buffersp_loadseg: dw 0 ; Load segmentsp_sectors: dw 0 ; Sector countsp_chs: db 0,0,0 ; Simulated CHS geometrysp_dummy: db 0 ; Scratch, safe to overwrite;; Spec packet for disk image emulation; align 8, db 0dspec_packet: db 13h ; Size of packetdsp_media: db 0 ; Media typedsp_drive: db 0 ; Drive numberdsp_controller: db 0 ; Controller indexdsp_lba: dd 0 ; LBA for emulated disk imagedsp_devspec: dw 0 ; IDE/SCSI informationdsp_buffer: dw 0 ; User-provided bufferdsp_loadseg: dw 0 ; Load segmentdsp_sectors: dw 1 ; Sector countdsp_chs: db 0,0,0 ; Simulated CHS geometrydsp_dummy: db 0 ; Scratch, safe to overwrite;; EBIOS drive parameter packet; align 8, db 0drive_params: dw 30 ; Buffer sizedp_flags: dw 0 ; Information flagsdp_cyl: dd 0 ; Physical cylindersdp_head: dd 0 ; Physical headsdp_sec: dd 0 ; Physical sectors/trackdp_totalsec: dd 0,0 ; Total sectorsdp_secsize: dw 0 ; Bytes per sectordp_dpte: dd 0 ; Device Parameter Tabledp_dpi_key: dw 0 ; 0BEDDh if rest validdp_dpi_len: db 0 ; DPI len db 0 dw 0dp_bus: times 4 db 0 ; Host bus typedp_interface: times 8 db 0 ; Interface typedb_i_path: dd 0,0 ; Interface pathdb_d_path: dd 0,0 ; Device path db 0db_dpi_csum: db 0 ; Checksum for DPI info;; EBIOS disk address packet; align 8, db 0dapa: dw 16 ; Packet size.count: dw 0 ; Block count.off: dw 0 ; Offset of buffer.seg: dw 0 ; Segment of buffer.lba: dd 0 ; LBA (LSW) dd 0 ; LBA (MSW) alignb 4, db 0Stack dw _start, 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 "cpuinit.inc";; Clear Files structures; mov di,Files mov cx,(MAX_OPEN*open_file_t_size)/4 xor eax,eax rep stosd;; 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.; mov si,linuxauto_cmd ; Default command: "linux auto" mov di,default_cmd mov cx,linuxauto_len rep movsb mov di,KbdMap ; Default keymap 1:1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -