Fix a couple of problems with FreeLDR portability.
[reactos.git] / reactos / boot / freeldr / bootsect / isobtrt.asm
index 1188634..23fd649 100644 (file)
-; ****************************************************************************\r
-;\r
-;  isolinux.asm\r
-;\r
-;  A program to boot Linux kernels off a CD-ROM using the El Torito\r
-;  boot standard in "no emulation" mode, making the entire filesystem\r
-;  available.  It is based on the SYSLINUX boot loader for MS-DOS\r
-;  floppies.\r
-;\r
-;   Copyright (C) 1994-2001  H. Peter Anvin\r
-;\r
-;  This program is free software; you can redistribute it and/or modify\r
-;  it under the terms of the GNU General Public License as published by\r
-;  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,\r
-;  USA; either version 2 of the License, or (at your option) any later\r
-;  version; incorporated herein by reference.\r
-; \r
-; ****************************************************************************\r
-;\r
-; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM\r
-; MODIFICATION DONE BY MICHAEL K TER LOUW\r
-; LAST UPDATED 3-9-2002\r
-; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE\r
-;\r
-; ****************************************************************************\r
-;\r
-; This file is a modified version of ISOLINUX.ASM.\r
-; Modification done by Eric Kohl\r
-; Last update 04-25-2002\r
-;\r
-; ****************************************************************************\r
-;\r
-; This file is a modified version of ISOLINUX.ASM.\r
-; (for ReactOS regression testing)\r
-; Modification done by Christoph von Wittich\r
-; Last update 08-27-2006\r
-;\r
-; ****************************************************************************\r
-\r
-\r
-; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.\r
-;%define DEBUG_MESSAGES                ; Uncomment to get debugging messages\r
-\r
-%define WAIT_FOR_KEY\r
-\r
-\r
-; ---------------------------------------------------------------------------\r
-;   BEGIN THE BIOS/CODE/DATA SEGMENT\r
-; ---------------------------------------------------------------------------\r
-\r
-               absolute 0400h\r
-serial_base    resw 4                  ; Base addresses for 4 serial ports\r
-               absolute 0413h\r
-BIOS_fbm       resw 1                  ; Free Base Memory (kilobytes)\r
-               absolute 046Ch\r
-BIOS_timer     resw 1                  ; Timer ticks\r
-               absolute 0472h\r
-BIOS_magic     resw 1                  ; BIOS reset magic\r
-               absolute 0484h\r
-BIOS_vidrows   resb 1                  ; Number of screen rows\r
-\r
-;\r
-; Memory below this point is reserved for the BIOS and the MBR\r
-;\r
-               absolute 1000h\r
-trackbuf       resb 8192               ; Track buffer goes here\r
-trackbufsize   equ $-trackbuf\r
-;              trackbuf ends at 3000h\r
-\r
-               struc open_file_t\r
-file_sector    resd 1                  ; Sector pointer (0 = structure free)\r
-file_left      resd 1                  ; Number of sectors left\r
-               endstruc\r
-\r
-               struc dir_t\r
-dir_lba                resd 1                  ; Directory start (LBA)\r
-dir_len                resd 1                  ; Length in bytes\r
-dir_clust      resd 1                  ; Length in clusters\r
-               endstruc\r
-\r
-\r
-MAX_OPEN_LG2   equ 2                   ; log2(Max number of open files)\r
-MAX_OPEN       equ (1 << MAX_OPEN_LG2)\r
-SECTORSIZE_LG2 equ 11                  ; 2048 bytes/sector (El Torito requirement)\r
-SECTORSIZE     equ (1 << SECTORSIZE_LG2)\r
-CR             equ 13                  ; Carriage Return\r
-LF             equ 10                  ; Line Feed\r
-retry_count    equ 6                   ; How patient are we with the BIOS?\r
-\r
-\r
-\r
-       absolute 5000h                          ; Here we keep our BSS stuff\r
-\r
-DriveNo                resb 1                  ; CD-ROM BIOS drive number\r
-DiskError      resb 1                  ; Error code for disk I/O\r
-RetryCount     resb 1                  ; Used for disk access retries\r
-TimeoutCount   resb 1                  ; Timeout counter\r
-ISOFlags       resb 1                  ; Flags for ISO directory search\r
-RootDir                resb dir_t_size         ; Root directory\r
-CurDir         resb dir_t_size         ; Current directory\r
-ISOFileName    resb 64                 ; ISO filename canonicalization buffer\r
-ISOFileNameEnd equ $\r
-\r
-\r
-               alignb open_file_t_size\r
-Files          resb MAX_OPEN*open_file_t_size\r
-\r
-\r
-\r
-       section .text\r
-       org 7000h\r
-\r
-start:\r
-       cli                                     ; Disable interrupts\r
-       xor     ax, ax                          ; ax = segment zero\r
-       mov     ss, ax                          ; Initialize stack segment\r
-       mov     sp, start                       ; Set up stack\r
-       mov     ds, ax                          ; Initialize other segment registers\r
-       mov     es, ax\r
-       mov     fs, ax\r
-       mov     gs, ax\r
-       sti                                     ; Enable interrupts\r
-       cld                                     ; Increment pointers\r
-\r
-       mov     cx, 2048 >> 2                   ; Copy the bootsector\r
-       mov     si, 0x7C00                      ; from 0000:7C00\r
-       mov     di, 0x7000                      ; to 0000:7000\r
-       rep     movsd                           ; copy the program\r
-       jmp     0:relocate                      ; jump into relocated code\r
-\r
-relocate:\r
-       ; Display the banner and copyright\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, isolinux_banner             ; si points to hello message\r
-       call    writestr                        ; display the message\r
-       mov     si,copyright_str\r
-       call    writestr\r
-%endif\r
-\r
-\r
-       ; Make sure the keyboard buffer is empty\r
-%ifdef WAIT_FOR_KEY\r
-.kbd_buffer_test:\r
-       call    pollchar\r
-       jz      .kbd_buffer_empty\r
-       call    getchar\r
-       jmp     .kbd_buffer_test\r
-.kbd_buffer_empty:\r
-\r
-       ; Check if there is harddisk\r
-       pusha\r
-       mov     ax, 0800h\r
-       mov     dx, 0080h\r
-       int     13h\r
-       popa\r
-       jmp     .boot_cdrom\r
-\r
-       ; Display the 'Press key' message and wait for a maximum of 5 seconds\r
-       call    crlf\r
-       mov     si, presskey_msg                ; si points to 'Press key' message\r
-       call    writestr                        ; display the message\r
-\r
-       mov     byte [TimeoutCount], 5\r
-.next_second:\r
-       mov     eax, [BIOS_timer]               ; load current tick counter\r
-       add     eax, 19                         ; \r
-\r
-.poll_again:\r
-       call    pollchar\r
-       jnz     .boot_cdrom\r
-\r
-       mov     ebx, [BIOS_timer]\r
-       cmp     eax, ebx\r
-       jnz     .poll_again\r
-\r
-       mov     si, dot_msg                     ; print '.'\r
-       call    writestr\r
-       dec     byte [TimeoutCount]             ; decrement timeout counter\r
-       jz      .boot_harddisk\r
-       jmp     .next_second\r
-\r
-.boot_harddisk:\r
-       call    crlf\r
-\r
-       ; Boot first harddisk (drive 0x80)\r
-       mov     ax, 0201h\r
-       mov     dx, 0080h\r
-       mov     cx, 0001h\r
-       mov     bx, 7C00h\r
-       int     13h\r
-       jnc     .go_hd\r
-       jmp     kaboom\r
-.go_hd:\r
-       mov     ax, cs\r
-       mov     ds, ax\r
-       mov     es, ax\r
-       mov     fs, ax\r
-       mov     gs, ax\r
-       mov     dx, 0080h\r
-\r
-       jmp     0:0x7C00\r
-%endif\r
-\r
-.boot_cdrom:\r
-%ifdef WAIT_FOR_KEY\r
-       call    crlf\r
-       call    crlf\r
-%endif\r
-\r
-       ; Save and display the boot drive number\r
-       mov     [DriveNo], dl\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, startup_msg\r
-       call    writemsg\r
-       mov     al, dl\r
-       call    writehex2\r
-       call    crlf\r
-%endif\r
-\r
-       ; Now figure out what we're actually doing\r
-       ; Note: use passed-in DL value rather than 7Fh because\r
-       ; at least some BIOSes will get the wrong value otherwise\r
-       mov     ax, 4B01h                       ; Get disk emulation status\r
-       mov     dl, [DriveNo]\r
-       mov     si, spec_packet\r
-       int     13h\r
-       jc      near spec_query_failed          ; Shouldn't happen (BIOS bug)\r
-       mov     dl, [DriveNo]\r
-       cmp     [sp_drive], dl                  ; Should contain the drive number\r
-       jne     near spec_query_failed\r
-\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, spec_ok_msg\r
-       call    writemsg\r
-       mov     al, byte [sp_drive]\r
-       call    writehex2\r
-       call    crlf\r
-%endif\r
-\r
-found_drive:\r
-       ; Get drive information\r
-       mov     ah, 48h\r
-       mov     dl, [DriveNo]\r
-       mov     si, drive_params\r
-       int     13h\r
-       jnc     params_ok\r
-\r
-       ; mov   si, nosecsize_msg       No use in reporting this\r
-       ; call  writemsg\r
-\r
-params_ok:\r
-       ; Check for the sector size (should be 2048, but\r
-       ; some BIOSes apparently think we're 512-byte media)\r
-       ;\r
-       ; FIX: We need to check what the proper behaviour\r
-       ; is for getlinsec when the BIOS thinks the sector\r
-       ; size is 512!!!  For that, we need such a BIOS, though...\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, secsize_msg\r
-       call    writemsg\r
-       mov     ax, [dp_secsize]\r
-       call    writehex4\r
-       call    crlf\r
-%endif\r
-\r
-\r
-       ;\r
-       ; Clear Files structures\r
-       ;\r
-       mov     di, Files\r
-       mov     cx, (MAX_OPEN*open_file_t_size)/4\r
-       xor     eax, eax\r
-       rep     stosd\r
-\r
-       ;\r
-       ; Now, we need to sniff out the actual filesystem data structures.\r
-       ; mkisofs gave us a pointer to the primary volume descriptor\r
-       ; (which will be at 16 only for a single-session disk!); from the PVD\r
-       ; we should be able to find the rest of what we need to know.\r
-       ;\r
-get_fs_structures:\r
-       mov     eax, 16                 ; Primary Volume Descriptor (sector 16)\r
-       mov     bx, trackbuf\r
-       call    getonesec\r
-\r
-       mov     eax, [trackbuf+156+2]\r
-       mov     [RootDir+dir_lba],eax\r
-       mov     [CurDir+dir_lba],eax\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, rootloc_msg\r
-       call    writemsg\r
-       call    writehex8\r
-       call    crlf\r
-%endif\r
-\r
-       mov     eax,[trackbuf+156+10]\r
-       mov     [RootDir+dir_len],eax\r
-       mov     [CurDir+dir_len],eax\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, rootlen_msg\r
-       call    writemsg\r
-       call    writehex8\r
-       call    crlf\r
-%endif\r
-       add     eax,SECTORSIZE-1\r
-       shr     eax,SECTORSIZE_LG2\r
-       mov     [RootDir+dir_clust],eax\r
-       mov     [CurDir+dir_clust],eax\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, rootsect_msg\r
-       call    writemsg\r
-       call    writehex8\r
-       call    crlf\r
-%endif\r
-\r
-       ; Look for the "REACTOS" directory, and if found,\r
-       ; make it the current directory instead of the root\r
-       ; directory.\r
-       mov     di,isolinux_dir\r
-       mov     al,02h                          ; Search for a directory\r
-       call    searchdir_iso\r
-       jnz     .dir_found\r
-       mov     si,no_dir_msg\r
-       call    writemsg\r
-       jmp     kaboom\r
-\r
-.dir_found:\r
-       mov     [CurDir+dir_len],eax\r
-       mov     eax,[si+file_left]\r
-       mov     [CurDir+dir_clust],eax\r
-       xor     eax,eax                         ; Free this file pointer entry\r
-       xchg    eax,[si+file_sector]\r
-       mov     [CurDir+dir_lba],eax\r
-\r
-\r
-       mov     di, isolinux_bin                ; di points to Isolinux filename\r
-       call    searchdir                       ; look for the file\r
-       jnz     .isolinux_opened                ; got the file\r
-       mov     si, no_isolinux_msg             ; si points to error message\r
-       call    writemsg                        ; display the message\r
-       jmp     kaboom                          ; fail boot\r
-\r
-.isolinux_opened:\r
-       mov     di, si                          ; save file pointer\r
-\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, filelen_msg\r
-       call    writemsg\r
-       call    writehex8\r
-       call    crlf\r
-%endif\r
-\r
-       mov ecx, eax                    ; calculate sector count\r
-       shr ecx, 11\r
-       test eax, 0x7FF\r
-       jz .full_sector\r
-       inc ecx\r
-.full_sector:\r
-\r
-%ifdef DEBUG_MESSAGES\r
-       mov eax, ecx\r
-       mov     si, filesect_msg\r
-       call    writemsg\r
-       call    writehex8\r
-       call    crlf\r
-%endif\r
-\r
-       mov     bx, 0x8000                      ; bx = load address\r
-       mov     si, di                          ; restore file pointer\r
-       mov     cx, 0xFFFF                      ; load the whole file\r
-       call    getfssec                        ; get the whole file\r
-\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, startldr_msg\r
-       call    writemsg\r
-       call    crlf\r
-%endif\r
-\r
-       mov     dl, [DriveNo]                   ; dl = boot drive\r
-       mov dh, 0                                       ; dh = boot partition\r
-       jmp     0:0x8000                        ; jump into OSLoader\r
-\r
-\r
-\r
-;\r
-; searchdir:\r
-;\r
-; Open a file\r
-;\r
-;  On entry:\r
-;      DS:DI   = filename\r
-;  If successful:\r
-;      ZF clear\r
-;      SI              = file pointer\r
-;      DX:AX or EAX    = file length in bytes\r
-;  If unsuccessful\r
-;      ZF set\r
-;\r
-\r
-;\r
-; searchdir_iso is a special entry point for ISOLINUX only.  In addition\r
-; to the above, searchdir_iso passes a file flag mask in AL.  This is useful\r
-; for searching for directories.\r
-;\r
-alloc_failure:\r
-       xor     ax,ax                           ; ZF <- 1\r
-       ret\r
-\r
-searchdir:\r
-       xor     al,al\r
-searchdir_iso:\r
-       mov     [ISOFlags],al\r
-       call    allocate_file                   ; Temporary file structure for directory\r
-       jnz     alloc_failure\r
-       push    es\r
-       push    ds\r
-       pop     es                              ; ES = DS\r
-       mov     si,CurDir\r
-       cmp     byte [di],'\'                   ; If filename begins with slash\r
-       jne     .not_rooted\r
-       inc     di                              ; Skip leading slash\r
-       mov     si,RootDir                      ; Reference root directory instead\r
-.not_rooted:\r
-       mov     eax,[si+dir_clust]\r
-       mov     [bx+file_left],eax\r
-       mov     eax,[si+dir_lba]\r
-       mov     [bx+file_sector],eax\r
-       mov     edx,[si+dir_len]\r
-\r
-.look_for_slash:\r
-       mov     ax,di\r
-.scan:\r
-       mov     cl,[di]\r
-       inc     di\r
-       and     cl,cl\r
-       jz      .isfile\r
-       cmp     cl,'\'\r
-       jne     .scan\r
-       mov     [di-1],byte 0                   ; Terminate at directory name\r
-       mov     cl,02h                          ; Search for directory\r
-       xchg    cl,[ISOFlags]\r
-       push    di\r
-       push    cx\r
-       push    word .resume                    ; Where to "return" to\r
-       push    es\r
-.isfile:\r
-       xchg    ax,di\r
-\r
-.getsome:\r
-       ; Get a chunk of the directory\r
-       mov     si,trackbuf\r
-       pushad\r
-       xchg    bx,si\r
-       mov     cx,1                            ; load one sector\r
-       call    getfssec\r
-       popad\r
-\r
-.compare:\r
-       movzx   eax, byte [si]                  ; Length of directory entry\r
-       cmp     al, 33\r
-       jb      .next_sector\r
-       mov     cl, [si+25]\r
-       xor     cl, [ISOFlags]\r
-       test    cl, byte 8Eh                    ; Unwanted file attributes!\r
-       jnz     .not_file\r
-       pusha\r
-       movzx   cx, byte [si+32]                ; File identifier length\r
-       add     si, byte 33                     ; File identifier offset\r
-       call    iso_compare_names\r
-       popa\r
-       je      .success\r
-.not_file:\r
-       sub     edx, eax                        ; Decrease bytes left\r
-       jbe     .failure\r
-       add     si, ax                          ; Advance pointer\r
-\r
-.check_overrun:\r
-       ; Did we finish the buffer?\r
-       cmp     si, trackbuf+trackbufsize\r
-       jb      .compare                        ; No, keep going\r
-\r
-       jmp     short .getsome                  ; Get some more directory\r
-\r
-.next_sector:\r
-       ; Advance to the beginning of next sector\r
-       lea     ax, [si+SECTORSIZE-1]\r
-       and     ax, ~(SECTORSIZE-1)\r
-       sub     ax, si\r
-       jmp     short .not_file                 ; We still need to do length checks\r
-\r
-.failure:\r
-%ifdef DEBUG_MESSAGES\r
-       mov     si, findfail_msg\r
-       call    writemsg\r
-       call    crlf\r
-%endif\r
-       xor     eax, eax                        ; ZF = 1\r
-       mov     [bx+file_sector], eax\r
-       pop     es\r
-       ret\r
-\r
-.success:\r
-       mov     eax, [si+2]                     ; Location of extent\r
-       mov     [bx+file_sector], eax\r
-       mov     eax, [si+10]                    ; Data length\r
-       push    eax\r
-       add     eax, SECTORSIZE-1\r
-       shr     eax, SECTORSIZE_LG2\r
-       mov     [bx+file_left], eax\r
-       pop     eax\r
-       mov     edx, eax\r
-       shr     edx, 16\r
-       and     bx, bx                          ; ZF = 0\r
-       mov     si, bx\r
-       pop     es\r
-       ret\r
-\r
-.resume:\r
-       ; We get here if we were only doing part of a lookup\r
-       ; This relies on the fact that .success returns bx == si\r
-       xchg    edx, eax                        ; Directory length in edx\r
-       pop     cx                              ; Old ISOFlags\r
-       pop     di                              ; Next filename pointer\r
-\r
-       mov     byte [di-1], '\'                ; restore the backslash in the filename\r
-\r
-       mov     [ISOFlags], cl                  ; Restore the flags\r
-       jz      .failure                        ; Did we fail?  If so fail for real!\r
-       jmp     .look_for_slash                 ; Otherwise, next level\r
-\r
-;\r
-; allocate_file: Allocate a file structure\r
-;\r
-;              If successful:\r
-;                ZF set\r
-;                BX = file pointer\r
-;              In unsuccessful:\r
-;                ZF clear\r
-;\r
-allocate_file:\r
-       push    cx\r
-       mov     bx, Files\r
-       mov     cx, MAX_OPEN\r
-.check:\r
-       cmp     dword [bx], byte 0\r
-       je      .found\r
-       add     bx, open_file_t_size            ; ZF = 0\r
-       loop    .check\r
-       ; ZF = 0 if we fell out of the loop\r
-.found:\r
-       pop     cx\r
-       ret\r
-\r
-;\r
-; iso_compare_names:\r
-;      Compare the names DS:SI and DS:DI and report if they are\r
-;      equal from an ISO 9660 perspective.  SI is the name from\r
-;      the filesystem; CX indicates its length, and ';' terminates.\r
-;      DI is expected to end with a null.\r
-;\r
-;      Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment\r
-;\r
-iso_compare_names:\r
-       ; First, terminate and canonicalize input filename\r
-       push    di\r
-       mov     di, ISOFileName\r
-.canon_loop:\r
-       jcxz    .canon_end\r
-       lodsb\r
-       dec     cx\r
-       cmp     al, ';'\r
-       je      .canon_end\r
-       and     al, al\r
-       je      .canon_end\r
-       stosb\r
-       cmp     di, ISOFileNameEnd-1            ; Guard against buffer overrun\r
-       jb      .canon_loop\r
-.canon_end:\r
-       cmp     di, ISOFileName\r
-       jbe     .canon_done\r
-       cmp     byte [di-1], '.'                ; Remove terminal dots\r
-       jne     .canon_done\r
-       dec     di\r
-       jmp     short .canon_end\r
-.canon_done:\r
-       mov     [di], byte 0                    ; Null-terminate string\r
-       pop     di\r
-       mov     si, ISOFileName\r
-.compare:\r
-       lodsb\r
-       mov     ah, [di]\r
-       inc     di\r
-       and     ax, ax\r
-       jz      .success                        ; End of string for both\r
-       and     al, al                          ; Is either one end of string?\r
-       jz      .failure                        ; If so, failure\r
-       and     ah, ah\r
-       jz      .failure\r
-       or      ax, 2020h                       ; Convert to lower case\r
-       cmp     al, ah\r
-       je      .compare\r
-.failure:\r
-       and     ax, ax                          ; ZF = 0 (at least one will be nonzero)\r
-.success:\r
-       ret\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-;\r
-; getfssec: Get multiple clusters from a file, given the file pointer.\r
-;\r
-;  On entry:\r
-;      ES:BX   -> Buffer\r
-;      SI      -> File pointer\r
-;      CX      -> Cluster count; 0FFFFh = until end of file\r
-;  On exit:\r
-;      SI      -> File pointer (or 0 on EOF)\r
-;      CF = 1  -> Hit EOF\r
-;\r
-getfssec:\r
-       cmp     cx, [si+file_left]\r
-       jna     .ok_size\r
-       mov     cx, [si+file_left]\r
-\r
-.ok_size:\r
-       mov     bp, cx\r
-       push    cx\r
-       push    si\r
-       mov     eax, [si+file_sector]\r
-       call    getlinsec\r
-       xor     ecx, ecx\r
-       pop     si\r
-       pop     cx\r
-\r
-       add     [si+file_sector], ecx\r
-       sub     [si+file_left], ecx\r
-       ja      .not_eof                        ; CF = 0\r
-\r
-       xor     ecx, ecx\r
-       mov     [si+file_sector], ecx           ; Mark as unused\r
-       xor     si,si\r
-       stc\r
-\r
-.not_eof:\r
-       ret\r
-\r
-\r
-\r
-; INT 13h, AX=4B01h, DL=<passed in value> failed.\r
-; Try to scan the entire 80h-FFh from the end.\r
-spec_query_failed:\r
-       mov     si,spec_err_msg\r
-       call    writemsg\r
-\r
-       mov     dl, 0FFh\r
-.test_loop:\r
-       pusha\r
-       mov     ax, 4B01h\r
-       mov     si, spec_packet\r
-       mov     byte [si], 13                   ; Size of buffer\r
-       int     13h\r
-       popa\r
-       jc      .still_broken\r
-\r
-       mov     si, maybe_msg\r
-       call    writemsg\r
-       mov     al, dl\r
-       call    writehex2\r
-       call    crlf\r
-\r
-       cmp     byte [sp_drive], dl\r
-       jne     .maybe_broken\r
-\r
-       ; Okay, good enough...\r
-       mov     si, alright_msg\r
-       call    writemsg\r
-       mov     [DriveNo], dl\r
-.found_drive:\r
-       jmp     found_drive\r
-\r
-       ; Award BIOS 4.51 apparently passes garbage in sp_drive,\r
-       ; but if this was the drive number originally passed in\r
-       ; DL then consider it "good enough"\r
-.maybe_broken:\r
-       cmp     byte [DriveNo], dl\r
-       je      .found_drive\r
-\r
-.still_broken:\r
-       dec dx\r
-       cmp     dl, 80h\r
-       jnb     .test_loop\r
-\r
-fatal_error:\r
-       mov     si, nothing_msg\r
-       call    writemsg\r
-\r
-.norge:\r
-       jmp     short .norge\r
-\r
-\r
-\r
-       ; Information message (DS:SI) output\r
-       ; Prefix with "isolinux: "\r
-       ;\r
-writemsg:\r
-       push    ax\r
-       push    si\r
-       mov     si, isolinux_str\r
-       call    writestr\r
-       pop     si\r
-       call    writestr\r
-       pop     ax\r
-       ret\r
-\r
-;\r
-; crlf: Print a newline\r
-;\r
-crlf:\r
-       mov     si, crlf_msg\r
-       ; Fall through\r
-\r
-;\r
-; writestr: write a null-terminated string to the console, saving\r
-;           registers on entry.\r
-;\r
-writestr:\r
-       pushfd\r
-       pushad\r
-.top:\r
-       lodsb\r
-       and     al, al\r
-       jz      .end\r
-       call    writechr\r
-       jmp     short .top\r
-.end:\r
-       popad\r
-       popfd\r
-       ret\r
-\r
-\r
-;\r
-; writehex[248]: Write a hex number in (AL, AX, EAX) to the console\r
-;\r
-writehex2:\r
-       pushfd\r
-       pushad\r
-       shl     eax, 24\r
-       mov     cx, 2\r
-       jmp     short writehex_common\r
-writehex4:\r
-       pushfd\r
-       pushad\r
-       shl     eax, 16\r
-       mov     cx, 4\r
-       jmp     short writehex_common\r
-writehex8:\r
-       pushfd\r
-       pushad\r
-       mov     cx, 8\r
-writehex_common:\r
-.loop:\r
-       rol     eax, 4\r
-       push    eax\r
-       and     al, 0Fh\r
-       cmp     al, 10\r
-       jae     .high\r
-.low:\r
-       add     al, '0'\r
-       jmp     short .ischar\r
-.high:\r
-       add     al, 'A'-10\r
-.ischar:\r
-       call    writechr\r
-       pop     eax\r
-       loop    .loop\r
-       popad\r
-       popfd\r
-       ret\r
-\r
-;\r
-; Write a character to the screen.  There is a more "sophisticated"\r
-; version of this in the subsequent code, so we patch the pointer\r
-; when appropriate.\r
-;\r
-\r
-writechr:\r
-       pushfd\r
-       pushad\r
-       mov     ah, 0Eh\r
-       xor     bx, bx\r
-       int     10h\r
-       popad\r
-       popfd\r
-       ret\r
-\r
-;\r
-; Get one sector.  Convenience entry point.\r
-;\r
-getonesec:\r
-       mov     bp, 1\r
-       ; Fall through to getlinsec\r
-\r
-;\r
-; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.\r
-;\r
-; Note that we can't always do this as a single request, because at least\r
-; Phoenix BIOSes has a 127-sector limit.  To be on the safe side, stick\r
-; to 32 sectors (64K) per request.\r
-;\r
-; Input:\r
-;      EAX     - Linear sector number\r
-;      ES:BX   - Target buffer\r
-;      BP      - Sector count\r
-;\r
-getlinsec:\r
-       mov si,dapa                     ; Load up the DAPA\r
-       mov [si+4],bx\r
-       mov bx,es\r
-       mov [si+6],bx\r
-       mov [si+8],eax\r
-.loop2:\r
-       push bp                         ; Sectors left\r
-       cmp bp,[MaxTransfer]\r
-       jbe .bp_ok\r
-       mov bp,[MaxTransfer]\r
-.bp_ok:\r
-       mov [si+2],bp\r
-       push si\r
-       mov dl,[DriveNo]\r
-       mov ah,42h                      ; Extended Read\r
-       call xint13\r
-       pop si\r
-       pop bp\r
-       movzx eax,word [si+2]           ; Sectors we read\r
-       add [si+8],eax                  ; Advance sector pointer\r
-       sub bp,ax                       ; Sectors left\r
-       shl ax,SECTORSIZE_LG2-4         ; 2048-byte sectors -> segment\r
-       add [si+6],ax                   ; Advance buffer pointer\r
-       and bp,bp\r
-       jnz .loop2\r
-       mov eax,[si+8]                  ; Next sector\r
-       ret\r
-\r
-       ; INT 13h with retry\r
-xint13:\r
-       mov     byte [RetryCount], retry_count\r
-.try:\r
-       pushad\r
-       int     13h\r
-       jc      .error\r
-       add     sp, byte 8*4                    ; Clean up stack\r
-       ret\r
-.error:\r
-       mov     [DiskError], ah         ; Save error code\r
-       popad\r
-       dec byte [RetryCount]\r
-       jz .real_error\r
-       push ax\r
-       mov al,[RetryCount]\r
-       mov ah,[dapa+2]                 ; Sector transfer count\r
-       cmp al,2                        ; Only 2 attempts left\r
-       ja .nodanger\r
-       mov ah,1                        ; Drop transfer size to 1\r
-       jmp short .setsize\r
-.nodanger:\r
-       cmp al,retry_count-2\r
-       ja .again                       ; First time, just try again\r
-       shr ah,1                        ; Otherwise, try to reduce\r
-       adc ah,0                        ; the max transfer size, but not to 0\r
-.setsize:\r
-       mov [MaxTransfer],ah\r
-       mov [dapa+2],ah\r
-.again:\r
-       pop ax\r
-       jmp .try\r
-\r
-.real_error:\r
-       mov     si, diskerr_msg\r
-       call    writemsg\r
-       mov     al, [DiskError]\r
-       call    writehex2\r
-       mov     si, ondrive_str\r
-       call    writestr\r
-       mov     al, dl\r
-       call    writehex2\r
-       call    crlf\r
-       ; Fall through to kaboom\r
-\r
-;\r
-; kaboom: write a message and bail out.  Wait for a user keypress,\r
-;        then do a hard reboot.\r
-;\r
-kaboom:\r
-       mov     ax, cs\r
-       mov     ds, ax\r
-       mov     es, ax\r
-       mov     fs, ax\r
-       mov     gs, ax\r
-       sti\r
-       mov     si, err_bootfailed\r
-       call    writestr\r
-       call    getchar\r
-       cli\r
-       mov     word [BIOS_magic], 0    ; Cold reboot\r
-       jmp     0F000h:0FFF0h           ; Reset vector address\r
-\r
-getchar:\r
-.again:\r
-       mov     ah, 1           ; Poll keyboard\r
-       int     16h\r
-       jz      .again\r
-.kbd:\r
-       xor     ax, ax          ; Get keyboard input\r
-       int     16h\r
-.func_key:\r
-       ret\r
-\r
-\r
-;\r
-; pollchar: check if we have an input character pending (ZF = 0)\r
-;\r
-pollchar:\r
-       pushad\r
-       mov ah,1                ; Poll keyboard\r
-       int 16h\r
-       popad\r
-       ret\r
-\r
-\r
-\r
-isolinux_banner        db CR, LF, 'Loading IsoBoot...', CR, LF, 0\r
-copyright_str  db ' Copyright (C) 1994-2002 H. Peter Anvin', CR, LF, 0\r
-presskey_msg   db 'Press any key to boot from CD', 0\r
-dot_msg                db '.',0\r
-\r
-%ifdef DEBUG_MESSAGES\r
-startup_msg:   db 'Starting up, DL = ', 0\r
-spec_ok_msg:   db 'Loaded spec packet OK, drive = ', 0\r
-secsize_msg:   db 'Sector size appears to be ', 0\r
-rootloc_msg:   db 'Root directory location: ', 0\r
-rootlen_msg:   db 'Root directory length: ', 0\r
-rootsect_msg:  db 'Root directory length(sectors): ', 0\r
-fileloc_msg:   db 'SETUPLDR.SYS location: ', 0\r
-filelen_msg:   db 'SETUPLDR.SYS length: ', 0\r
-filesect_msg:  db 'SETUPLDR.SYS length(sectors): ', 0\r
-findfail_msg:  db 'Failed to find file!', 0\r
-startldr_msg:  db 'Starting SETUPLDR.SYS', 0\r
-%endif\r
-\r
-nosecsize_msg: db 'Failed to get sector size, assuming 0800', CR, LF, 0\r
-spec_err_msg:  db 'Loading spec packet failed, trying to wing it...', CR, LF, 0\r
-maybe_msg:     db 'Found something at drive = ', 0\r
-alright_msg:   db 'Looks like it might be right, continuing...', CR, LF, 0\r
-nothing_msg:   db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0\r
-isolinux_str   db 'IsoBoot: ', 0\r
-crlf_msg       db CR, LF, 0\r
-diskerr_msg:   db 'Disk error ', 0\r
-ondrive_str:   db ', drive ', 0\r
-err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'\r
-isolinux_dir   db '\LOADER', 0\r
-no_dir_msg     db 'Could not find the LOADER directory.', CR, LF, 0\r
-isolinux_bin   db 'SETUPLDR.SYS', 0\r
-no_isolinux_msg        db 'Could not find SETUPLDR.SYS.', CR, LF, 0\r
-\r
-;\r
-; El Torito spec packet\r
-;\r
-               align 8, db 0\r
-spec_packet:   db 13h                          ; Size of packet\r
-sp_media:      db 0                            ; Media type\r
-sp_drive:      db 0                            ; Drive number\r
-sp_controller: db 0                            ; Controller index\r
-sp_lba:                dd 0                            ; LBA for emulated disk image\r
-sp_devspec:    dw 0                            ; IDE/SCSI information\r
-sp_buffer:     dw 0                            ; User-provided buffer\r
-sp_loadseg:    dw 0                            ; Load segment\r
-sp_sectors:    dw 0                            ; Sector count\r
-sp_chs:                db 0,0,0                        ; Simulated CHS geometry\r
-sp_dummy:      db 0                            ; Scratch, safe to overwrite\r
-\r
-;\r
-; EBIOS drive parameter packet\r
-;\r
-               align 8, db 0\r
-drive_params:  dw 30                           ; Buffer size\r
-dp_flags:      dw 0                            ; Information flags\r
-dp_cyl:                dd 0                            ; Physical cylinders\r
-dp_head:       dd 0                            ; Physical heads\r
-dp_sec:                dd 0                            ; Physical sectors/track\r
-dp_totalsec:   dd 0,0                          ; Total sectors\r
-dp_secsize:    dw 0                            ; Bytes per sector\r
-dp_dpte:       dd 0                            ; Device Parameter Table\r
-dp_dpi_key:    dw 0                            ; 0BEDDh if rest valid\r
-dp_dpi_len:    db 0                            ; DPI len\r
-               db 0\r
-               dw 0\r
-dp_bus:                times 4 db 0                    ; Host bus type\r
-dp_interface:  times 8 db 0                    ; Interface type\r
-db_i_path:     dd 0,0                          ; Interface path\r
-db_d_path:     dd 0,0                          ; Device path\r
-               db 0\r
-db_dpi_csum:   db 0                            ; Checksum for DPI info\r
-\r
-;\r
-; EBIOS disk address packet\r
-;\r
-               align 8, db 0\r
-dapa:          dw 16                           ; Packet size\r
-.count:                dw 0                            ; Block count\r
-.off:          dw 0                            ; Offset of buffer\r
-.seg:          dw 0                            ; Segment of buffer\r
-.lba:          dd 0                            ; LBA (LSW)\r
-               dd 0                            ; LBA (MSW)\r
-\r
-               alignb 4, db 0\r
-MaxTransfer    dw 2 ;32                                ; Max sectors per transfer\r
-\r
-               times 2046-($-$$) db 0          ; Pad to file offset 2046\r
-               dw 0aa55h                       ; BootSector signature\r
+; ****************************************************************************
+;
+;  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
+;
+; ****************************************************************************
+;
+; This file is a modified version of ISOLINUX.ASM.
+; (for ReactOS regression testing)
+; Modification done by Christoph von Wittich
+; Last update 08-27-2006
+;
+; ****************************************************************************
+
+
+; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
+;%define DEBUG_MESSAGES                ; Uncomment to get debugging messages
+
+
+; ---------------------------------------------------------------------------
+;   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
+
+; check if there is a mbr on the hdd if so boot from it
+
+       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+510]
+       cmp ax, 0
+       je      .boot_cdrom ; no boot sector found (hopefully there are no weird bootsectors which begin with 0)
+       pop ax
+
+.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
+
+.boot_cdrom:
+       ; 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
+
+       mov     bx, 0x8000                      ; bx = load address
+       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
+       jmp     0:0x8000                        ; jump into OSLoader
+
+
+
+;
+; 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
+       call    getchar
+       cli
+       mov     word [BIOS_magic], 0    ; Cold reboot
+       jmp     0F000h:0FFF0h           ; Reset vector address
+
+getchar:
+.again:
+       mov     ah, 1           ; Poll keyboard
+       int     16h
+       jz      .again
+.kbd:
+       xor     ax, ax          ; Get keyboard input
+       int     16h
+.func_key:
+       ret
+
+
+;
+; pollchar: check if we have an input character pending (ZF = 0)
+;
+pollchar:
+       pushad
+       mov ah,1                ; Poll keyboard
+       int 16h
+       popad
+       ret
+
+
+
+isolinux_banner        db CR, LF, 'Loading IsoBoot...', CR, LF, 0
+copyright_str  db ' Copyright (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 'Starting up, DL = ', 0
+spec_ok_msg:   db 'Loaded spec packet OK, drive = ', 0
+secsize_msg:   db 'Sector size appears to be ', 0
+rootloc_msg:   db 'Root directory location: ', 0
+rootlen_msg:   db 'Root directory length: ', 0
+rootsect_msg:  db 'Root directory length(sectors): ', 0
+fileloc_msg:   db 'SETUPLDR.SYS location: ', 0
+filelen_msg:   db 'SETUPLDR.SYS length: ', 0
+filesect_msg:  db 'SETUPLDR.SYS length(sectors): ', 0
+findfail_msg:  db 'Failed to find file!', 0
+startldr_msg:  db 'Starting SETUPLDR.SYS', 0
+%endif
+
+nosecsize_msg: db 'Failed to get sector size, assuming 0800', 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 like it might be right, continuing...', CR, LF, 0
+nothing_msg:   db 'Failed to locate CD-ROM device; 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, 'Boot failed: press a key to retry...'
+isolinux_dir   db '\LOADER', 0
+no_dir_msg     db 'Could not find the LOADER directory.', CR, LF, 0
+isolinux_bin   db 'SETUPLDR.SYS', 0
+no_isolinux_msg        db 'Could not find SETUPLDR.SYS.', 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