diff options
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/core/isolinux.asm')
-rw-r--r-- | contrib/syslinux/syslinux-4.03/core/isolinux.asm | 1384 |
1 files changed, 0 insertions, 1384 deletions
diff --git a/contrib/syslinux/syslinux-4.03/core/isolinux.asm b/contrib/syslinux/syslinux-4.03/core/isolinux.asm deleted file mode 100644 index ca8ee3a..0000000 --- a/contrib/syslinux/syslinux-4.03/core/isolinux.asm +++ /dev/null @@ -1,1384 +0,0 @@ -; -*- fundamental -*- (asm-mode sucks) -; **************************************************************************** -; -; isolinux.asm -; -; A program to boot Linux kernels off a CD-ROM using the El Torito -; boot standard in "no emulation" mode, making the entire filesystem -; available. It is based on the SYSLINUX boot loader for MS-DOS -; floppies. -; -; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved -; Copyright 2009 Intel Corporation; author: H. Peter Anvin -; -; This program is free software; you can redistribute it and/or modify -; it under the terms of the GNU General Public License as published by -; the Free Software Foundation, Inc., 53 Temple Place Ste 330, -; Boston MA 02111-1307, USA; either version 2 of the License, or -; (at your option) any later version; incorporated herein by reference. -; -; **************************************************************************** - -%define IS_ISOLINUX 1 -%include "head.inc" - -; -; Some semi-configurable constants... change on your own risk. -; -my_id equ isolinux_id -NULLFILE equ 0 ; Zero byte == null file name -NULLOFFSET equ 0 ; Position in which to look -retry_count equ 6 ; How patient are we with the BIOS? -%assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement) -SECTOR_SIZE equ (1 << SECTOR_SHIFT) - -ROOT_DIR_WORD equ 0x002F - -; -; The following structure is used for "virtual kernels"; i.e. LILO-style -; option labels. The options we permit here are `kernel' and `append -; Since there is no room in the bottom 64K for all of these, we -; stick them in high memory and copy them down before we need them. -; - struc vkernel -vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!** -vk_rname: resb FILENAME_MAX ; Real name -vk_appendlen: resw 1 -vk_type: resb 1 ; Type of file - alignb 4 -vk_append: resb max_cmd_len+1 ; Command line - alignb 4 -vk_end: equ $ ; Should be <= vk_size - endstruc - -; -; File structure. This holds the information for each currently open file. -; - struc open_file_t -file_sector resd 1 ; Sector pointer (0 = structure free) -file_bytesleft resd 1 ; Number of bytes left -file_left resd 1 ; Number of sectors left - resd 1 ; Unused - endstruc - -%ifndef DEPEND -%if (open_file_t_size & (open_file_t_size-1)) -%error "open_file_t is not a power of 2" -%endif -%endif - -; --------------------------------------------------------------------------- -; BEGIN CODE -; --------------------------------------------------------------------------- - -; -; 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 - - ; Some of these are touched before the whole image - ; is loaded. DO NOT move this to .bss16/.uibss. - section .earlybss - alignb 4 -FirstSecSum resd 1 ; Checksum of bytes 64-2048 -ImageDwords resd 1 ; isolinux.bin size, dwords -InitStack resd 1 ; Initial stack pointer (SS:SP) -DiskSys resw 1 ; Last INT 13h call -ImageSectors resw 1 ; isolinux.bin size, sectors -; These following two are accessed as a single dword... -GetlinsecPtr resw 1 ; The sector-read pointer -BIOSName resw 1 ; Display string for BIOS type -%define HAVE_BIOSNAME 1 -BIOSType resw 1 -DiskError resb 1 ; Error code for disk I/O -DriveNumber resb 1 ; CD-ROM BIOS drive number -ISOFlags resb 1 ; Flags for ISO directory search -RetryCount resb 1 ; Used for disk access retries - - alignb 8 -Hidden resq 1 ; Used in hybrid mode -bsSecPerTrack resw 1 ; Used in hybrid mode -bsHeads resw 1 ; Used in hybrid mode - - -; -; El Torito spec packet -; - - alignb 8 -_spec_start equ $ -spec_packet: resb 1 ; Size of packet -sp_media: resb 1 ; Media type -sp_drive: resb 1 ; Drive number -sp_controller: resb 1 ; Controller index -sp_lba: resd 1 ; LBA for emulated disk image -sp_devspec: resw 1 ; IDE/SCSI information -sp_buffer: resw 1 ; User-provided buffer -sp_loadseg: resw 1 ; Load segment -sp_sectors: resw 1 ; Sector count -sp_chs: resb 3 ; Simulated CHS geometry -sp_dummy: resb 1 ; Scratch, safe to overwrite - -; -; EBIOS drive parameter packet -; - alignb 8 -drive_params: resw 1 ; Buffer size -dp_flags: resw 1 ; Information flags -dp_cyl: resd 1 ; Physical cylinders -dp_head: resd 1 ; Physical heads -dp_sec: resd 1 ; Physical sectors/track -dp_totalsec: resd 2 ; Total sectors -dp_secsize: resw 1 ; Bytes per sector -dp_dpte: resd 1 ; Device Parameter Table -dp_dpi_key: resw 1 ; 0BEDDh if rest valid -dp_dpi_len: resb 1 ; DPI len - resb 1 - resw 1 -dp_bus: resb 4 ; Host bus type -dp_interface: resb 8 ; Interface type -db_i_path: resd 2 ; Interface path -db_d_path: resd 2 ; Device path - resb 1 -db_dpi_csum: resb 1 ; Checksum for DPI info - -; -; EBIOS disk address packet -; - alignb 8 -dapa: resw 1 ; Packet size -.count: resw 1 ; Block count -.off: resw 1 ; Offset of buffer -.seg: resw 1 ; Segment of buffer -.lba: resd 2 ; LBA (LSW, MSW) - -; -; Spec packet for disk image emulation -; - alignb 8 -dspec_packet: resb 1 ; Size of packet -dsp_media: resb 1 ; Media type -dsp_drive: resb 1 ; Drive number -dsp_controller: resb 1 ; Controller index -dsp_lba: resd 1 ; LBA for emulated disk image -dsp_devspec: resw 1 ; IDE/SCSI information -dsp_buffer: resw 1 ; User-provided buffer -dsp_loadseg: resw 1 ; Load segment -dsp_sectors: resw 1 ; Sector count -dsp_chs: resb 3 ; Simulated CHS geometry -dsp_dummy: resb 1 ; Scratch, safe to overwrite - - alignb 4 -_spec_end equ $ -_spec_len equ _spec_end - _spec_start - - section .init -;; -;; Primary entry point. Because BIOSes are buggy, we only load the first -;; CD-ROM sector (2K) of the file, so the number one priority is actually -;; loading the rest. -;; -StackBuf equ STACK_TOP-44 ; 44 bytes needed for - ; the bootsector chainloading - ; code! -OrigESDI equ StackBuf-4 ; The high dword on the stack -StackHome equ OrigESDI - -bootsec equ $ - -_start: ; Far jump makes sure we canonicalize the address - cli - jmp 0:_start1 - times 8-($-$$) nop ; Pad to file offset 8 - - ; This table hopefully gets filled in by mkisofs using the - ; -boot-info-table option. If not, the values in this - ; table are default values that we can use to get us what - ; we need, at least under a certain set of assumptions. - global iso_boot_info -iso_boot_info: -bi_pvd: dd 16 ; LBA of primary volume descriptor -bi_file: dd 0 ; LBA of boot file -bi_length: dd 0xdeadbeef ; Length of boot file -bi_csum: dd 0xdeadbeef ; Checksum of boot file -bi_reserved: times 10 dd 0xdeadbeef ; Reserved -bi_end: - - ; Custom entry point for the hybrid-mode disk. - ; The following values will have been pushed onto the - ; entry stack: - ; - partition offset (qword) - ; - ES - ; - DI - ; - DX (including drive number) - ; - CBIOS Heads - ; - CBIOS Sectors - ; - EBIOS flag - ; (top of stack) - ; - ; If we had an old isohybrid, the partition offset will - ; be missing; we can check for that with sp >= 0x7c00. - ; Serious hack alert. -%ifndef DEBUG_MESSAGES -_hybrid_signature: - dd 0x7078c0fb ; An arbitrary number... - -_start_hybrid: - pop cx ; EBIOS flag - pop word [cs:bsSecPerTrack] - pop word [cs:bsHeads] - pop dx - pop di - pop es - xor eax,eax - xor ebx,ebx - cmp sp,7C00h - jae .nooffset - pop eax - pop ebx -.nooffset: - mov si,bios_cbios - jcxz _start_common - mov si,bios_ebios - jmp _start_common -%endif - -_start1: - mov si,bios_cdrom - xor eax,eax - xor ebx,ebx -_start_common: - mov [cs:InitStack],sp ; Save initial stack pointer - mov [cs:InitStack+2],ss - xor cx,cx - mov ss,cx - mov sp,StackBuf ; Set up stack - push es ; Save initial ES:DI -> $PnP pointer - push di - mov ds,cx - mov es,cx - mov fs,cx - mov gs,cx - sti - cld - - mov [Hidden],eax - mov [Hidden+4],ebx - - mov [BIOSType],si - mov eax,[si] - mov [GetlinsecPtr],eax - - ; Show signs of life - mov si,syslinux_banner - call writestr_early -%ifdef DEBUG_MESSAGES - mov si,copyright_str -%else - mov si,[BIOSName] -%endif - call writestr_early - - ; - ; Before modifying any memory, get the checksum of bytes - ; 64-2048 - ; -initial_csum: xor edi,edi - mov si,bi_end - mov cx,(SECTOR_SIZE-64) >> 2 -.loop: lodsd - add edi,eax - loop .loop - mov [FirstSecSum],edi - - mov [DriveNumber],dl -%ifdef DEBUG_MESSAGES - mov si,startup_msg - call writemsg - mov al,dl - call writehex2 - call crlf -%endif - ; - ; Initialize spec packet buffers - ; - mov di,_spec_start - mov cx,_spec_len >> 2 - xor eax,eax - rep stosd - - ; Initialize length field of the various packets - mov byte [spec_packet],13h - mov byte [drive_params],30 - mov byte [dapa],16 - mov byte [dspec_packet],13h - - ; Other nonzero fields - inc word [dsp_sectors] - - ; Are we just pretending to be a CD-ROM? - cmp word [BIOSType],bios_cdrom - jne found_drive ; If so, no spec packet... - - ; Now figure out what we're actually doing - ; Note: use passed-in DL value rather than 7Fh because - ; at least some BIOSes will get the wrong value otherwise - mov ax,4B01h ; Get disk emulation status - mov dl,[DriveNumber] - mov si,spec_packet - call int13 - jc award_hack ; changed for BrokenAwardHack - mov dl,[DriveNumber] - cmp [sp_drive],dl ; Should contain the drive number - jne spec_query_failed - -%ifdef DEBUG_MESSAGES - mov si,spec_ok_msg - call writemsg - mov al,byte [sp_drive] - call writehex2 - call crlf -%endif - -found_drive: - ; Alright, we have found the drive. Now, try to find the - ; boot file itself. If we have a boot info table, life is - ; good; if not, we have to make some assumptions, and try - ; to figure things out ourselves. In particular, the - ; assumptions we have to make are: - ; - single session only - ; - only one boot entry (no menu or other alternatives) - - cmp dword [bi_file],0 ; Address of code to load - jne found_file ; Boot info table present :) - -%ifdef DEBUG_MESSAGES - mov si,noinfotable_msg - call writemsg -%endif - - ; No such luck. See if the spec packet contained one. - mov eax,[sp_lba] - and eax,eax - jz set_file ; Good enough - -%ifdef DEBUG_MESSAGES - mov si,noinfoinspec_msg - call writemsg -%endif - - ; No such luck. Get the Boot Record Volume, assuming single - ; session disk, and that we're the first entry in the chain. - mov eax,17 ; Assumed address of BRV - mov bx,trackbuf - call getonesec - - mov eax,[trackbuf+47h] ; Get boot catalog address - mov bx,trackbuf - call getonesec ; Get boot catalog - - mov eax,[trackbuf+28h] ; First boot entry - ; And hope and pray this is us... - - ; Some BIOSes apparently have limitations on the size - ; that may be loaded (despite the El Torito spec being very - ; clear on the fact that it must all be loaded.) Therefore, - ; we load it ourselves, and *bleep* the BIOS. - -set_file: - mov [bi_file],eax - -found_file: - ; Set up boot file sizes - mov eax,[bi_length] - sub eax,SECTOR_SIZE-3 ; ... minus sector loaded - shr eax,2 ; bytes->dwords - mov [ImageDwords],eax ; boot file dwords - add eax,((SECTOR_SIZE-1) >> 2) - shr eax,SECTOR_SHIFT-2 ; dwords->sectors - mov [ImageSectors],ax ; boot file sectors - - mov eax,[bi_file] ; Address of code to load - inc eax ; Don't reload bootstrap code -%ifdef DEBUG_MESSAGES - mov si,offset_msg - call writemsg - call writehex8 - call crlf -%endif - - ; Load the rest of the file. However, just in case there - ; are still BIOSes with 64K wraparound problems, we have to - ; take some extra precautions. Since the normal load - ; address (TEXT_START) is *not* 2K-sector-aligned, we round - ; the target address upward to a sector boundary, - ; and then move the entire thing down as a unit. -MaxLMA equ 384*1024 ; Reasonable limit (384K) - - mov bx,((TEXT_START+2*SECTOR_SIZE-1) & ~(SECTOR_SIZE-1)) >> 4 - mov bp,[ImageSectors] - push bx ; Load segment address - -.more: - push bx ; Segment address - push bp ; Sector count - mov es,bx - mov cx,0xfff - and bx,cx - inc cx - sub cx,bx - shr cx,SECTOR_SHIFT - 4 - jnz .notaligned - mov cx,0x10000 >> SECTOR_SHIFT ; Full 64K segment possible -.notaligned: - cmp bp,cx - jbe .ok - mov bp,cx -.ok: - xor bx,bx - push bp - call getlinsec - pop cx - mov dx,cx - pop bp - pop bx - - shl cx,SECTOR_SHIFT - 4 - add bx,cx - sub bp,dx - jnz .more - - ; Move the image into place, and also verify the - ; checksum - pop ax ; Load segment address - mov bx,(TEXT_START + SECTOR_SIZE) >> 4 - mov ecx,[ImageDwords] - mov edi,[FirstSecSum] ; First sector checksum - xor si,si - -move_verify_image: -.setseg: - mov ds,ax - mov es,bx -.loop: - mov edx,[si] - add edi,edx - dec ecx - mov [es:si],edx - jz .done - add si,4 - jnz .loop - add ax,1000h - add bx,1000h - jmp .setseg -.done: - mov ax,cs - mov ds,ax - mov es,ax - - ; Verify the checksum on the loaded image. - cmp [bi_csum],edi - je integrity_ok - - mov si,checkerr_msg - call writemsg - jmp kaboom - -integrity_ok: -%ifdef DEBUG_MESSAGES - mov si,allread_msg - call writemsg -%endif - jmp all_read ; Jump to main code - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; There is a problem with certain versions of the AWARD BIOS ... -;; the boot sector will be loaded and executed correctly, but, because the -;; int 13 vector points to the wrong code in the BIOS, every attempt to -;; load the spec packet will fail. We scan for the equivalent of -;; -;; mov ax,0201h -;; mov bx,7c00h -;; mov cx,0006h -;; mov dx,0180h -;; pushf -;; call <direct far> -;; -;; and use <direct far> as the new vector for int 13. The code above is -;; used to load the boot code into ram, and there should be no reason -;; for anybody to change it now or in the future. There are no opcodes -;; that use encodings relativ to IP, so scanning is easy. If we find the -;; code above in the BIOS code we can be pretty sure to run on a machine -;; with an broken AWARD BIOS ... -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; -%ifdef DEBUG_MESSAGES ;; - ;; -award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;; -award_not_orig db "BAH: Original Int 13 vector : ",0 ;; -award_not_new db "BAH: Int 13 vector changed to : ",0 ;; -award_not_succ db "BAH: SUCCESS",CR,LF,0 ;; -award_not_fail db "BAH: FAILURE" ;; -award_not_crlf db CR,LF,0 ;; - ;; -%endif ;; - ;; -award_oldint13 dd 0 ;; -award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;; - ;; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -award_hack: mov si,spec_err_msg ; Moved to this place from - call writemsg ; spec_query_faild - ; -%ifdef DEBUG_MESSAGES ; - ; - mov si,award_notice ; display our plan - call writemsg ; - mov si,award_not_orig ; display original int 13 - call writemsg ; vector -%endif ; - mov eax,[13h*4] ; - mov [award_oldint13],eax ; - ; -%ifdef DEBUG_MESSAGES ; - ; - call writehex8 ; - mov si,award_not_crlf ; - call writestr_early ; -%endif ; - push es ; save ES - mov ax,0f000h ; ES = BIOS Seg - mov es,ax ; - cld ; - xor di,di ; start at ES:DI = f000:0 -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_early ; -%endif ; - mov ax,4B01h ; try to read the spec packet - mov dl,[DriveNumber] ; 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],13h ; Size of buffer - call int13 - 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 -.found_drive0: mov [DriveNumber],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: - mov al,[DriveNumber] - cmp al,dl - je .found_drive - - ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02 - ; passes garbage in sp_drive, and the drive number originally - ; passed in DL does not have 80h bit set. - or al,80h - cmp al,dl - je .found_drive0 - -.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,[DriveNumber] - 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_early - pop si - call writestr_early - 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: -.simple: - pushfd - pushad - mov ah,0Eh - xor bx,bx - int 10h - popad - popfd - ret - -; -; int13: save all the segment registers and call INT 13h. -; Some CD-ROM BIOSes have been found to corrupt segment registers -; and/or disable interrupts. -; -int13: - pushf - push bp - push ds - push es - push fs - push gs - int 13h - mov bp,sp - setc [bp+10] ; Propagate CF to the caller - pop gs - pop fs - pop es - pop ds - pop bp - popf - ret - -; -; Get one sector. Convenience entry point. -; -getonesec: - mov bp,1 - ; Fall through to getlinsec - -; -; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors. -; -; Input: -; EAX - Linear sector number -; ES:BX - Target buffer -; BP - Sector count -; - global getlinsec -getlinsec: jmp word [cs:GetlinsecPtr] - -%ifndef DEBUG_MESSAGES - -; -; First, the variants that we use when actually loading off a disk -; (hybrid mode.) These are adapted versions of the equivalent routines -; in ldlinux.asm. -; - -; -; getlinsec_ebios: -; -; getlinsec implementation for floppy/HDD EBIOS (EDD) -; -getlinsec_ebios: - xor edx,edx - shld edx,eax,2 - shl eax,2 ; Convert to HDD sectors - add eax,[Hidden] - adc edx,[Hidden+4] - shl bp,2 - -.loop: - push bp ; Sectors left -.retry2: - call maxtrans ; Enforce maximum transfer size - movzx edi,bp ; Sectors we are about to read - mov cx,retry_count -.retry: - - ; Form DAPA on stack - push edx - push eax - push es - push bx - push di - push word 16 - mov si,sp - pushad - mov dl,[DriveNumber] - push ds - push ss - pop ds ; DS <- SS - mov ah,42h ; Extended Read - call int13 - pop ds - popad - lea sp,[si+16] ; Remove DAPA - jc .error - pop bp - add eax,edi ; Advance sector pointer - adc edx,0 - sub bp,di ; Sectors left - shl di,9 ; 512-byte sectors - add bx,di ; Advance buffer pointer - and bp,bp - jnz .loop - - ret - -.error: - ; Some systems seem to get "stuck" in an error state when - ; using EBIOS. Doesn't happen when using CBIOS, which is - ; good, since some other systems get timeout failures - ; waiting for the floppy disk to spin up. - - pushad ; Try resetting the device - xor ax,ax - mov dl,[DriveNumber] - call int13 - popad - loop .retry ; CX-- and jump if not zero - - ;shr word [MaxTransfer],1 ; Reduce the transfer size - ;jnz .retry2 - - ; Total failure. Try falling back to CBIOS. - mov word [GetlinsecPtr], getlinsec_cbios - ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer - - pop bp - jmp getlinsec_cbios.loop - -; -; getlinsec_cbios: -; -; getlinsec implementation for legacy CBIOS -; -getlinsec_cbios: - xor edx,edx - shl eax,2 ; Convert to HDD sectors - add eax,[Hidden] - shl bp,2 - -.loop: - push edx - push eax - push bp - push bx - - movzx esi,word [bsSecPerTrack] - movzx edi,word [bsHeads] - ; - ; Dividing by sectors to get (track,sector): we may have - ; up to 2^18 tracks, so we need to use 32-bit arithmetric. - ; - div esi - xor cx,cx - xchg cx,dx ; CX <- sector index (0-based) - ; EDX <- 0 - ; eax = track # - div edi ; Convert track to head/cyl - - ; We should test this, but it doesn't fit... - ; cmp eax,1023 - ; ja .error - - ; - ; Now we have AX = cyl, DX = head, CX = sector (0-based), - ; BP = sectors to transfer, SI = bsSecPerTrack, - ; ES:BX = data target - ; - - call maxtrans ; Enforce maximum transfer size - - ; Must not cross track boundaries, so BP <= SI-CX - sub si,cx - cmp bp,si - jna .bp_ok - mov bp,si -.bp_ok: - - shl ah,6 ; Because IBM was STOOPID - ; and thought 8 bits were enough - ; then thought 10 bits were enough... - inc cx ; Sector numbers are 1-based, sigh - or cl,ah - mov ch,al - mov dh,dl - mov dl,[DriveNumber] - xchg ax,bp ; Sector to transfer count - mov ah,02h ; Read sectors - mov bp,retry_count -.retry: - pushad - call int13 - popad - jc .error -.resume: - movzx ecx,al ; ECX <- sectors transferred - shl ax,9 ; Convert sectors in AL to bytes in AX - pop bx - add bx,ax - pop bp - pop eax - pop edx - add eax,ecx - sub bp,cx - jnz .loop - ret - -.error: - dec bp - jnz .retry - - xchg ax,bp ; Sectors transferred <- 0 - shr word [MaxTransfer],1 - jnz .resume - jmp disk_error - -; -; Truncate BP to MaxTransfer -; -maxtrans: - cmp bp,[MaxTransfer] - jna .ok - mov bp,[MaxTransfer] -.ok: ret - -%endif - -; -; This is the variant we use for real CD-ROMs: -; LBA, 2K sectors, some special error handling. -; -getlinsec_cdrom: - mov si,dapa ; Load up the DAPA - mov [si+4],bx - mov [si+6],es - mov [si+8],eax -.loop: - push bp ; Sectors left - cmp bp,[MaxTransferCD] - jbe .bp_ok - mov bp,[MaxTransferCD] -.bp_ok: - mov [si+2],bp - push si - mov dl,[DriveNumber] - 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 retry -xint13: mov byte [RetryCount],retry_count -.try: pushad - call int13 - 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 [MaxTransferCD],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_early - mov ax,[DiskSys] - call writehex4 - mov si,ondrive_str - call writestr_early - 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. -; - global kaboom -disk_error: -kaboom: - RESET_STACK_AND_SEGS AX - mov si,err_bootfailed - call writestr - 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 output -writestr_early equ writestr -%include "writehex.inc" ; Hexadecimal output - -; ----------------------------------------------------------------------------- -; Data that needs to be in the first sector -; ----------------------------------------------------------------------------- - -syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0 -copyright_str db ' Copyright (C) 1994-' - asciidec YEAR - db ' H. Peter Anvin et al', CR, LF, 0 -isolinux_str db 'isolinux: ', 0 -%ifdef DEBUG_MESSAGES -startup_msg: db 'Starting up, DL = ', 0 -spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0 -secsize_msg: db 'Sector size ', 0 -offset_msg: db 'Main image LBA = ', 0 -verify_msg: db 'Image checksum verified.', CR, LF, 0 -allread_msg db 'Main image read, jumping to main code...', CR, LF, 0 -%endif -noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0 -noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0 -spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0 -maybe_msg: db 'Found something at drive = ', 0 -alright_msg: db 'Looks reasonable, continuing...', CR, LF, 0 -nospec_msg db 'Extremely broken BIOS detected, last attempt with drive = ', 0 -nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF -trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0 -diskerr_msg: db 'Disk error ', 0 -oncall_str: db ', AX = ',0 -ondrive_str: db ', drive ', 0 -checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0 - -err_bootfailed db CR, LF, 'Boot failed: press a key to retry...' -bailmsg equ err_bootfailed -crlf_msg db CR, LF -null_msg db 0 - -bios_cdrom_str db 'ETCD', 0 -%ifndef DEBUG_MESSAGES -bios_cbios_str db 'CHDD', 0 -bios_ebios_str db 'EHDD' ,0 -%endif - - alignz 4 -bios_cdrom: dw getlinsec_cdrom, bios_cdrom_str -%ifndef DEBUG_MESSAGES -bios_cbios: dw getlinsec_cbios, bios_cbios_str -bios_ebios: dw getlinsec_ebios, bios_ebios_str -%endif - -; Maximum transfer size -MaxTransfer dw 127 ; Hard disk modes -MaxTransferCD dw 32 ; CD mode - -rl_checkpt equ $ ; Must be <= 800h - - ; This pads to the end of sector 0 and errors out on - ; overflow. - times 2048-($-$$) db 0 - -; ---------------------------------------------------------------------------- -; End of code and data that have to be in the first sector -; ---------------------------------------------------------------------------- - - section .text16 - -all_read: - -; Test tracers - TRACER 'T' - TRACER '>' - -; -; Common initialization code -; -%include "init.inc" - - ; Patch the writechr routine to point to the full code - mov di,writechr - mov al,0e9h - stosb - mov ax,writechr_full-2 - sub ax,di - stosw - -; Tell the user we got this far... -%ifndef DEBUG_MESSAGES ; Gets messy with debugging on - mov si,copyright_str - call writestr_early -%endif - -; -; 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. -; -init_fs: - pushad - mov eax,ROOT_FS_OPS - mov dl,[DriveNumber] - cmp word [BIOSType],bios_cdrom - sete dh ; 1 for cdrom, 0 for hybrid mode - jne .hybrid - movzx ebp,word [MaxTransferCD] - jmp .common -.hybrid: - movzx ebp,word [MaxTransfer] -.common: - mov ecx,[Hidden] - mov ebx,[Hidden+4] - mov si,[bsHeads] - mov di,[bsSecPerTrack] - pm_call fs_init - popad - - section .rodata - alignz 4 -ROOT_FS_OPS: - extern iso_fs_ops - dd iso_fs_ops - dd 0 - - section .text16 - -; -; Locate the configuration file -; - pm_call pm_load_config - jz no_config_file - -; -; Now we have the config file open. Parse the config file and -; run the user interface. -; -%include "ui.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 ':' - - mov edx,eax ; 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 - pm_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 - mov dl,[DriveNumber] - lss sp,[InitStack] - TRACER 'X' - - call int13 - - ; If this returns, we have problems -.bad_image: - mov si,err_disk_image - call writestr - 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 - - - -; ----------------------------------------------------------------------------- -; Common modules -; ----------------------------------------------------------------------------- - -%include "common.inc" ; Universal modules -%include "rawcon.inc" ; Console I/O w/o using the console functions -%include "localboot.inc" ; Disk-based local boot - -; ----------------------------------------------------------------------------- -; Begin data section -; ----------------------------------------------------------------------------- - - section .data16 -err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0 - -; -; Config file keyword table -; -%include "keywords.inc" - -; -; Extensions to search for (in *forward* order). -; - alignz 4 -exten_table: db '.cbt' ; COMBOOT (specific) - db '.img' ; Disk image - db '.bin' ; CD boot sector - db '.com' ; COMBOOT (same as DOS) - db '.c32' ; COM32 -exten_table_end: - dd 0, 0 ; Need 8 null bytes here - -; -; Floppy image table -; - alignz 4 -img_table_count equ 3 -img_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 |