summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/syslinux-4.03/core/isolinux.asm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/core/isolinux.asm')
-rw-r--r--contrib/syslinux/syslinux-4.03/core/isolinux.asm1384
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