[BOOTSECTORS] Use the new header with SPDX license identifier for the ISO boot sector...
[reactos.git] / reactos / boot / freeldr / bootsect / isoboot.asm
diff --git a/reactos/boot/freeldr/bootsect/isoboot.asm b/reactos/boot/freeldr/bootsect/isoboot.asm
deleted file mode 100644 (file)
index 9c0e186..0000000
+++ /dev/null
@@ -1,1018 +0,0 @@
-; ****************************************************************************
-;
-;  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 (C) 1994-2001  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., 675 Mass Ave, Cambridge MA 02139,
-;  USA; either version 2 of the License, or (at your option) any later
-;  version; incorporated herein by reference.
-;
-; ****************************************************************************
-;
-; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM
-; MODIFICATION DONE BY MICHAEL K TER LOUW
-; LAST UPDATED 3-9-2002
-; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE
-;
-; ****************************************************************************
-;
-; This file is a modified version of ISOLINUX.ASM.
-; Modification done by Eric Kohl
-; Last update 04-25-2002
-;
-; ****************************************************************************
-
-; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
-;%define DEBUG_MESSAGES                ; Uncomment to get debugging messages
-
-%define WAIT_FOR_KEY
-
-
-; ---------------------------------------------------------------------------
-;   BEGIN THE BIOS/CODE/DATA SEGMENT
-; ---------------------------------------------------------------------------
-
-               absolute 0400h
-serial_base    resw 4                  ; Base addresses for 4 serial ports
-               absolute 0413h
-BIOS_fbm       resw 1                  ; Free Base Memory (kilobytes)
-               absolute 046Ch
-BIOS_timer     resw 1                  ; Timer ticks
-               absolute 0472h
-BIOS_magic     resw 1                  ; BIOS reset magic
-               absolute 0484h
-BIOS_vidrows   resb 1                  ; Number of screen rows
-
-;
-; Memory below this point is reserved for the BIOS and the MBR
-;
-               absolute 1000h
-trackbuf       resb 8192               ; Track buffer goes here
-trackbufsize   equ $-trackbuf
-;              trackbuf ends at 3000h
-
-               struc open_file_t
-file_sector    resd 1                  ; Sector pointer (0 = structure free)
-file_left      resd 1                  ; Number of sectors left
-               endstruc
-
-               struc dir_t
-dir_lba                resd 1                  ; Directory start (LBA)
-dir_len                resd 1                  ; Length in bytes
-dir_clust      resd 1                  ; Length in clusters
-               endstruc
-
-
-MAX_OPEN_LG2   equ 2                   ; log2(Max number of open files)
-MAX_OPEN       equ (1 << MAX_OPEN_LG2)
-SECTORSIZE_LG2 equ 11                  ; 2048 bytes/sector (El Torito requirement)
-SECTORSIZE     equ (1 << SECTORSIZE_LG2)
-CR             equ 13                  ; Carriage Return
-LF             equ 10                  ; Line Feed
-retry_count    equ 6                   ; How patient are we with the BIOS?
-
-
-
-       absolute 5000h                          ; Here we keep our BSS stuff
-
-DriveNo                resb 1                  ; CD-ROM BIOS drive number
-DiskError      resb 1                  ; Error code for disk I/O
-RetryCount     resb 1                  ; Used for disk access retries
-TimeoutCount   resb 1                  ; Timeout counter
-ISOFlags       resb 1                  ; Flags for ISO directory search
-RootDir                resb dir_t_size         ; Root directory
-CurDir         resb dir_t_size         ; Current directory
-ISOFileName    resb 64                 ; ISO filename canonicalization buffer
-ISOFileNameEnd equ $
-
-
-               alignb open_file_t_size
-Files          resb MAX_OPEN*open_file_t_size
-
-
-
-       section .text
-       org 7000h
-
-start:
-       cli                                     ; Disable interrupts
-       xor     ax, ax                          ; ax = segment zero
-       mov     ss, ax                          ; Initialize stack segment
-       mov     sp, start                       ; Set up stack
-       mov     ds, ax                          ; Initialize other segment registers
-       mov     es, ax
-       mov     fs, ax
-       mov     gs, ax
-       sti                                     ; Enable interrupts
-       cld                                     ; Increment pointers
-
-       mov     cx, 2048 >> 2                   ; Copy the bootsector
-       mov     si, 0x7C00                      ; from 0000:7C00
-       mov     di, 0x7000                      ; to 0000:7000
-       rep     movsd                           ; copy the program
-       jmp     0:relocate                      ; jump into relocated code
-
-relocate:
-       ; Display the banner and copyright
-%ifdef DEBUG_MESSAGES
-       mov     si, isolinux_banner             ; si points to hello message
-       call    writestr                        ; display the message
-       mov     si,copyright_str
-       call    writestr
-%endif
-
-
-       ; Make sure the keyboard buffer is empty
-%ifdef WAIT_FOR_KEY
-       call    pollchar_and_empty
-
-       ; Check for MBR on harddisk
-       pusha
-       mov     ax, 0201h
-       mov     dx, 0080h
-       mov     cx, 0001h
-       mov     bx, trackbuf
-       int     13h
-       popa
-       jc      .boot_cdrom ; could not read hdd
-
-       push ax
-       mov ax, word [trackbuf]
-       cmp ax, 0
-       je      .boot_cdrom ; no boot sector found (hopefully there are no weird bootsectors which begin with 0)
-       pop ax
-
-       ; Display the 'Press key' message and wait for a maximum of 5 seconds
-       call    crlf
-       mov     si, presskey_msg                ; si points to 'Press key' message
-       call    writestr                        ; display the message
-
-       mov     byte [TimeoutCount], 5
-.next_second:
-       mov     eax, [BIOS_timer]               ; load current tick counter
-       add     eax, 19                         ;
-
-.poll_again:
-       call    pollchar_and_empty
-       jnz     .boot_cdrom
-
-       mov     ebx, [BIOS_timer]
-       cmp     eax, ebx
-       jnz     .poll_again
-
-       mov     si, dot_msg                     ; print '.'
-       call    writestr
-       dec     byte [TimeoutCount]             ; decrement timeout counter
-       jz      .boot_harddisk
-       jmp     .next_second
-
-.boot_harddisk:
-       call    crlf
-
-       ; Boot first harddisk (drive 0x80)
-       mov     ax, 0201h
-       mov     dx, 0080h
-       mov     cx, 0001h
-       mov     bx, 7C00h
-       int     13h
-       jnc     .go_hd
-       jmp     kaboom
-.go_hd:
-       mov     ax, cs
-       mov     ds, ax
-       mov     es, ax
-       mov     fs, ax
-       mov     gs, ax
-       mov     dx, 0080h
-
-       jmp     0:0x7C00
-%endif
-
-.boot_cdrom:
-%ifdef WAIT_FOR_KEY
-       call    crlf
-       call    crlf
-%endif
-
-       ; Save and display the boot drive number
-       mov     [DriveNo], dl
-%ifdef DEBUG_MESSAGES
-       mov     si, startup_msg
-       call    writemsg
-       mov     al, dl
-       call    writehex2
-       call    crlf
-%endif
-
-       ; 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, [DriveNo]
-       mov     si, spec_packet
-       int     13h
-       jc      near spec_query_failed          ; Shouldn't happen (BIOS bug)
-       mov     dl, [DriveNo]
-       cmp     [sp_drive], dl                  ; Should contain the drive number
-       jne     near 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:
-       ; Get drive information
-       mov     ah, 48h
-       mov     dl, [DriveNo]
-       mov     si, drive_params
-       int     13h
-       jnc     params_ok
-
-       ; mov   si, nosecsize_msg       No use in reporting this
-       ; call  writemsg
-
-params_ok:
-       ; Check for the sector size (should be 2048, but
-       ; some BIOSes apparently think we're 512-byte media)
-       ;
-       ; FIX: We need to check what the proper behaviour
-       ; is for getlinsec when the BIOS thinks the sector
-       ; size is 512!!!  For that, we need such a BIOS, though...
-%ifdef DEBUG_MESSAGES
-       mov     si, secsize_msg
-       call    writemsg
-       mov     ax, [dp_secsize]
-       call    writehex4
-       call    crlf
-%endif
-
-
-       ;
-       ; Clear Files structures
-       ;
-       mov     di, Files
-       mov     cx, (MAX_OPEN*open_file_t_size)/4
-       xor     eax, eax
-       rep     stosd
-
-       ;
-       ; 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, 16                 ; Primary Volume Descriptor (sector 16)
-       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, rootloc_msg
-       call    writemsg
-       call    writehex8
-       call    crlf
-%endif
-
-       mov     eax,[trackbuf+156+10]
-       mov     [RootDir+dir_len],eax
-       mov     [CurDir+dir_len],eax
-%ifdef DEBUG_MESSAGES
-       mov     si, rootlen_msg
-       call    writemsg
-       call    writehex8
-       call    crlf
-%endif
-       add     eax,SECTORSIZE-1
-       shr     eax,SECTORSIZE_LG2
-       mov     [RootDir+dir_clust],eax
-       mov     [CurDir+dir_clust],eax
-%ifdef DEBUG_MESSAGES
-       mov     si, rootsect_msg
-       call    writemsg
-       call    writehex8
-       call    crlf
-%endif
-
-       ; Look for the "REACTOS" directory, and if found,
-       ; make it the current directory instead of the root
-       ; directory.
-       mov     di,isolinux_dir
-       mov     al,02h                          ; Search for a directory
-       call    searchdir_iso
-       jnz     .dir_found
-       mov     si,no_dir_msg
-       call    writemsg
-       jmp     kaboom
-
-.dir_found:
-       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
-
-
-       mov     di, isolinux_bin                ; di points to Isolinux filename
-       call    searchdir                       ; look for the file
-       jnz     .isolinux_opened                ; got the file
-       mov     si, no_isolinux_msg             ; si points to error message
-       call    writemsg                        ; display the message
-       jmp     kaboom                          ; fail boot
-
-.isolinux_opened:
-       mov     di, si                          ; save file pointer
-
-%ifdef DEBUG_MESSAGES
-       mov     si, filelen_msg
-       call    writemsg
-       call    writehex8
-       call    crlf
-%endif
-
-       mov ecx, eax                    ; calculate sector count
-       shr ecx, 11
-       test eax, 0x7FF
-       jz .full_sector
-       inc ecx
-.full_sector:
-
-%ifdef DEBUG_MESSAGES
-       mov eax, ecx
-       mov     si, filesect_msg
-       call    writemsg
-       call    writehex8
-       call    crlf
-%endif
-
-; use high segment, as some bios can fail, when offset is too big
-    mov bx, 0x0F80          ; FREELDR_BASE / 16 ; es = load segment
-    mov es, bx
-    xor ebx, ebx            ; bx = load offset
-       mov     si, di                          ; restore file pointer
-       mov     cx, 0xFFFF                      ; load the whole file
-       call    getfssec                        ; get the whole file
-
-%ifdef DEBUG_MESSAGES
-       mov     si, startldr_msg
-       call    writemsg
-       call    crlf
-%endif
-
-       mov     dl, [DriveNo]                   ; dl = boot drive
-       mov dh, 0                                       ; dh = boot partition
-
-    ; Transfer execution to the bootloader
-    ;ljmp16 0, FREELDR_BASE
-    db 0xEA
-    dw 0xF800
-    dw 0
-
-;
-; 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
-;
-
-;
-; 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
-       ret
-
-searchdir:
-       xor     al,al
-searchdir_iso:
-       mov     [ISOFlags],al
-       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
-       push    cx
-       push    word .resume                    ; Where to "return" to
-       push    es
-.isfile:
-       xchg    ax,di
-
-.getsome:
-       ; Get a chunk of the directory
-       mov     si,trackbuf
-       pushad
-       xchg    bx,si
-       mov     cx,1                            ; load one sector
-       call    getfssec
-       popad
-
-.compare:
-       movzx   eax, byte [si]                  ; Length of directory entry
-       cmp     al, 33
-       jb      .next_sector
-       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
-       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+SECTORSIZE-1]
-       and     ax, ~(SECTORSIZE-1)
-       sub     ax, si
-       jmp     short .not_file                 ; We still need to do length checks
-
-.failure:
-%ifdef DEBUG_MESSAGES
-       mov     si, findfail_msg
-       call    writemsg
-       call    crlf
-%endif
-       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, SECTORSIZE-1
-       shr     eax, SECTORSIZE_LG2
-       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 the backslash in the filename
-
-       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:
-       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
-
-
-
-
-
-
-
-;
-; getfssec: Get multiple clusters from a file, given the file pointer.
-;
-;  On entry:
-;      ES:BX   -> Buffer
-;      SI      -> File pointer
-;      CX      -> Cluster count; 0FFFFh = until end of file
-;  On exit:
-;      SI      -> File pointer (or 0 on EOF)
-;      CF = 1  -> Hit EOF
-;
-getfssec:
-       cmp     cx, [si+file_left]
-       jna     .ok_size
-       mov     cx, [si+file_left]
-
-.ok_size:
-       mov     bp, cx
-       push    cx
-       push    si
-       mov     eax, [si+file_sector]
-       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:
-       ret
-
-
-
-; INT 13h, AX=4B01h, DL=<passed in value> failed.
-; Try to scan the entire 80h-FFh from the end.
-spec_query_failed:
-       mov     si,spec_err_msg
-       call    writemsg
-
-       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
-
-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
-
-;
-; crlf: Print a newline
-;
-crlf:
-       mov     si, crlf_msg
-       ; Fall through
-
-;
-; writestr: write a null-terminated string to the console, saving
-;           registers on entry.
-;
-writestr:
-       pushfd
-       pushad
-.top:
-       lodsb
-       and     al, al
-       jz      .end
-       call    writechr
-       jmp     short .top
-.end:
-       popad
-       popfd
-       ret
-
-
-;
-; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
-;
-writehex2:
-       pushfd
-       pushad
-       shl     eax, 24
-       mov     cx, 2
-       jmp     short writehex_common
-writehex4:
-       pushfd
-       pushad
-       shl     eax, 16
-       mov     cx, 4
-       jmp     short writehex_common
-writehex8:
-       pushfd
-       pushad
-       mov     cx, 8
-writehex_common:
-.loop:
-       rol     eax, 4
-       push    eax
-       and     al, 0Fh
-       cmp     al, 10
-       jae     .high
-.low:
-       add     al, '0'
-       jmp     short .ischar
-.high:
-       add     al, 'A'-10
-.ischar:
-       call    writechr
-       pop     eax
-       loop    .loop
-       popad
-       popfd
-       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:
-       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
-.loop2:
-       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 .loop2
-       mov eax,[si+8]                  ; Next sector
-       ret
-
-       ; INT 13h with retry
-xint13:
-       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
-       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, 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:
-       mov     ax, cs
-       mov     ds, ax
-       mov     es, ax
-       mov     fs, ax
-       mov     gs, ax
-       sti
-       mov     si, err_bootfailed
-       call    writestr
-       xor     ax, ax          ; Wait for keypress
-       int     16h
-       cli
-       mov     word [BIOS_magic], 0    ; Cold reboot
-       jmp     0F000h:0FFF0h           ; Reset vector address
-
-
-;
-; pollchar_and_empty: check if we have an input character pending (ZF = 0) and empty the input buffer afterwards
-;
-pollchar_and_empty:
-       pushad
-       mov ah, 1               ; Did the user press a key?
-       int 16h
-       jz      .end            ; No, then we're done
-       mov ah, 0               ; Otherwise empty the buffer by reading it
-       int 16h
-.end:
-       popad
-       ret
-
-
-
-isolinux_banner        db CR, LF, 'Loading IsoBoot...', CR, LF, 0
-copyright_str  db ' (C) 1994-2002 H. Peter Anvin', CR, LF, 0
-presskey_msg   db 'Press any key to boot from CD', 0
-dot_msg                db '.',0
-
-%ifdef DEBUG_MESSAGES
-startup_msg:   db 'Startup, DL = ', 0
-spec_ok_msg:   db 'packet OK, drive = ', 0
-secsize_msg:   db 'size appears to be ', 0
-rootloc_msg:   db 'Root dir loc: ', 0
-rootlen_msg:   db 'Root dir len: ', 0
-rootsect_msg:  db 'Root dir len(sect): ', 0
-fileloc_msg:   db 'SETUPLDR loc: ', 0
-filelen_msg:   db 'SETUPLDR len: ', 0
-filesect_msg:  db 'SETUPLDR len(sect): ', 0
-findfail_msg:  db 'Failed to find file!', 0
-startldr_msg:  db 'Starting SETUPLDR.SYS', 0
-%endif
-
-; nosecsize_msg:       db 'No sector size, assume 0800', CR, LF, 0
-spec_err_msg:  db 'Load spec failed, trying wing ...', CR, LF, 0
-maybe_msg:     db 'Found smth at drive = ', 0
-alright_msg:   db 'might be ok, continuing...', CR, LF, 0
-nothing_msg:   db 'Failed locate CD-ROM; boot failed.', CR, LF, 0
-isolinux_str   db 'IsoBoot: ', 0
-crlf_msg       db CR, LF, 0
-diskerr_msg:   db 'Disk error ', 0
-ondrive_str:   db ', drive ', 0
-err_bootfailed db CR, LF, 'failed..', 0
-isolinux_dir   db '\LOADER', 0
-no_dir_msg     db 'LOADER dir not found.', CR, LF, 0
-isolinux_bin   db 'SETUPLDR.SYS', 0
-no_isolinux_msg        db 'SETUPLDR not found.', CR, LF, 0
-
-;
-; El Torito spec packet
-;
-               align 8, db 0
-spec_packet:   db 13h                          ; Size of packet
-sp_media:      db 0                            ; Media type
-sp_drive:      db 0                            ; Drive number
-sp_controller: db 0                            ; Controller index
-sp_lba:                dd 0                            ; LBA for emulated disk image
-sp_devspec:    dw 0                            ; IDE/SCSI information
-sp_buffer:     dw 0                            ; User-provided buffer
-sp_loadseg:    dw 0                            ; Load segment
-sp_sectors:    dw 0                            ; Sector count
-sp_chs:                db 0,0,0                        ; Simulated CHS geometry
-sp_dummy:      db 0                            ; Scratch, safe to overwrite
-
-;
-; EBIOS drive parameter packet
-;
-               align 8, db 0
-drive_params:  dw 30                           ; Buffer size
-dp_flags:      dw 0                            ; Information flags
-dp_cyl:                dd 0                            ; Physical cylinders
-dp_head:       dd 0                            ; Physical heads
-dp_sec:                dd 0                            ; Physical sectors/track
-dp_totalsec:   dd 0,0                          ; Total sectors
-dp_secsize:    dw 0                            ; Bytes per sector
-dp_dpte:       dd 0                            ; Device Parameter Table
-dp_dpi_key:    dw 0                            ; 0BEDDh if rest valid
-dp_dpi_len:    db 0                            ; DPI len
-               db 0
-               dw 0
-dp_bus:                times 4 db 0                    ; Host bus type
-dp_interface:  times 8 db 0                    ; Interface type
-db_i_path:     dd 0,0                          ; Interface path
-db_d_path:     dd 0,0                          ; Device path
-               db 0
-db_dpi_csum:   db 0                            ; Checksum for DPI info
-
-;
-; EBIOS disk address packet
-;
-               align 8, db 0
-dapa:          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 0
-MaxTransfer    dw 2 ;32                                ; Max sectors per transfer
-
-               times 2046-($-$$) db 0          ; Pad to file offset 2046
-               dw 0aa55h                       ; BootSector signature