Remove the unmaintained .asm files.
svn path=/trunk/; revision=75984
+++ /dev/null
-;
-; Normal DOS boot sector
-;
-; Ported to NASM from FreeDOS fdisk 1.2.0 by:
-; Casper Hornstrup (chorns@users.sourceforge.net)
-;
-
- align 2, db 0
-
- global _bootnormal_code
-_bootnormal_code:
-
-;-----------------------------------------------------------------------
-; ENTRY (copied from freedos bootsector)
-;
-; IN: DL = boot drive
-;OUT: DL = boot drive
-;
-;-----------------------------------------------------------------------
-
-real_start: cli
- cld
- xor ax, ax
- mov ss, ax ; initialize stack
- mov ds, ax
- mov bp, 0x7c00
- lea sp, [bp-0x20]
- sti
-
- mov ax, 0x1FE0
- mov es, ax
- mov si, bp
- mov di, bp
- mov cx, 0x0100
- rep movsw
-
- jmp word 0x1FE0:0x7c00+ cont-real_start
-
-cont: mov ds, ax
- mov ss, ax
- xor ax,ax
- mov es,ax
-
-
- ; search for active partition
- lea di, [bp+0x1be] ; start of partition table
-test_next_for_active:
- test byte [di],0x80
- jne active_partition_found
- add di,0x10 ; next table
- cmp di, 07c00h+0x1fe; scanned beyond end of table ??
- jb test_next_for_active
-
-;*****************************************************************
- call print
- db 'No active partition found',0
-
-WAIT_FOR_REBOOT:
- jmp $
-
-
-;*****************************************************************
-trouble_reading_drive:
- call print
- db 'Read error while reading drive',0
- jmp WAIT_FOR_REBOOT
-
-;*****************************************************************
-
-invalid_partition_code:
- call print
- db 'Partition signature != 55AA',0
-
- jmp WAIT_FOR_REBOOT
-
-
-;*****************************************************************
-
-active_partition_found:
-; call print
-; db 'Loading active partition',0
-
- call read_boot_sector
-
- jc trouble_reading_drive
-
- cmp word [es:0x7c00+0x1fe],0xaa55
- jne invalid_partition_code
-
- jmp word 0x0:0x7c00 ; and jump to boot sector code
-
-
-;*****************************
-; read_boot_sector
-;
-; IN: DI--> partition info
-;OUT:CARRY
-;*****************************
-
-read_boot_sector:
- ; /* check for LBA support */
- mov bx,0x55aa
- mov ah,0x41
- int 0x13
-
- jc StandardBios ; if (regs.b.x != 0xaa55 || (regs.flags & 0x01))
- cmp bx,0xaa55 ; goto StandardBios;
- jne StandardBios
-
- ; /* if DAP cannot be used, don't use LBA */
- ; if ((regs.c.x & 1) == 0)
- ; goto StandardBios;
- test cl,1
- jz StandardBios
-
- jmp short LBABios
-
-
-_bios_LBA_address_packet:
- db 0x10
- db 0
- db 4 ; read four sectors - why not
- db 0
- dw 0x7c00 ; fixed boot address for DOS sector
- dw 0x0000
-_bios_LBA_low dw 0
-_bios_LBA_high dw 0
- dw 0,0
-
-
-LBABios:
- ; copy start address of partition to DAP
- mov ax,[di+8]
- mov [0x7c00+ (_bios_LBA_low-real_start)],ax
- mov ax,[di+8+2]
- mov [0x7c00+ (_bios_LBA_high-real_start)],ax
-
- mov ax,0x4200 ; regs.a.x = LBA_READ;
- mov si,0x7c00+ (_bios_LBA_address_packet-real_start); regs.si = FP_OFF(&dap);
-
- int 0x13
- ret
-
-;*****************************************************************
-; read disk, using standard BIOS
-;
-StandardBios:
- mov ax,0x0204 ; regs.a.x = 0x0201;
- mov bx,0x7c00 ; regs.b.x = FP_OFF(buffer);
- mov cx,[di+2] ; regs.c.x =
- ; ((chs.Cylinder & 0xff) << 8) + ((chs.Cylinder & 0x300) >> 2) +
- ; chs.Sector;
- ; that was easy ;-)
- mov dh,[di+1] ; regs.d.b.h = chs.Head;
- ; regs.es = FP_SEG(buffer);
- int 0x13
- ret
-
-
-
-;****** PRINT
-; prints text after call to this function.
-
-print_1char:
- xor bx, bx ; video page 0
- mov ah, 0x0E ; else print it
- int 0x10 ; via TTY mode
-print: pop si ; this is the first character
-print1: lodsb ; get token
- push si ; stack up potential return address
- cmp al, 0 ; end of string?
- jne print_1char ; until done
- ret ; and jump to it
-
-
-
- times 0x1fe-$+$$ db 0
- db 0x55,0xaa
-
+++ /dev/null
-; EXT2.ASM
-; EXT2 Boot Sector
-; Copyright (c) 2002, 2003 Brian Palmer
-
-; [bp-0x04] Here we will store the number of sectors per track
-; [bp-0x08] Here we will store the number of heads
-; [bp-0x0c] Here we will store the size of the disk as the BIOS reports in CHS form
-; [bp-0x10] Here we will store the number of LBA sectors read
-
-SECTORS_PER_TRACK equ 0x04
-NUMBER_OF_HEADS equ 0x08
-BIOS_CHS_DRIVE_SIZE equ 0x0C
-LBA_SECTORS_READ equ 0x10
-
-
-EXT2_ROOT_INO equ 2
-EXT2_S_IFMT equ 0f0h
-EXT2_S_IFREG equ 080h
-
-
-org 7c00h
-
-segment .text
-
-bits 16
-
-start:
- jmp short main
- nop
-
-BootDrive db 0x80
-;BootPartition db 0 ; Moved to end of boot sector to have a standard format across all boot sectors
-;SectorsPerTrack db 63 ; Moved to [bp-SECTORS_PER_TRACK]
-;NumberOfHeads dw 16 ; Moved to [bp-NUMBER_OF_HEADS]
-;BiosCHSDriveSize dd (1024 * 1024 * 63) ; Moved to [bp-BIOS_CHS_DRIVE_SIZE]
-;LBASectorsRead dd 0 ; Moved to [bp-LBA_SECTORS_READ]
-
-Ext2VolumeStartSector dd 263088 ; Start sector of the ext2 volume
-Ext2BlockSize dd 2 ; Block size in sectors
-Ext2BlockSizeInBytes dd 1024 ; Block size in bytes
-Ext2PointersPerBlock dd 256 ; Number of block pointers that can be contained in one block
-Ext2GroupDescPerBlock dd 32 ; Number of group descriptors per block
-Ext2FirstDataBlock dd 1 ; First data block (1 for 1024-byte blocks, 0 for bigger sizes)
-Ext2InodesPerGroup dd 2048 ; Number of inodes per group
-Ext2InodesPerBlock dd 8 ; Number of inodes per block
-
-Ext2ReadEntireFileLoadSegment:
- dw 0
-Ext2InodeIndirectPointer:
- dd 0
-Ext2InodeDoubleIndirectPointer:
- dd 0
-Ext2BlocksLeftToRead:
- dd 0
-
-main:
- xor ax,ax ; Setup segment registers
- mov ds,ax ; Make DS correct
- mov es,ax ; Make ES correct
- mov ss,ax ; Make SS correct
- mov bp,7c00h
- mov sp,7b00h ; Setup a stack
-
-
- cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
- jne GetDriveParameters
-
- mov [BYTE bp+BootDrive],dl ; Save the boot drive
-
-
-GetDriveParameters:
- mov ah,08h
- mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
- int 13h ; Request drive parameters from the bios
- jnc CalcDriveSize ; If the call succeeded then calculate the drive size
-
- ; If we get here then the call to the BIOS failed
- ; so just set CHS equal to the maximum addressable
- ; size
- mov cx,0ffffh
- mov dh,cl
-
-CalcDriveSize:
- ; Now that we have the drive geometry
- ; lets calculate the drive size
- mov bl,ch ; Put the low 8-bits of the cylinder count into BL
- mov bh,cl ; Put the high 2-bits in BH
- shr bh,6 ; Shift them into position, now BX contains the cylinder count
- and cl,3fh ; Mask off cylinder bits from sector count
- ; CL now contains sectors per track and DH contains head count
- movzx eax,dh ; Move the heads into EAX
- movzx ebx,bx ; Move the cylinders into EBX
- movzx ecx,cl ; Move the sectors per track into ECX
- inc eax ; Make it one based because the bios returns it zero based
- mov [BYTE bp-NUMBER_OF_HEADS],eax ; Save number of heads
- mov [BYTE bp-SECTORS_PER_TRACK],ecx ; Save number of sectors per track
- inc ebx ; Make the cylinder count one based also
- mul ecx ; Multiply heads with the sectors per track, result in edx:eax
- mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
-
- ; We now have the total number of sectors as reported
- ; by the bios in eax, so store it in our variable
- mov [BYTE bp-BIOS_CHS_DRIVE_SIZE],eax
-
-
-LoadExtraBootCode:
- ; First we have to load our extra boot code at
- ; sector 1 into memory at [0000:7e00h]
- ;mov eax,01h
- xor eax,eax
- inc eax ; Read logical sector 1, EAX now = 1
- mov cx,1 ; Read one sector
- mov bx,7e00h ; Read sector to [0000:7e00h]
- call ReadSectors
-
- jmp LoadRootDirectory
-
-
-
-; Reads ext2 group descriptor into [7000:8000]
-; We read it to this arbitrary location so
-; it will not cross a 64k boundary
-; EAX has group descriptor number to read
-Ext2ReadGroupDesc:
- shl eax,5 ; Group = (Group * sizeof(GROUP_DESCRIPTOR) /* 32 */)
- xor edx,edx
- div DWORD [BYTE bp+Ext2GroupDescPerBlock] ; Group = (Group / Ext2GroupDescPerBlock)
- add eax,DWORD [BYTE bp+Ext2FirstDataBlock] ; Group = Group + Ext2FirstDataBlock + 1
- inc eax ; EAX now has the group descriptor block number
- ; EDX now has the group descriptor offset in the block
-
- ; Adjust the read offset so that the
- ; group descriptor is read to 7000:8000
- mov ebx,78000h
- sub ebx,edx
- shr ebx,4
- mov es,bx
- xor bx,bx
-
-
- ; Everything is now setup to call Ext2ReadBlock
- ; Instead of using the call instruction we will
- ; just put Ext2ReadBlock right after this routine
-
-; Reads ext2 block into [ES:BX]
-; EAX has logical block number to read
-Ext2ReadBlock:
- mov ecx,DWORD [BYTE bp+Ext2BlockSize]
- mul ecx
- jmp ReadSectors
-
-; Reads ext2 inode into [6000:8000]
-; We read it to this arbitrary location so
-; it will not cross a 64k boundary
-; EAX has inode number to read
-Ext2ReadInode:
- dec eax ; Inode = Inode - 1
- xor edx,edx
- div DWORD [BYTE bp+Ext2InodesPerGroup] ; Inode = (Inode / Ext2InodesPerGroup)
- mov ebx,eax ; EBX now has the inode group number
- mov eax,edx
- xor edx,edx
- div DWORD [BYTE bp+Ext2InodesPerBlock] ; Inode = (Inode / Ext2InodesPerBlock)
- shl edx,7 ; FIXME: InodeOffset *= 128 (make the array index a byte offset)
- ; EAX now has the inode offset block number from inode table
- ; EDX now has the inode offset in the block
-
- ; Save the inode values and put the group
- ; descriptor number in EAX and read it in
- push edx
- push eax
- mov eax,ebx
- call Ext2ReadGroupDesc
-
- ; Group descriptor has been read, now
- ; grab the inode table block number from it
- push WORD 7000h
- pop es
- mov di,8008h
- pop eax ; Restore inode offset block number from stack
- add eax,DWORD [es:di] ; Add the inode table start block
-
- ; Adjust the read offset so that the
- ; inode we want is read to 6000:8000
- pop edx ; Restore inode offset in the block from stack
- mov ebx,68000h
- sub ebx,edx
- shr ebx,4
- mov es,bx
- xor bx,bx
-
- call Ext2ReadBlock
- ret
-
-
-; Reads logical sectors into [ES:BX]
-; EAX has logical sector number to read
-; CX has number of sectors to read
-ReadSectors:
- add eax,DWORD [BYTE bp+Ext2VolumeStartSector] ; Add the start of the volume
- cmp eax,DWORD [BYTE bp-BIOS_CHS_DRIVE_SIZE] ; Check if they are reading a sector outside CHS range
- jae ReadSectorsLBA ; Yes - go to the LBA routine
- ; If at all possible we want to use LBA routines because
- ; They are optimized to read more than 1 sector per read
-
- pushad ; Save logical sector number & sector count
-
-CheckInt13hExtensions: ; Now check if this computer supports extended reads
- mov ah,0x41 ; AH = 41h
- mov bx,0x55aa ; BX = 55AAh
- mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
- int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
- jc ReadSectorsCHS ; CF set on error (extensions not supported)
- cmp bx,0xaa55 ; BX = AA55h if installed
- jne ReadSectorsCHS
- test cl,1 ; CX = API subset support bitmap
- jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
-
- popad ; Restore sector count & logical sector number
-
-ReadSectorsLBA:
- pushad ; Save logical sector number & sector count
-
- cmp cx,byte 64 ; Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
- jbe ReadSectorsSetupDiskAddressPacket ; If we are reading less than 65 sectors then just do the read
- mov cx,64 ; Otherwise read only 64 sectors on this loop iteration
-
-ReadSectorsSetupDiskAddressPacket:
- mov [BYTE bp-LBA_SECTORS_READ],cx
- mov WORD [BYTE bp-LBA_SECTORS_READ+2],0
- o32 push byte 0
- push eax ; Put 64-bit logical block address on stack
- push es ; Put transfer segment on stack
- push bx ; Put transfer offset on stack
- push cx ; Set transfer count
- push byte 0x10 ; Set size of packet to 10h
- mov si,sp ; Setup disk address packet on stack
-
-
- mov dl,[BYTE bp+BootDrive] ; Drive number
- mov ah,42h ; Int 13h, AH = 42h - Extended Read
- int 13h ; Call BIOS
- jc PrintDiskError ; If the read failed then abort
-
- add sp,byte 0x10 ; Remove disk address packet from stack
-
- popad ; Restore sector count & logical sector number
-
- push bx
- mov ebx,DWORD [BYTE bp-LBA_SECTORS_READ]
- add eax,ebx ; Increment sector to read
- shl ebx,5
- mov dx,es
- add dx,bx ; Setup read buffer for next sector
- mov es,dx
- pop bx
-
- sub cx,[BYTE bp-LBA_SECTORS_READ]
- jnz ReadSectorsLBA ; Read next sector
-
- ret
-
-
-; Reads logical sectors into [ES:BX]
-; EAX has logical sector number to read
-; CX has number of sectors to read
-ReadSectorsCHS:
- popad ; Get logical sector number & sector count off stack
-
-ReadSectorsCHSLoop:
- pushad
- xor edx,edx
- mov ecx,DWORD [BYTE bp-SECTORS_PER_TRACK]
- div ecx ; Divide logical by SectorsPerTrack
- inc dl ; Sectors numbering starts at 1 not 0
- mov cl,dl ; Sector in CL
- mov edx,eax
- shr edx,16
- div WORD [BYTE bp-NUMBER_OF_HEADS] ; Divide logical by number of heads
- mov dh,dl ; Head in DH
- mov dl,[BYTE bp+BootDrive] ; Drive number in DL
- mov ch,al ; Cylinder in CX
- ror ah,2 ; Low 8 bits of cylinder in CH, high 2 bits
- ; in CL shifted to bits 6 & 7
- or cl,ah ; Or with sector number
- mov ax,0201h
- int 13h ; DISK - READ SECTORS INTO MEMORY
- ; AL = number of sectors to read, CH = track, CL = sector
- ; DH = head, DL = drive, ES:BX -> buffer to fill
- ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
-
- jc PrintDiskError ; If the read failed then abort
-
- popad
-
- inc eax ; Increment Sector to Read
-
- mov dx,es
- add dx,byte 20h ; Increment read buffer for next sector
- mov es,dx
-
- loop ReadSectorsCHSLoop ; Read next sector
-
- ret
-
-
-
-
-; Displays a disk error message
-; And reboots
-PrintDiskError:
- mov si,msgDiskError ; Bad boot disk message
- call PutChars ; Display it
-
-Reboot:
- mov si,msgAnyKey ; Press any key message
- call PutChars ; Display it
- xor ax,ax
- int 16h ; Wait for a keypress
- int 19h ; Reboot
-
-PutChars:
- lodsb
- or al,al
- jz short Done
- call PutCharsCallBios
- jmp short PutChars
-PutCharsCallBios:
- mov ah,0eh
- mov bx,07h
- int 10h
- retn
-Done:
- mov al,0dh
- call PutCharsCallBios
- mov al,0ah
- call PutCharsCallBios
- retn
-
-
-
-msgDiskError db 'Disk error',0
-; Sorry, need the space...
-;msgAnyKey db 'Press any key to restart',0
-msgAnyKey db 'Press any key',0
-
- times 509-($-$$) db 0 ; Pad to 509 bytes
-
-BootPartition db 0
-
- dw 0aa55h ; BootSector signature
-
-
-; End of bootsector
-;
-; Now starts the extra boot code that we will store
-; at sector 1 on a EXT2 volume
-
-
-
-LoadRootDirectory:
-
- mov eax,EXT2_ROOT_INO ; Put the root directory inode number in EAX
- call Ext2ReadInode ; Read in the inode
-
- ; Point ES:DI to the inode structure at 6000:8000
- push WORD 6000h
- pop es
- mov di,8000h
- push di
- push es ; Save these for later
-
- ; Get root directory size from inode structure
- mov eax,DWORD [es:di+4]
- push eax
-
- ; Now that the inode has been read in load
- ; the root directory file data to 0000:8000
- call Ext2ReadEntireFile
-
- ; Since the root directory was loaded to 0000:8000
- ; then add 8000h to the root directory's size
- pop eax
- mov edx,8000h ; Set EDX to the current offset in the root directory
- add eax,edx ; Initially add 8000h to the size of the root directory
-
-SearchRootDirectory:
- push edx ; Save current offset in root directory
- push eax ; Save the size of the root directory
-
- ; Now we have to convert the current offset
- ; in the root directory to a SEGMENT:OFFSET pair
- mov eax,edx
- xor edx,edx
- mov ecx,16
- div ecx ; Now AX:DX has segment & offset
- mov es,ax
- mov di,dx
- push di ; Save the start of the directory entry
- add di,byte 8 ; Add the offset to the filename
- mov si,filename
- mov cl,11
- rep cmpsb ; Compare the file names
- pop di
- pop eax
- pop edx
- jz FoundFile
-
- ; Nope, didn't find it in this entry, keep looking
- movzx ecx,WORD [es:di+4]
- add edx,ecx
-
- ; Check to see if we have reached the
- ; end of the root directory
- cmp edx,eax
- jb SearchRootDirectory
- jmp PrintFileNotFound
-
-FoundFile:
- mov eax,[es:di] ; Get inode number from directory entry
- call Ext2ReadInode ; Read in the inode
-
- ; Point ES:DI to the inode structure at 6000:8000
- pop es
- pop di ; These were saved earlier
-
- mov cx,[es:di] ; Get the file mode so we can make sure it's a regular file
- and ch,EXT2_S_IFMT ; Mask off everything but the file type
- cmp ch,EXT2_S_IFREG ; Make sure it's a regular file
- je LoadFreeLoader
- jmp PrintRegFileError
-
-LoadFreeLoader:
- mov si,msgLoading ; "Loading FreeLoader..." message
- call PutChars ; Display it
-
- call Ext2ReadEntireFile ; Read freeldr.sys to 0000:8000
-
- mov dl,[BYTE bp+BootDrive]
- mov dh,[BYTE bp+BootPartition]
- push 0 ; push segment (0x0000)
- mov eax, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
- add eax, 0x8000 ; RVA -> VA
- push ax ; push offset
- retf ; Transfer control to FreeLoader
-
-
-
-
-
-; Reads ext2 file data into [0000:8000]
-; This function assumes that the file's
-; inode has been read in to 6000:8000 *and*
-; ES:DI points to 6000:8000
-; This will load all the blocks up to
-; and including the double-indirect pointers.
-; This should be sufficient because it
-; allows for ~64MB which is much bigger
-; than we need for a boot loader.
-Ext2ReadEntireFile:
-
- ; Reset the load segment
- mov WORD [BYTE bp+Ext2ReadEntireFileLoadSegment],800h
-
- ; Now we must calculate how
- ; many blocks to read in
- ; We will do this by rounding the
- ; file size up to the next block
- ; size and then dividing by the block size
- mov eax,DWORD [BYTE bp+Ext2BlockSizeInBytes] ; Get the block size in bytes
- push eax
- dec eax ; Ext2BlockSizeInBytes -= 1
- add eax,DWORD [es:di+4] ; Add the file size
- xor edx,edx
- pop ecx ; Divide by the block size in bytes
- div ecx ; EAX now contains the number of blocks to load
- push eax
-
- ; Make sure the file size isn't zero
- cmp eax,byte 0
- jnz Ext2ReadEntireFile2
- jmp PrintFileSizeError
-
-Ext2ReadEntireFile2:
- ; Save the indirect & double indirect pointers
- mov edx,DWORD [es:di+0x58] ; Get indirect pointer
- mov [BYTE bp+Ext2InodeIndirectPointer],edx ; Save indirect pointer
- mov edx,DWORD [es:di+0x5c] ; Get double indirect pointer
- mov [BYTE bp+Ext2InodeDoubleIndirectPointer],edx ; Save double indirect pointer
-
- ; Now copy the direct pointers to 7000:0000
- ; so that we can call Ext2ReadDirectBlocks
- push ds ; Save DS
- push es
- push WORD 7000h
- pop es
- pop ds
- mov si,8028h
- xor di,di ; DS:SI = 6000:8028 ES:DI = 7000:0000
- mov cx,24 ; Moving 24 words of data
- rep movsw
- pop ds ; Restore DS
-
- ; Now we have all the block pointers in the
- ; right location so read them in
- pop eax ; Restore the total number of blocks in this file
- xor ecx,ecx ; Set the max count of blocks to read to 12
- mov cl,12 ; which is the number of direct block pointers in the inode
- call Ext2ReadDirectBlockList
-
- ; Check to see if we actually have
- ; blocks left to read
- cmp eax,byte 0
- jz Ext2ReadEntireFileDone
-
- ; Now we have read all the direct blocks in
- ; the inode. So now we have to read the indirect
- ; block and read all it's direct blocks
- push eax ; Save the total block count
- mov eax,DWORD [BYTE bp+Ext2InodeIndirectPointer] ; Get the indirect block pointer
- push WORD 7000h
- pop es
- xor bx,bx ; Set the load address to 7000:0000
- call Ext2ReadBlock ; Read the block
-
- ; Now we have all the block pointers from the
- ; indirect block in the right location so read them in
- pop eax ; Restore the total block count
- mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
- call Ext2ReadDirectBlockList
-
- ; Check to see if we actually have
- ; blocks left to read
- cmp eax,byte 0
- jz Ext2ReadEntireFileDone
-
- ; Now we have read all the direct blocks from
- ; the inode's indirect block pointer. So now
- ; we have to read the double indirect block
- ; and read all it's indirect blocks
- ; (whew, it's a good thing I don't support triple indirect blocks)
- mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
- mov eax,DWORD [BYTE bp+Ext2InodeDoubleIndirectPointer] ; Get the double indirect block pointer
- push WORD 7800h
- pop es
- push es ; Save an extra copy of this value on the stack
- xor bx,bx ; Set the load address to 7000:8000
- call Ext2ReadBlock ; Read the block
-
- pop es ; Put 7800h into ES (saved on the stack already)
- xor di,di
-
-Ext2ReadIndirectBlock:
- mov eax,DWORD [es:di] ; Get indirect block pointer
- add di,BYTE 4 ; Update DI for next array index
- push es
- push di
-
- push WORD 7000h
- pop es
- xor bx,bx ; Set the load address to 7000:0000
- call Ext2ReadBlock ; Read the indirect block
-
- ; Now we have all the block pointers from the
- ; indirect block in the right location so read them in
- mov eax,DWORD [BYTE bp+Ext2BlocksLeftToRead] ; Restore the total block count
- mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
- call Ext2ReadDirectBlockList
- mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
- pop di
- pop es
-
- ; Check to see if we actually have
- ; blocks left to read
- cmp eax,byte 0
- jnz Ext2ReadIndirectBlock
-
-Ext2ReadEntireFileDone:
- ret
-
-; Reads a maximum number of blocks
-; from an array at 7000:0000
-; and updates the total count
-; ECX contains the max number of blocks to read
-; EAX contains the number of blocks left to read
-; On return:
-; EAX contains the new number of blocks left to read
-Ext2ReadDirectBlockList:
- cmp eax,ecx ; Compare it to the maximum number of blocks to read
- ja CallExt2ReadDirectBlocks ; If it will take more blocks then just read all of the blocks
- mov cx,ax ; Otherwise adjust the block count accordingly
-
-CallExt2ReadDirectBlocks:
- sub eax,ecx ; Subtract the number of blocks being read from the total count
- push eax ; Save the new total count
- call Ext2ReadDirectBlocks
- pop eax ; Restore the total count
- ret
-
-
-; Reads a specified number of blocks
-; from an array at 7000:0000
-; CX contains the number of blocks to read
-Ext2ReadDirectBlocks:
-
- push WORD 7000h
- pop es
- xor di,di ; Set ES:DI = 7000:0000
-
-Ext2ReadDirectBlocksLoop:
- mov eax,[es:di] ; Get direct block pointer from array
- add di,BYTE 4 ; Update DI for next array index
-
- push cx ; Save number of direct blocks left
- push es ; Save array segment
- push di ; Save array offset
- mov es,[BYTE bp+Ext2ReadEntireFileLoadSegment]
- xor bx,bx ; Setup load address for next read
-
- call Ext2ReadBlock ; Read the block (this updates ES for the next read)
-
- mov [BYTE bp+Ext2ReadEntireFileLoadSegment],es ; Save updated ES
-
- pop di ; Restore the array offset
- pop es ; Restore the array segment
- pop cx ; Restore the number of blocks left
-
- loop Ext2ReadDirectBlocksLoop
-
- ; At this point all the direct blocks should
- ; be loaded and ES (Ext2ReadEntireFileLoadSegment)
- ; should be ready for the next read.
- ret
-
-
-
-; Displays a file not found error message
-; And reboots
-PrintFileNotFound:
- mov si,msgFreeLdr ; FreeLdr not found message
- jmp short DisplayItAndReboot
-
-; Displays a file size is 0 error
-; And reboots
-PrintFileSizeError:
- mov si,msgFileSize ; Error message
- jmp short DisplayItAndReboot
-
-; Displays a file is not a regular file error
-; And reboots
-PrintRegFileError:
- mov si,msgRegFile ; Error message
-DisplayItAndReboot:
- call PutChars ; Display it
- jmp Reboot
-
-msgFreeLdr db 'freeldr.sys not found',0
-msgFileSize db 'File size is 0',0
-msgRegFile db 'freeldr.sys isnt a regular file',0
-filename db 'freeldr.sys'
-msgLoading db 'Loading FreeLoader...',0
-
- times 1022-($-$$) db 0 ; Pad to 1022 bytes
-
- dw 0aa55h ; BootSector signature
+++ /dev/null
-; FAT.ASM
-; FAT12/16 Boot Sector
-; Copyright (c) 1998, 2001, 2002 Brian Palmer
-
-
-
-; This is a FAT12/16 file system boot sector
-; that searches the entire root directory
-; for the file freeldr.sys and loads it into
-; memory.
-;
-; The stack is set to 0000:7BF2 so that the first
-; WORD pushed will be placed at 0000:7BF0
-;
-; The DWORD at 0000:7BFC or BP-04h is the logical
-; sector number of the start of the data area.
-;
-; The DWORD at 0000:7BF8 or BP-08h is the total
-; sector count of the boot drive as reported by
-; the computers bios.
-;
-; The WORD at 0000:7BF6 or BP-0ah is the offset
-; of the ReadSectors function in the boot sector.
-;
-; The WORD at 0000:7BF4 or BP-0ch is the offset
-; of the ReadCluster function in the boot sector.
-;
-; The WORD at 0000:7BF2 or BP-0eh is the offset
-; of the PutChars function in the boot sector.
-;
-; When it locates freeldr.sys on the disk it will
-; load the first sector of the file to 0000:F800
-; With the help of this sector we should be able
-; to load the entire file off the disk, no matter
-; how fragmented it is.
-;
-; We load the entire FAT table into memory at
-; 7000:0000. This improves the speed of floppy disk
-; boots dramatically.
-
-
-BootSectorStackTop equ 0x7bf2
-DataAreaStartHigh equ 0x2
-DataAreaStartLow equ 0x4
-BiosCHSDriveSizeHigh equ 0x6
-BiosCHSDriveSizeLow equ 0x8
-BiosCHSDriveSize equ 0x8
-ReadSectorsOffset equ 0xa
-ReadClusterOffset equ 0xc
-PutCharsOffset equ 0xe
-
-
-org 7c00h
-
-segment .text
-
-bits 16
-
-start:
- jmp short main
- nop
-
-OEMName db 'FrLdr1.0'
-BytesPerSector dw 512
-SectsPerCluster db 1
-ReservedSectors dw 1
-NumberOfFats db 2
-MaxRootEntries dw 224
-TotalSectors dw 2880
-MediaDescriptor db 0f0h
-SectorsPerFat dw 9
-SectorsPerTrack dw 18
-NumberOfHeads dw 2
-HiddenSectors dd 0
-TotalSectorsBig dd 0
-BootDrive db 0xff
-Reserved db 0
-ExtendSig db 29h
-SerialNumber dd 00000000h
-VolumeLabel db 'NO NAME '
-FileSystem db 'FAT12 '
-
-main:
- xor ax,ax
- mov ss,ax
- mov bp,7c00h
- mov sp,BootSectorStackTop ; Setup a stack
- mov ds,ax ; Make DS correct
- mov es,ax ; Make ES correct
-
-
- cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
- jne GetDriveParameters
-
- mov [BYTE bp+BootDrive],dl ; Save the boot drive
-
-
-GetDriveParameters:
- mov ah,08h
- mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
- int 13h ; Request drive parameters from the bios
- jnc CalcDriveSize ; If the call succeeded then calculate the drive size
-
- ; If we get here then the call to the BIOS failed
- ; so just set CHS equal to the maximum addressable
- ; size
- mov cx,0ffffh
- mov dh,cl
-
-CalcDriveSize:
- ; Now that we have the drive geometry
- ; lets calculate the drive size
- mov bl,ch ; Put the low 8-bits of the cylinder count into BL
- mov bh,cl ; Put the high 2-bits in BH
- shr bh,6 ; Shift them into position, now BX contains the cylinder count
- and cl,3fh ; Mask off cylinder bits from sector count
- ; CL now contains sectors per track and DH contains head count
- movzx eax,dh ; Move the heads into EAX
- movzx ebx,bx ; Move the cylinders into EBX
- movzx ecx,cl ; Move the sectors per track into ECX
- inc eax ; Make it one based because the bios returns it zero based
- inc ebx ; Make the cylinder count one based also
- mul ecx ; Multiply heads with the sectors per track, result in edx:eax
- mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
-
- ; We now have the total number of sectors as reported
- ; by the bios in eax, so store it in our variable
- mov [BYTE bp-BiosCHSDriveSize],eax
-
-
- ; Now we must find our way to the first sector of the root directory
- xor ax,ax
- xor cx,cx
- mov al,[BYTE bp+NumberOfFats] ; Number of fats
- mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
- add ax,WORD [BYTE bp+HiddenSectors]
- adc dx,WORD [BYTE bp+HiddenSectors+2] ; Add the number of hidden sectors
- add ax,WORD [BYTE bp+ReservedSectors] ; Add the number of reserved sectors
- adc dx,cx ; Add carry bit
- mov WORD [BYTE bp-DataAreaStartLow],ax ; Save the starting sector of the root directory
- mov WORD [BYTE bp-DataAreaStartHigh],dx ; Save it in the first 4 bytes before the boot sector
- mov si,WORD [BYTE bp+MaxRootEntries] ; Get number of root dir entries in SI
- pusha ; Save 32-bit logical start sector of root dir
- ; DX:AX now has the number of the starting sector of the root directory
-
- ; Now calculate the size of the root directory
- xor dx,dx
- mov ax,0020h ; Size of dir entry
- mul si ; Times the number of entries
- mov bx,[BYTE bp+BytesPerSector]
- add ax,bx
- dec ax
- div bx ; Divided by the size of a sector
- ; AX now has the number of root directory sectors
-
- add [BYTE bp-DataAreaStartLow],ax ; Add the number of sectors of the root directory to our other value
- adc [BYTE bp-DataAreaStartHigh],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
- popa ; Restore root dir logical sector start to DX:AX
-
-LoadRootDirSector:
- mov bx,7e0h ; We will load the root directory sector
- mov es,bx ; Right after the boot sector in memory
- xor bx,bx ; We will load it to [0000:7e00h]
- xor cx,cx ; Zero out CX
- inc cx ; Now increment it to 1, we are reading one sector
- xor di,di ; Zero out di
- push es ; Save ES because it will get incremented by 20h
- call ReadSectors ; Read the first sector of the root directory
- pop es ; Restore ES (ES:DI = 07E0:0000)
-
-SearchRootDirSector:
- cmp [es:di],ch ; If the first byte of the directory entry is zero then we have
- jz ErrBoot ; reached the end of the directory and FREELDR.SYS is not here so reboot
- pusha ; Save all registers
- mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
- mov si,filename ; Put offset of filename string in DS:SI
- repe cmpsb ; Compare this directory entry against 'FREELDR SYS'
- popa ; Restore all the registers
- jz FoundFreeLoader ; If we found it then jump
- dec si ; SI holds MaxRootEntries, subtract one
- jz ErrBoot ; If we are out of root dir entries then reboot
- add di,BYTE +0x20 ; Increment DI by the size of a directory entry
- cmp di,0200h ; Compare DI to 512 (DI has offset to next dir entry, make sure we haven't gone over one sector)
- jc SearchRootDirSector ; If DI is less than 512 loop again
- jmp short LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again
-
-FoundFreeLoader:
- ; We found freeldr.sys on the disk
- ; so we need to load the first 512
- ; bytes of it to 0000:F800
- ; ES:DI has dir entry (ES:DI == 07E0:XXXX)
- mov ax,WORD [es:di+1ah] ; Get start cluster
- push ax ; Save start cluster
- push WORD 0F80h ; FREELDR_BASE / 16 ; Put load segment on the stack and load it
- pop es ; Into ES so that we load the cluster at 0000:F800
- call ReadCluster ; Read the cluster
- pop ax ; Restore start cluster of FreeLoader
-
- ; Save the addresses of needed functions so
- ; the helper code will know where to call them.
- mov WORD [BYTE bp-ReadSectorsOffset],ReadSectors ; Save the address of ReadSectors
- mov WORD [BYTE bp-ReadClusterOffset],ReadCluster ; Save the address of ReadCluster
- mov WORD [BYTE bp-PutCharsOffset],PutChars ; Save the address of PutChars
-
- ; Now AX has start cluster of FreeLoader and we
- ; have loaded the helper code in the first 512 bytes
- ; of FreeLoader to 0000:F800. Now transfer control
- ; to the helper code. Skip the first three bytes
- ; because they contain a jump instruction to skip
- ; over the helper code in the FreeLoader image.
- ;ljmp16 0, FREELDR_BASE + 3
- db 0EAh
- dw 0F803h
- dw 0
-
-
-
-
-; Displays an error message
-; And reboots
-ErrBoot:
- mov si,msgFreeLdr ; FreeLdr not found message
- call PutChars ; Display it
-
-Reboot:
- ; mov si,msgAnyKey ; Press any key message
- ; call PutChars ; Display it
- xor ax,ax
- int 16h ; Wait for a keypress
- int 19h ; Reboot
-
-PutChars:
- lodsb
- or al,al
- jz short Done
- mov ah,0eh
- mov bx,07h
- int 10h
- jmp short PutChars
-Done:
- retn
-
-; Displays a bad boot message
-; And reboots
-BadBoot:
- mov si,msgDiskError ; Bad boot disk message
- call PutChars ; Display it
-
- jmp short Reboot
-
-
-; Reads cluster number in AX into [ES:0000]
-ReadCluster:
- ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
- dec ax ; Adjust start cluster by 2
- dec ax ; Because the data area starts on cluster 2
- xor ch,ch
- mov cl,BYTE [BYTE bp+SectsPerCluster]
- mul cx ; Times sectors per cluster
- add ax,[BYTE bp-DataAreaStartLow] ; Add start of data area
- adc dx,[BYTE bp-DataAreaStartHigh] ; Now we have DX:AX with the logical start sector of FREELDR.SYS
- xor bx,bx ; We will load it to [ES:0000], ES loaded before function call
- ;mov cl,BYTE [BYTE bp+SectsPerCluster]; Sectors per cluster still in CX
- ;call ReadSectors
- ;ret
-
-
-
-; Reads logical sectors into [ES:BX]
-; DX:AX has logical sector number to read
-; CX has number of sectors to read
-ReadSectors:
-
- ; We can't just check if the start sector is
- ; in the BIOS CHS range. We have to check if
- ; the start sector + length is in that range.
- pusha
- dec cx
- add ax,cx
- adc dx,byte 0
-
- cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh] ; Check if they are reading a sector within CHS range
- ja ReadSectorsLBA ; No - go to the LBA routine
- jb ReadSectorsCHS ; Yes - go to the old CHS routine
- cmp ax,WORD [BYTE bp-BiosCHSDriveSizeLow] ; Check if they are reading a sector within CHS range
- jbe ReadSectorsCHS ; Yes - go to the old CHS routine
-
-ReadSectorsLBA:
- popa
-ReadSectorsLBALoop:
- pusha ; Save logical sector number & sector count
-
- o32 push byte 0
- push dx ; Put 64-bit logical
- push ax ; block address on stack
- push es ; Put transfer segment on stack
- push bx ; Put transfer offset on stack
- push byte 1 ; Set transfer count to 1 sector
- push byte 0x10 ; Set size of packet to 10h
- mov si,sp ; Setup disk address packet on stack
-
-; We are so totally out of space here that I am forced to
-; comment out this very beautifully written piece of code
-; It would have been nice to have had this check...
-;CheckInt13hExtensions: ; Now make sure this computer supports extended reads
-; mov ah,0x41 ; AH = 41h
-; mov bx,0x55aa ; BX = 55AAh
-; mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
-; int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
-; jc PrintDiskError ; CF set on error (extensions not supported)
-; cmp bx,0xaa55 ; BX = AA55h if installed
-; jne PrintDiskError
-; test cl,1 ; CX = API subset support bitmap
-; jz PrintDiskError ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
-
-
- ; Good, we're here so the computer supports LBA disk access
- ; So finish the extended read
- mov dl,[BYTE bp+BootDrive] ; Drive number
- mov ah,42h ; Int 13h, AH = 42h - Extended Read
- int 13h ; Call BIOS
- jc BadBoot ; If the read failed then abort
-
- add sp,byte 0x10 ; Remove disk address packet from stack
-
- popa ; Restore sector count & logical sector number
-
- inc ax ; Increment Sector to Read
- adc dx,byte 0
-
- push bx
- mov bx,es
- add bx,byte 20h ; Increment read buffer for next sector
- mov es,bx
- pop bx
-
- loop ReadSectorsLBALoop ; Read next sector
-
- ret
-
-
-; Reads logical sectors into [ES:BX]
-; DX:AX has logical sector number to read
-; CX has number of sectors to read
-; CarryFlag set on error
-ReadSectorsCHS:
- popa
-ReadSectorsCHSLoop:
- pusha
- xchg ax,cx
- xchg ax,dx
- xor dx,dx
- div WORD [BYTE bp+SectorsPerTrack]
- xchg ax,cx
- div WORD [BYTE bp+SectorsPerTrack] ; Divide logical by SectorsPerTrack
- inc dx ; Sectors numbering starts at 1 not 0
- xchg cx,dx
- div WORD [BYTE bp+NumberOfHeads] ; Number of heads
- mov dh,dl ; Head to DH, drive to DL
- mov dl,[BYTE bp+BootDrive] ; Drive number
- mov ch,al ; Cylinder in CX
- ror ah,2 ; Low 8 bits of cylinder in CH, high 2 bits
- ; in CL shifted to bits 6 & 7
- or cl,ah ; Or with sector number
- mov ax,0201h
- int 13h ; DISK - READ SECTORS INTO MEMORY
- ; AL = number of sectors to read, CH = track, CL = sector
- ; DH = head, DL = drive, ES:BX -> buffer to fill
- ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
-
- jc BadBoot
-
- popa
- inc ax ;Increment Sector to Read
- jnz NoCarryCHS
- inc dx
-
-
-NoCarryCHS:
- push bx
- mov bx,es
- add bx,byte 20h
- mov es,bx
- pop bx
- ; Increment read buffer for next sector
- loop ReadSectorsCHSLoop ; Read next sector
-
- ret
-
-
-msgDiskError db 'Disk error',0dh,0ah,0
-msgFreeLdr db 'Ldr not found',0dh,0ah,0
-; Sorry, need the space...
-;msgAnyKey db 'Press any key to restart',0dh,0ah,0
-;msgAnyKey db 'Press a key',0dh,0ah,0
-filename db 'FREELDR SYS'
-
- times 509-($-$$) db 0 ; Pad to 509 bytes
-
-BootPartition:
- db 0
-
-BootSignature:
- dw 0aa55h ; BootSector signature
+++ /dev/null
-; FAT32.ASM
-; FAT32 Boot Sector
-; Copyright (c) 1998, 2000, 2001, 2002 Brian Palmer
-
-org 7c00h
-
-segment .text
-
-bits 16
-
-start:
- jmp short main
- nop
-
-OEMName db 'FrLdr1.0'
-BytesPerSector dw 512
-SectsPerCluster db 0
-ReservedSectors dw 32
-NumberOfFats db 2
-MaxRootEntries dw 0 ; Always zero for FAT32 volumes
-TotalSectors dw 0 ; Always zero for FAT32 volumes
-MediaDescriptor db 0f8h
-SectorsPerFat dw 0 ; Always zero for FAT32 volumes
-SectorsPerTrack dw 0
-NumberOfHeads dw 0
-HiddenSectors dd 0
-TotalSectorsBig dd 0
-; FAT32 Inserted Info
-SectorsPerFatBig dd 0
-ExtendedFlags dw 0
-FSVersion dw 0
-RootDirStartCluster dd 0
-FSInfoSector dw 0
-BackupBootSector dw 6
-Reserved1 times 12 db 0
-; End FAT32 Inserted Info
-BootDrive db 0
-Reserved db 0
-ExtendSig db 29h
-SerialNumber dd 00000000h
-VolumeLabel db 'NO NAME '
-FileSystem db 'FAT32 '
-
-main:
- xor ax,ax ; Setup segment registers
- mov ds,ax ; Make DS correct
- mov es,ax ; Make ES correct
- mov ss,ax ; Make SS correct
- mov bp,7c00h
- mov sp,7c00h ; Setup a stack
-
-
-
- cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
- jne CheckSectorsPerFat
-
- mov [BYTE bp+BootDrive],dl ; Save the boot drive
-
-
-
-CheckSectorsPerFat:
- cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat
- jnz CheckFailed ; If it is non-zero then exit with an error
-CheckTotalSectors: ; Check the old 16-bit value of TotalSectors & MaxRootEntries
- cmp DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero
- jnz CheckFailed ; If it is non-zero then exit with an error
-CheckFileSystemVersion:
- cmp WORD [BYTE bp+FSVersion],byte 0x00 ; Check the file system version word
- jna GetDriveParameters ; It is zero, so continue
-CheckFailed:
- jmp PrintFileSystemError ; If it is not zero then exit with an error
-
-
-GetDriveParameters:
- mov ax,0800h
- mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
- int 13h ; Request drive parameters from the bios
- jnc CalcDriveSize ; If the call succeeded then calculate the drive size
-
- ; If we get here then the call to the BIOS failed
- ; so just set CHS equal to the maximum addressable
- ; size
- mov cx,0ffffh
- mov dh,cl
-
-CalcDriveSize:
- ; Now that we have the drive geometry
- ; lets calculate the drive size
- mov bl,ch ; Put the low 8-bits of the cylinder count into BL
- mov bh,cl ; Put the high 2-bits in BH
- shr bh,6 ; Shift them into position, now BX contains the cylinder count
- and cl,3fh ; Mask off cylinder bits from sector count
- ; CL now contains sectors per track and DH contains head count
- movzx eax,dh ; Move the heads into EAX
- movzx ebx,bx ; Move the cylinders into EBX
- movzx ecx,cl ; Move the sectors per track into ECX
- inc eax ; Make it one based because the bios returns it zero based
- inc ebx ; Make the cylinder count one based also
- mul ecx ; Multiply heads with the sectors per track, result in edx:eax
- mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
-
- ; We now have the total number of sectors as reported
- ; by the bios in eax, so store it in our variable
- mov [BiosCHSDriveSize],eax
-
-
-LoadExtraBootCode:
- ; First we have to load our extra boot code at
- ; sector 14 into memory at [0000:7e00h]
- mov eax,0eh
- add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
- mov cx,1
- xor bx,bx
- mov es,bx ; Read sector to [0000:7e00h]
- mov bx,7e00h
- call ReadSectors
- jmp StartSearch
-
-
-
-; Reads logical sectors into [ES:BX]
-; EAX has logical sector number to read
-; CX has number of sectors to read
-ReadSectors:
- push es
- cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
- jae ReadSectorsLBA ; Yes - go to the LBA routine
- ; If at all possible we want to use LBA routines because
- ; They are optimized to read more than 1 sector per read
-
- pushad ; Save logical sector number & sector count
-
-CheckInt13hExtensions: ; Now check if this computer supports extended reads
- mov ah,0x41 ; AH = 41h
- mov bx,0x55aa ; BX = 55AAh
- mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
- int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
- jc ReadSectorsCHS ; CF set on error (extensions not supported)
- cmp bx,0xaa55 ; BX = AA55h if installed
- jne ReadSectorsCHS
- test cl,1 ; CX = API subset support bitmap
- jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
-
- popad ; Restore sector count & logical sector number
-
-ReadSectorsLBA:
- pushad ; Save logical sector number & sector count
-
- cmp cx,64 ; Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
- jbe ReadSectorsSetupDiskAddressPacket ; If we are reading less than 65 sectors then just do the read
- mov cx,64 ; Otherwise read only 64 sectors on this loop iteration
-
-ReadSectorsSetupDiskAddressPacket:
- mov [LBASectorsRead],cx
- o32 push byte 0
- push eax ; Put 64-bit logical block address on stack
- push es ; Put transfer segment on stack
- push bx ; Put transfer offset on stack
- push cx ; Set transfer count
- push byte 0x10 ; Set size of packet to 10h
- mov si,sp ; Setup disk address packet on stack
-
-
- mov dl,[BYTE bp+BootDrive] ; Drive number
- mov ah,42h ; Int 13h, AH = 42h - Extended Read
- int 13h ; Call BIOS
- jc PrintDiskError ; If the read failed then abort
-
- add sp,byte 0x10 ; Remove disk address packet from stack
-
- popad ; Restore sector count & logical sector number
-
- push bx
- mov ebx,DWORD [LBASectorsRead]
- add eax,ebx ; Increment sector to read
- shl ebx,5
- mov dx,es
- add dx,bx ; Setup read buffer for next sector
- mov es,dx
- pop bx
-
- sub cx,[LBASectorsRead]
- jnz ReadSectorsLBA ; Read next sector
-
- pop es
- ret
-
-LBASectorsRead:
- dd 0
-
-
-; Reads logical sectors into [ES:BX]
-; EAX has logical sector number to read
-; CX has number of sectors to read
-ReadSectorsCHS:
- popad ; Get logical sector number & sector count off stack
-
-ReadSectorsCHSLoop:
- pushad
- xor edx,edx
- movzx ecx,WORD [BYTE bp+SectorsPerTrack]
- div ecx ; Divide logical by SectorsPerTrack
- inc dl ; Sectors numbering starts at 1 not 0
- mov cl,dl ; Sector in CL
- mov edx,eax
- shr edx,16
- div WORD [BYTE bp+NumberOfHeads] ; Divide logical by number of heads
- mov dh,dl ; Head in DH
- mov dl,[BYTE bp+BootDrive] ; Drive number in DL
- mov ch,al ; Cylinder in CX
- ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
- ror ah,1 ; in CL shifted to bits 6 & 7
- or cl,ah ; Or with sector number
- mov ax,0201h
- int 13h ; DISK - READ SECTORS INTO MEMORY
- ; AL = number of sectors to read, CH = track, CL = sector
- ; DH = head, DL = drive, ES:BX -> buffer to fill
- ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
-
- jc PrintDiskError ; If the read failed then abort
-
- popad
-
- inc eax ; Increment Sector to Read
-
- mov dx,es
- add dx,byte 20h ; Increment read buffer for next sector
- mov es,dx
-
- loop ReadSectorsCHSLoop ; Read next sector
-
- ret
-
-
-
-
-; Displays a disk error message
-; And reboots
-PrintDiskError:
- mov si,msgDiskError ; Bad boot disk message
- call PutChars ; Display it
-
- jmp Reboot
-
-; Displays a file system error message
-; And reboots
-PrintFileSystemError:
- mov si,msgFileSystemError ; FreeLdr not found message
- call PutChars ; Display it
-
-Reboot:
- mov si,msgAnyKey ; Press any key message
- call PutChars ; Display it
- xor ax,ax
- int 16h ; Wait for a keypress
- int 19h ; Reboot
-
-PutChars:
- lodsb
- or al,al
- jz short Done
- mov ah,0eh
- mov bx,07h
- int 10h
- jmp short PutChars
-Done:
- retn
-
-
-
-BiosCHSDriveSize dd 0
-
-msgDiskError db 'Disk error',0dh,0ah,0
-msgFileSystemError db 'File system error',0dh,0ah,0
-msgAnyKey db 'Press any key to restart',0dh,0ah,0
-
- times 509-($-$$) db 0 ; Pad to 509 bytes
-
-BootPartition:
- db 0
-
-BootSignature:
- dw 0aa55h ; BootSector signature
-
-
-; End of bootsector
-;
-; Now starts the extra boot code that we will store
-; at sector 14 on a FAT32 volume
-;
-; To remain multi-boot compatible with other operating
-; systems we must not overwrite anything other than
-; the bootsector which means we will have to use
-; a different sector like 14 to store our extra boot code
-
-
-
-StartSearch:
- ; Now we must get the first cluster of the root directory
- mov eax,DWORD [BYTE bp+RootDirStartCluster]
- cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
- jb ContinueSearch ; If not continue, if so then we didn't find freeldr.sys
- jmp PrintFileNotFound
-ContinueSearch:
- mov bx,2000h
- mov es,bx ; Read cluster to [2000:0000h]
- call ReadCluster ; Read the cluster
-
-
- ; Now we have to find our way through the root directory to
- ; The FREELDR.SYS file
- xor bx,bx
- mov bl,[BYTE bp+SectsPerCluster]
- shl bx,4 ; BX = BX * 512 / 32
- mov ax,2000h ; We loaded at 2000:0000
- mov es,ax
- xor di,di
- mov si,filename
- mov cx,11
- rep cmpsb ; Compare filenames
- jz FoundFile ; If same we found it
- dec bx
- jnz FindFile
- jmp PrintFileNotFound
-
-FindFile:
- mov ax,es ; We didn't find it in the previous dir entry
- add ax,2 ; So lets move to the next one
- mov es,ax ; And search again
- xor di,di
- mov si,filename
- mov cx,11
- rep cmpsb ; Compare filenames
- jz FoundFile ; If same we found it
- dec bx ; Keep searching till we run out of dir entries
- jnz FindFile ; Last entry?
-
- ; Get the next root dir cluster and try again until we run out of clusters
- mov eax,DWORD [BYTE bp+RootDirStartCluster]
- call GetFatEntry
- mov [BYTE bp+RootDirStartCluster],eax
- jmp StartSearch
-
-FoundFile:
- ; Display "Loading FreeLoader..." message
- mov si,msgLoading ; Loading message
- call PutChars ; Display it
-
- xor di,di ; ES:DI has dir entry
- xor dx,dx
- mov ax,WORD [es:di+14h] ; Get start cluster high word
- shl eax,16
- mov ax,WORD [es:di+1ah] ; Get start cluster low word
-
-CheckStartCluster:
- cmp eax,2 ; Check and see if the start cluster starts at cluster 2 or above
- jnb CheckEndCluster ; If so then continue
- jmp PrintFileSystemError ; If not exit with error
-CheckEndCluster:
- cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator
- jb InitializeLoadSegment ; If not then continue
- jmp PrintFileSystemError ; If so exit with error
-
-InitializeLoadSegment:
- mov bx,0F80h ; FREELDR_BASE / 16
- mov es,bx
-
-LoadFile:
- cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
- jae LoadFileDone ; If so continue, if not then read the next one
- push eax
- xor bx,bx ; Load ROSLDR starting at 0000:F800h
- push es
- call ReadCluster
- pop es
-
- xor bx,bx
- mov bl,[BYTE bp+SectsPerCluster]
- shl bx,5 ; BX = BX * 512 / 16
- mov ax,es ; Increment the load address by
- add ax,bx ; The size of a cluster
- mov es,ax
-
- pop eax
- push es
- call GetFatEntry ; Get the next entry
- pop es
-
- jmp LoadFile ; Load the next cluster (if any)
-
-LoadFileDone:
- mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
- mov dh,[BootPartition] ; Load boot partition into DH
-
- ; Transfer execution to the bootloader
- ;ljmp16 0, FREELDR_BASE
- db 0EAh
- dw 0F800h
- dw 0
-
-; Returns the FAT entry for a given cluster number
-; On entry EAX has cluster number
-; On return EAX has FAT entry for that cluster
-GetFatEntry:
-
- shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
- mov ecx,eax ; Save this for later in ECX
- xor edx,edx
- movzx ebx,WORD [BYTE bp+BytesPerSector]
- push ebx
- div ebx ; FAT Sector Number = EAX / BytesPerSector
- movzx ebx,WORD [BYTE bp+ReservedSectors]
- add eax,ebx ; FAT Sector Number += ReservedSectors
- mov ebx,DWORD [BYTE bp+HiddenSectors]
- add eax,ebx ; FAT Sector Number += HiddenSectors
- pop ebx
- dec ebx
- and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
- ; EAX holds logical FAT sector number
- ; ECX holds FAT entry offset
-
- ; Now we have to check the extended flags
- ; to see which FAT is the active one
- ; and use it, or if they are mirrored then
- ; no worries
- movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx
- and bx,0x0f ; Mask off upper 8 bits, now we have active fat in bl
- jz LoadFatSector ; If fat is mirrored then skip fat calcs
- cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats
- jb GetActiveFatOffset
- jmp PrintFileSystemError ; If bl is bigger than numfats exit with error
-GetActiveFatOffset:
- push eax ; Save logical FAT sector number
- mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
- mul ebx ; Multiplied by the active FAT index we have in ebx
- pop edx ; Get logical FAT sector number
- add eax,edx ; Add the current FAT sector offset
-
-LoadFatSector:
- push ecx
-
- mov bx, 9000h ; We will load it to [9000:0000h]
- mov es, bx
-
- ; EAX holds logical FAT sector number
- ; Check if we have already loaded it
- cmp eax,DWORD [FatSectorInCache]
- je LoadFatSectorAlreadyLoaded
-
- mov DWORD [FatSectorInCache],eax
- xor bx,bx
- mov cx,1
- call ReadSectors
-
-LoadFatSectorAlreadyLoaded:
- pop ecx
- mov eax,DWORD [es:ecx] ; Get FAT entry
- and eax,0fffffffh ; Mask off reserved bits
-
- ret
-
-FatSectorInCache: ; This variable tells us which sector we currently have in memory
- dd 0ffffffffh ; There is no need to re-read the same sector if we don't have to
-
-
-; Reads cluster number in EAX into [ES:0000]
-ReadCluster:
- ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
-
- dec eax
- dec eax
- xor edx,edx
- movzx ebx,BYTE [BYTE bp+SectsPerCluster]
- mul ebx
- push eax
- xor edx,edx
- movzx eax,BYTE [BYTE bp+NumberOfFats]
- mul DWORD [BYTE bp+SectorsPerFatBig]
- movzx ebx,WORD [BYTE bp+ReservedSectors]
- add eax,ebx
- add eax,DWORD [BYTE bp+HiddenSectors]
- pop ebx
- add eax,ebx ; EAX now contains the logical sector number of the cluster
- xor bx,bx ; We will load it to [ES:0000], ES loaded before function call
- movzx cx,BYTE [BYTE bp+SectsPerCluster]
- call ReadSectors
- ret
-
-
-; Displays a file not found error message
-; And reboots
-PrintFileNotFound:
- mov si,msgFreeLdr ; FreeLdr not found message
- call PutChars ; Display it
- mov si,msgAnyKey ; Press any key message
- call PutChars ; Display it
-
- jmp Reboot
-
-msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
-filename db 'FREELDR SYS'
-msgLoading db 'Loading FreeLoader...',0dh,0ah,0
-
-
- times 1022-($-$$) db 0 ; Pad to 1022 bytes
-
- dw 0aa55h ; BootSector signature
/*
- * PROJECT: ReactOS Boot Sector for ISO file system (based on ISOLINUX)
- * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
- * PROGRAMMERS: H. Peter Anvin
- * Michael K. Ter Louw
- * Eric Kohl
- * Timo Kreuzer <timo.kreuzer@reactos.org>
- * Colin Finck <colin@reactos.org>
- *
- *****************************************************************************
- *
- * isolinux.asm
- *
- * A program to boot Linux kernels off a CD-ROM using the El Torito
- * boot standard in "no emulation" mode, making the entire filesystem
- * available. It is based on the SYSLINUX boot loader for MS-DOS
- * floppies.
- *
- * Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation *author: H. Peter Anvin
- *
- * This program is free software *you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
- * Boston MA 02111-1307, USA *either version 2 of the License, or
- * (at your option) any later version *incorporated herein by reference.
- *
- *****************************************************************************/
+ * PROJECT: ReactOS Boot Sector for ISO file system (based on ISOLINUX)
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Booting ReactOS off a CD-ROM using the El Torito boot standard in "no emulation mode"
+ * COPYRIGHT: Copyright 1994-2009 H. Peter Anvin
+ * Copyright 2002 Michael K. Ter Louw
+ * Copyright 2002 Eric Kohl
+ * Copyright 2009 Intel Corporation *author: H. Peter Anvin
+ * Copyright 2011 Timo Kreuzer (timo.kreuzer@reactos.org)
+ * Copyright 2017 Colin Finck (colin@reactos.org)
+ */
/* INCLUDES ******************************************************************/
#include <asm.inc>
+++ /dev/null
-; ****************************************************************************
-;
-; 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
+++ /dev/null
-; ****************************************************************************
-;
-; 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
-
-; 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
- 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
-
-
-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 '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
/*
* PROJECT: ReactOS MBR Boot Sector for ISO file system ("isohybrid mode")
- * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
- * COPYRIGHT: Copyright 2017 Colin Finck <colin@reactos.org>
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Providing an MBR Boot Sector that enables an ISO to be booted from a disk
+ * COPYRIGHT: Copyright 2017 Colin Finck (colin@reactos.org)
*/
#include <asm.inc>
+++ /dev/null
-;
-; Win2k FAT32 Boot Sector
-;
-; Brian Palmer <brianp@sginet.com>
-;
-
-;
-; The BP register is initialized to 0x7c00, the start of
-; the boot sector. The SP register is initialized to
-; 0x7bf4, leaving 12 bytes of data storage space above
-; the stack.
-;
-; The DWORD that gets stored at 0x7bf4 is 0xffffffff ??
-;
-; The DWORD that gets stored at 0x7bf8 is the count of
-; total sectors of the volume, calculated from the BPB.
-;
-; The DWORD that gets stored at 0x7bfc is the logical
-; sector number of the start of the data area.
-;
-
-org 7c00h
-
-segment .text
-
-bits 16
-
-start:
- jmp short main
- nop
-
-OEMName db 'MSWIN4.0'
-BytesPerSector dw 512
-SectsPerCluster db 1
-ReservedSectors dw 1
-NumberOfFats db 2
-MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
-TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
-MediaDescriptor db 0f8h
-SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
-SectorsPerTrack dw 18
-NumberOfHeads dw 2
-HiddenSectors dd 0
-TotalSectorsBig dd 0
-; FAT32 Inserted Info
-SectorsPerFatBig dd 0
-ExtendedFlags dw 0
-FSVersion dw 0
-RootDirStartCluster dd 0
-FSInfoSector dw 0
-BackupBootSector dw 6
-Reserved1 times 12 db 0
-; End FAT32 Inserted Info
-BootDrive db 80h
-Reserved db 0
-ExtendSig db 29h
-SerialNumber dd 00000000h
-VolumeLabel db 'NO NAME '
-FileSystem db 'FAT32 '
-
-main:
-00007C5A 33C9 xor cx,cx
-00007C5C 8ED1 mov ss,cx ; Setup the stack
-00007C5E BCF47B mov sp,0x7bf4 ; Give us 12 bytes of space above the stack
-00007C61 8EC1 mov es,cx
-00007C63 8ED9 mov ds,cx
-00007C65 BD007C mov bp,0x7c00
-00007C68 884E02 mov [bp+0x2],cl ; Zero out the nop instruction?? (3rd byte of the boot sector)
-00007C6B 8A5640 mov dl,[bp+BootDrive]
-00007C6E B408 mov ah,0x8
-00007C70 CD13 int 0x13 ; Int 13, func 8 - Get Drive Parameters
-00007C72 7305 jnc drive_param_ok ; If no error jmp
-
-drive_param_error:
-00007C74 B9FFFF mov cx,0xffff ; We couldn't determine the drive parameters
-00007C77 8AF1 mov dh,cl ; So just set the CHS to 0xff
-
-drive_param_ok:
-00007C79 660FB6C6 movzx eax,dh ; Store the number of heads in eax
-00007C7D 40 inc ax ; Make it one-based because the bios returns it zero-based
-00007C7E 660FB6D1 movzx edx,cl ; Store the sectors per track in edx
-00007C82 80E23F and dl,0x3f ; Mask off the cylinder bits
-00007C85 F7E2 mul dx ; Multiply the sectors per track with the heads, result in dx:ax
-00007C87 86CD xchg cl,ch ; Switch the cylinder with the sectors
-00007C89 C0ED06 shr ch,0x6 ; Move the top two cylinder bits down where they should be
-00007C8C 41 inc cx ; Make it one-based because the bios returns it zero-based
-00007C8D 660FB7C9 movzx ecx,cx
-00007C91 66F7E1 mul ecx ; Multiply the cylinders with (heads * sectors) [stored in dx:ax already]
-00007C94 668946F8 mov [bp-0x8],eax ; This value is the number of total sectors on the disk, so save it for later
-00007C98 837E1600 cmp word [bp+TotalSectors],byte +0x0 ; Check the old 16-bit value of TotalSectors
-00007C9C 7538 jnz print_ntldr_error_message ; If it is non-zero then exit with an error
-
-00007C9E 837E2A00 cmp word [bp+FSVersion],byte +0x0 ; Check the file system version word
-00007CA2 7732 ja print_ntldr_error_message ; If it is not zero then exit with an error
-
-
- ;
- ; We are now ready to load our second sector of boot code
- ; But first, a bit of undocumented information about how
- ; Win2k stores it's second sector of boot code.
- ;
- ; The FAT32 filesystem was designed so that you can store
- ; multiple sectors of boot code. The boot sector of a FAT32
- ; volume is actually three sectors long. Microsoft extended
- ; the BPB so much that you can't fit enough code in the
- ; boot sector to make it work. So they extended it. Sector 0
- ; is the traditional boot sector, sector 1 is the FSInfo sector,
- ; and sector 2 is used to store extra boot code to make up
- ; for the lost space the BPB takes.
- ;
- ; Now this creates an interesting problem. Suppose for example
- ; that the user has Win98 and Win2k installed. The Win2k
- ; boot sector is stored at sector 0 and the Win98 boot sector is
- ; stored as BOOTSECT.DOS on the file system. Now if Win2k were
- ; to store it's second sector of boot code in sector 2 like
- ; the fat spec says to do then when you try to dual boot back
- ; to Win98 the Win98 boot sector will load Win2k's second
- ; sector of boot code. Understand? ;-)
- ;
- ; To get around this problem Win2k stores it's second sector
- ; of boot code elsewhere. This sector is always stored at sector 13
- ; on the file system. Now don't ask me what happens when you don't
- ; have enough reserved sectors to store it, but I've never seen a
- ; FAT32 volume that didn't have at least 32 reserved sectors.
- ;
-
-00007CA4 668B461C mov eax,[bp+HiddenSectors] ; Get the count of hidden sectors
-00007CA8 6683C00C add eax,byte +0xc ; Add 12 to that value so that we are loading the 13th sector of the volume
-00007CAC BB0080 mov bx,0x8000 ; Read the sector to address 0x8000
-00007CAF B90100 mov cx,0x1 ; Read just one sector
-00007CB2 E82B00 call read_sectors ; Read it
-00007CB5 E94803 jmp 0x8000 ; Jump to the next sector of boot code
-
-print_disk_error_message:
-00007CB8 A0FA7D mov al,[DISK_ERR_offset_from_0x7d00]
-putchars:
-00007CBB B47D mov ah,0x7d
-00007CBD 8BF0 mov si,ax
-get_another_char:
-00007CBF AC lodsb
-00007CC0 84C0 test al,al
-00007CC2 7417 jz reboot
-00007CC4 3CFF cmp al,0xff
-00007CC6 7409 jz print_reboot_message
-00007CC8 B40E mov ah,0xe
-00007CCA BB0700 mov bx,0x7
-00007CCD CD10 int 0x10
-00007CCF EBEE jmp short get_another_char
-print_reboot_message:
-00007CD1 A0FB7D mov al,[RESTART_ERR_offset_from_0x7d00]
-00007CD4 EBE5 jmp short putchars
-print_ntldr_error_message:
-00007CD6 A0F97D mov al,[NTLDR_ERR_offset_from_0x7d00]
-00007CD9 EBE0 jmp short putchars
-reboot:
-00007CDB 98 cbw
-00007CDC CD16 int 0x16
-00007CDE CD19 int 0x19
-
-read_sectors:
-00007CE0 6660 pushad
-00007CE2 663B46F8 cmp eax,[bp-0x8]
-00007CE6 0F824A00 jc near 0x7d34
-00007CEA 666A00 o32 push byte +0x0
-00007CED 6650 push eax
-00007CEF 06 push es
-00007CF0 53 push bx
-00007CF1 666810000100 push dword 0x10010
-00007CF7 807E0200 cmp byte [bp+0x2],0x0
-00007CFB 0F852000 jnz near 0x7d1f
-00007CFF B441 mov ah,0x41
-00007D01 BBAA55 mov bx,0x55aa
-00007D04 8A5640 mov dl,[bp+BootDrive]
-00007D07 CD13 int 0x13
-00007D09 0F821C00 jc near 0x7d29
-00007D0D 81FB55AA cmp bx,0xaa55
-00007D11 0F851400 jnz near 0x7d29
-00007D15 F6C101 test cl,0x1
-00007D18 0F840D00 jz near 0x7d29
-00007D1C FE4602 inc byte [bp+0x2]
-00007D1F B442 mov ah,0x42
-00007D21 8A5640 mov dl,[bp+BootDrive]
-00007D24 8BF4 mov si,sp
-00007D26 CD13 int 0x13
-00007D28 B0F9 mov al,0xf9
-00007D2A 6658 pop eax
-00007D2C 6658 pop eax
-00007D2E 6658 pop eax
-00007D30 6658 pop eax
-00007D32 EB2A jmp short 0x7d5e
-00007D34 6633D2 xor edx,edx
-00007D37 660FB74E18 movzx ecx,word [bp+SectorsPerTrack]
-00007D3C 66F7F1 div ecx
-00007D3F FEC2 inc dl
-00007D41 8ACA mov cl,dl
-00007D43 668BD0 mov edx,eax
-00007D46 66C1EA10 shr edx,0x10
-00007D4A F7761A div word [bp+NumberOfHeads]
-00007D4D 86D6 xchg dl,dh
-00007D4F 8A5640 mov dl,[bp+BootDrive]
-00007D52 8AE8 mov ch,al
-00007D54 C0E406 shl ah,0x6
-00007D57 0ACC or cl,ah
-00007D59 B80102 mov ax,0x201
-00007D5C CD13 int 0x13
-00007D5E 6661 popad
-00007D60 0F8254FF jc near print_disk_error_message
-00007D64 81C30002 add bx,0x200
-00007D68 6640 inc eax
-00007D6A 49 dec cx
-00007D6B 0F8571FF jnz near read_sectors
-00007D6F C3 ret
-
-NTLDR db 'NTLDR '
-
-filler times 49 db 0
-
-NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
-DISK_ERR db 0dh,0ah,'Disk error',0ffh
-RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
-
-more_filler times 16 db 0
-
-NTLDR_offset_from_0x7d00 db 0
-NTLDR_ERR_offset_from_0x7d00 db 0ach
-DISK_ERR_offset_from_0x7d00 db 0bfh
-RESTART_ERR_offset_from_0x7d00 db 0cch
-
- dw 0
- dw 0aa55h
-
-
-
-
-
-
-;
-; And that ends the code that makes up the traditional boot sector
-; From here on out is a disassembly of the extra sector of boot
-; code required for a FAT32 volume. Win2k stores this code at
-; sector 13 on the file system.
-;
-
-
-
-
-00008000 660FB64610 movzx eax,byte [bp+NumberOfFats] ; Put the number of fats into eax
-00008005 668B4E24 mov ecx,[bp+SectorsPerFatBig] ; Put the count of sectors per fat into ecx
-00008009 66F7E1 mul ecx ; Multiply them, edx:eax = (eax * ecx)
-0000800C 6603461C add eax,[bp+HiddenSectors] ; Add the hidden sectors to eax
-00008010 660FB7560E movzx edx,word [bp+ReservedSectors] ; Put the count of reserved sectors into edx
-00008015 6603C2 add eax,edx ; Add it to eax
-00008018 668946FC mov [bp-0x4],eax ; eax now contains the start of the data area, so save it for later
-0000801C 66C746F4FFFFFFFF mov dword [bp-0xc],0xffffffff ; Save 0xffffffff for later??
-00008024 668B462C mov eax,[bp+RootDirStartCluster] ; Put the starting cluster of the root directory into eax
-00008028 6683F802 cmp eax,byte +0x2 ; Check and see if the root directory starts at cluster 2 or above
-0000802C 0F82A6FC jc near print_ntldr_error_message ; If not exit with error
-00008030 663DF8FFFF0F cmp eax,0xffffff8 ; Check and see if the root directory start cluster is and end of cluster chain indicator
-00008036 0F839CFC jnc near print_ntldr_error_message ; If so exit with error
-
-search_root_directory_cluster:
-0000803A 6650 push eax ; Save root directory start cluster on stack
-0000803C 6683E802 sub eax,byte +0x2 ; Adjust it because the first two fat entries are unused so the third entry marks the first data area cluster
-00008040 660FB65E0D movzx ebx,byte [bp+SectsPerCluster] ; Put the number of sectors per cluster in ebx
-00008045 8BF3 mov si,bx ; Now store it also in si register
-00008047 66F7E3 mul ebx ; Multiply sectors per cluster with root directory start cluster
-0000804A 660346FC add eax,[bp-0x4] ; Add the start sector of the data area
-
-read_directory_sector:
-0000804E BB0082 mov bx,0x8200 ; We now have the start sector of the root directory, so load it to 0x8200
-00008051 8BFB mov di,bx ; Put the address of the root directory sector in di also
-00008053 B90100 mov cx,0x1 ; Read one sector
-00008056 E887FC call read_sectors ; Perform the read
-
-check_entry_for_ntldr:
-00008059 382D cmp [di],ch ; Check the first byte of the root directory entry for zero
-0000805B 741E jz ntldr_not_found ; If so then NTLDR is missing so exit with error
-0000805D B10B mov cl,0xb ; Put the value 11 in cl so we can compare an 11-byte filename
-0000805F 56 push si ; Save si (which contains the number of sectors per cluster)
-00008060 BE707D mov si,NTLDR ;0x7d70 ; Check and see if "NTLDR" is the first file entry
-00008063 F3A6 repe cmpsb ; Do the compare
-00008065 5E pop si ; Restore sectors per cluster into si
-00008066 741B jz ntldr_found ; If we found it then continue, else check next entry
-00008068 03F9 add di,cx ; Add 0 to di? the next entry is 0x15 bytes away
-0000806A 83C715 add di,byte +0x15 ; Add 0x15 to di
-0000806D 3BFB cmp di,bx ; Check to see if we have reached the end of our sector we loaded, read_sectors sets bx = end address of data loaded
-0000806F 72E8 jc check_entry_for_ntldr ; If we haven't reached the end then check the next entry
-00008071 4E dec si ; decrement si, si holds the number of sectors per cluster
-00008072 75DA jnz read_directory_sector ; If it's not zero then search the next sector for NTLDR
-00008074 6658 pop eax ; If we got here that means we didn't find NTLDR in the previous root directory cluster, so restore eax with the start cluster
-00008076 E86500 call get_fat_entry ; Get the next cluster in the fat chain
-00008079 72BF jc search_root_directory_cluster ; If we reached end-of-file marker then don't jump, otherwise continue search
-
-ntldr_not_found:
-0000807B 83C404 add sp,byte +0x4
-0000807E E955FC jmp print_ntldr_error_message
-
-ntldr_load_segment_address dw 0x2000
-
-ntldr_found:
-00008083 83C404 add sp,byte +0x4 ; Adjust stack to remove root directory start cluster
-00008086 8B7509 mov si,[di+0x9] ; Put start cluster high word in si
-00008089 8B7D0F mov di,[di+0xf] ; Put start cluster low word in di
-0000808C 8BC6 mov ax,si ; Put high word in ax
-0000808E 66C1E010 shl eax,0x10 ; Shift it into position
-00008092 8BC7 mov ax,di ; Put low word in ax, now eax contains start cluster of NTLDR
-00008094 6683F802 cmp eax,byte +0x2 ; Check and see if the start cluster of NTLDR starts at cluster 2 or above
-00008098 0F823AFC jc near print_ntldr_error_message ; If not exit with error
-0000809C 663DF8FFFF0F cmp eax,0xffffff8 ; Check and see if the start cluster of NTLDR is and end of cluster chain indicator
-000080A2 0F8330FC jnc near print_ntldr_error_message ; If so exit with error
-
-load_next_ntldr_cluster:
-000080A6 6650 push eax ; Save NTLDR start cluster for later
-000080A8 6683E802 sub eax,byte +0x2 ; Adjust it because the first two fat entries are unused so the third entry marks the first data area cluster
-000080AC 660FB64E0D movzx ecx,byte [bp+SectsPerCluster] ; Put the sectors per cluster into ecx
-000080B1 66F7E1 mul ecx ; Multiply sectors per cluster by the start cluster, we now have the logical start sector
-000080B4 660346FC add eax,[bp-0x4] ; Add the start of the data area logical sector
-000080B8 BB0000 mov bx,0x0 ; Load NTLDR to offset zero
-000080BB 06 push es ; Save es
-000080BC 8E068180 mov es,[ntldr_load_segment_address] ; Get the segment address to load NTLDR to
-000080C0 E81DFC call read_sectors ; Load the first cluster
-000080C3 07 pop es ; Restore es
-000080C4 6658 pop eax ; Restore eax to NTLDR start cluster
-000080C6 C1EB04 shr bx,0x4 ; bx contains the amount of data we transferred, so divide it by 16
-000080C9 011E8180 add [ntldr_load_segment_address],bx ; Add that value to the segment
-000080CD E80E00 call get_fat_entry ; Get the next cluster in eax
-000080D0 0F830200 jnc near jump_to_ntldr ; If we have reached the end of file then lets get to NTLDR
-000080D4 72D0 jc load_next_ntldr_cluster ; If not, then load another cluster
-
-jump_to_ntldr:
-000080D6 8A5640 mov dl,[bp+BootDrive] ; Put the boot drive in dl
-000080D9 EA00000020 jmp 0x2000:0x0 ; Jump to NTLDR
-
-get_fat_entry:
-000080DE 66C1E002 shl eax,0x2 ; Multiply cluster by 4
-000080E2 E81100 call load_fat_sector ; Load the fat sector
-000080E5 26668B01 mov eax,[es:bx+di] ; Get the fat entry
-000080E9 6625FFFFFF0F and eax,0xfffffff ; Mask off the most significant 4 bits
-000080EF 663DF8FFFF0F cmp eax,0xffffff8 ; Compare it to end of file marker to set the flags correctly
-000080F5 C3 ret ; Return to caller
-
-load_fat_sector:
-000080F6 BF007E mov di,0x7e00 ; We will load the fat sector to 0x7e00
-000080F9 660FB74E0B movzx ecx,word [bp+SectsPerCluster] ; Get the sectors per cluster
-000080FE 6633D2 xor edx,edx ; We will divide (cluster * 4) / sectorspercluster
-00008101 66F7F1 div ecx ; eax is already set before we get to this routine
-00008104 663B46F4 cmp eax,[bp-0xc] ; Compare eax to 0xffffffff (initially, we set this value later)
-00008108 743A jz load_fat_sector_end ; If it is the same return
-0000810A 668946F4 mov [bp-0xc],eax ; Update that value
-0000810E 6603461C add eax,[bp+HiddenSectors] ; Add the hidden sectors
-00008112 660FB74E0E movzx ecx,word [bp+ReservedSectors] ; Add the reserved sectors
-00008117 6603C1 add eax,ecx ; To the hidden sectors + the value we computed earlier
-0000811A 660FB75E28 movzx ebx,word [bp+ExtendedFlags] ; Get extended flags and put into ebx
-0000811F 83E30F and bx,byte +0xf ; Mask off upper 8 bits
-00008122 7416 jz load_fat_sector_into_memory ; If fat is mirrored then skip fat calcs
-00008124 3A5E10 cmp bl,[bp+NumberOfFats] ; Compare bl to number of fats
-00008127 0F83ABFB jnc near print_ntldr_error_message ; If bl is bigger than numfats exit with error
-0000812B 52 push dx ; Save dx
-0000812C 668BC8 mov ecx,eax ; Put the current fat sector offset into ecx
-0000812F 668B4624 mov eax,[bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat
-00008133 66F7E3 mul ebx ; Multiplied by the active fat index
-00008136 6603C1 add eax,ecx ; Add the current fat sector offset
-00008139 5A pop dx ; Restore dx
-load_fat_sector_into_memory:
-0000813A 52 push dx ; Save dx, what is so important in dx??
-0000813B 8BDF mov bx,di ; Put 0x7e00 in bx
-0000813D B90100 mov cx,0x1 ; Load one sector
-00008140 E89DFB call read_sectors ; Perform the read
-00008143 5A pop dx ; Restore dx
-load_fat_sector_end:
-00008144 8BDA mov bx,dx ; Put it into bx, what is this value??
-00008146 C3 ret ; Return
-
-
-00008147 0000 add [bx+si],al
-00008149 0000 add [bx+si],al
-0000814B 0000 add [bx+si],al
-0000814D 0000 add [bx+si],al
-0000814F 0000 add [bx+si],al
-00008151 0000 add [bx+si],al
-00008153 0000 add [bx+si],al
-00008155 0000 add [bx+si],al
-00008157 0000 add [bx+si],al
-00008159 0000 add [bx+si],al
-0000815B 0000 add [bx+si],al
-0000815D 0000 add [bx+si],al
-0000815F 0000 add [bx+si],al
-00008161 0000 add [bx+si],al
-00008163 0000 add [bx+si],al
-00008165 0000 add [bx+si],al
-00008167 0000 add [bx+si],al
-00008169 0000 add [bx+si],al
-0000816B 0000 add [bx+si],al
-0000816D 0000 add [bx+si],al
-0000816F 0000 add [bx+si],al
-00008171 0000 add [bx+si],al
-00008173 0000 add [bx+si],al
-00008175 0000 add [bx+si],al
-00008177 0000 add [bx+si],al
-00008179 0000 add [bx+si],al
-0000817B 0000 add [bx+si],al
-0000817D 0000 add [bx+si],al
-0000817F 0000 add [bx+si],al
-00008181 0000 add [bx+si],al
-00008183 0000 add [bx+si],al
-00008185 0000 add [bx+si],al
-00008187 0000 add [bx+si],al
-00008189 0000 add [bx+si],al
-0000818B 0000 add [bx+si],al
-0000818D 0000 add [bx+si],al
-0000818F 0000 add [bx+si],al
-00008191 0000 add [bx+si],al
-00008193 0000 add [bx+si],al
-00008195 0000 add [bx+si],al
-00008197 0000 add [bx+si],al
-00008199 0000 add [bx+si],al
-0000819B 0000 add [bx+si],al
-0000819D 0000 add [bx+si],al
-0000819F 0000 add [bx+si],al
-000081A1 0000 add [bx+si],al
-000081A3 0000 add [bx+si],al
-000081A5 0000 add [bx+si],al
-000081A7 0000 add [bx+si],al
-000081A9 0000 add [bx+si],al
-000081AB 0000 add [bx+si],al
-000081AD 0000 add [bx+si],al
-000081AF 0000 add [bx+si],al
-000081B1 0000 add [bx+si],al
-000081B3 0000 add [bx+si],al
-000081B5 0000 add [bx+si],al
-000081B7 0000 add [bx+si],al
-000081B9 0000 add [bx+si],al
-000081BB 0000 add [bx+si],al
-000081BD 0000 add [bx+si],al
-000081BF 0000 add [bx+si],al
-000081C1 0000 add [bx+si],al
-000081C3 0000 add [bx+si],al
-000081C5 0000 add [bx+si],al
-000081C7 0000 add [bx+si],al
-000081C9 0000 add [bx+si],al
-000081CB 0000 add [bx+si],al
-000081CD 0000 add [bx+si],al
-000081CF 0000 add [bx+si],al
-000081D1 0000 add [bx+si],al
-000081D3 0000 add [bx+si],al
-000081D5 0000 add [bx+si],al
-000081D7 0000 add [bx+si],al
-000081D9 0000 add [bx+si],al
-000081DB 0000 add [bx+si],al
-000081DD 0000 add [bx+si],al
-000081DF 0000 add [bx+si],al
-000081E1 0000 add [bx+si],al
-000081E3 0000 add [bx+si],al
-000081E5 0000 add [bx+si],al
-000081E7 0000 add [bx+si],al
-000081E9 0000 add [bx+si],al
-000081EB 0000 add [bx+si],al
-000081ED 0000 add [bx+si],al
-000081EF 0000 add [bx+si],al
-000081F1 0000 add [bx+si],al
-000081F3 0000 add [bx+si],al
-000081F5 0000 add [bx+si],al
-000081F7 0000 add [bx+si],al
-000081F9 0000 add [bx+si],al
-000081FB 0000 add [bx+si],al
-000081FD 0055AA add [di-0x56],dl ; We can't forget the infamous boot signature
+++ /dev/null
-
-;
-; The BP register is initialized to 0x7c00, the start of
-; the boot sector. The SP register is initialized to
-; 0x7bf0, leaving 16 bytes of data storage space above
-; the stack.
-;
-; The DWORD that gets stored at 0x7bfc is the logical
-; sector number of the start of the data area.
-;
-; The DWORD that gets stored at 0x7bf8 is ????????
-;
-; The DWORD that gets stored at 0x7bf4 is ????????
-;
-; The DWORD that gets stored at 0x7bf0 is ????????
-;
-
-
-org 7c00h
-
-segment .text
-
-bits 16
-
-start:
- jmp short main
- nop
-
-OEMName db 'MSWIN4.0'
-BytesPerSector dw 512
-SectsPerCluster db 1
-ReservedSectors dw 1
-NumberOfFats db 2
-MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
-TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
-MediaDescriptor db 0f8h
-SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
-SectorsPerTrack dw 18
-NumberOfHeads dw 2
-HiddenSectors dd 0
-TotalSectorsBig dd 0
-BootDrive db 80h
-Reserved db 0
-ExtendSig db 29h
-SerialNumber dd 00000000h
-VolumeLabel db 'NO NAME '
-FileSystem db 'FAT16 '
-
-main:
-00007C3E 33C9 xor cx,cx
-00007C40 8ED1 mov ss,cx ; Setup stack
-00007C42 BCF07B mov sp,0x7bf0 ; Give us 16 bytes (4 dwords) of space above stack
-00007C45 8ED9 mov ds,cx
-00007C47 B80020 mov ax,0x2000
-00007C4A 8EC0 mov es,ax ; Setup ES:0000 == 2000:0000
-00007C4C FC cld
-00007C4D BD007C mov bp,0x7c00
-00007C50 384E24 cmp [bp+BootDrive],cl ; Compare the boot drive to zero (I think they are testing for a hard disk drive number)
-00007C53 7D24 jnl floppy_boot ; Nope, it's a floppy, skip partition table tests
-00007C55 8BC1 mov ax,cx ; Move zero to AX
-00007C57 99 cwd ; DX:AX now contains zero
-00007C58 E83C01 call read_one_sector ; Try to read in the MBR sector
-00007C5B 721C jc floppy_boot ; Read failed, continue
-00007C5D 83EB3A sub bx,byte +0x3a ; BX comes back with 512, make it equal to 454 (offset of partition table in MBR)
-00007C60 66A11C7C mov eax,[HiddenSectors] ; Put HiddenSectors in EAX
-find_our_partition:
-00007C64 26663B07 cmp eax,[es:bx] ; Compare partition table entry's start sector to HiddenSectors
-00007C68 268A57FC mov dl,[es:bx-0x4] ; Get partition type byte for this entry
-00007C6C 7506 jnz next_partition_entry ; If partition start sector != HiddenSectors then skip this entry
-00007C6E 80CA02 or dl,0x2 ; Set the second bit in partition type?? I guess this makes types 4 & 6 identical
-00007C71 885602 mov [bp+0x2],dl ; Save it on top of nop instruction (3rd byte of boot sector)
-next_partition_entry:
-00007C74 80C310 add bl,0x10 ; Add 16 to bl (offset of next entry in partition table)
-00007C77 73EB jnc find_our_partition ; Jump back until we hit the end of the partition table
-
-; We now have our partition type at 0000:7C02
-; If the type was 4 or 6 then that byte is 6
-; I can't imagine why the boot sector needs to store
-; this information, but hopefully I will uncover it
-; as I further disassemble this boot sector.
-
-
-floppy_boot:
-00007C79 33C9 xor cx,cx ; Zero out CX
-00007C7B 8A4610 mov al,[bp+NumberOfFats] ; Get the number of FATs in AL (usually 2)
-00007C7E 98 cbw ; Sign extend it into AX (AX == 2)
-00007C7F F76616 mul word [bp+NumberOfFats] ; Multiply it with NumberOfFats PLUS the low byte of MaxRootEntries!!??
-00007C82 03461C add ax,[bp+HiddenSectors] ; Result is in DX:AX
-00007C85 13561E adc dx,[bp+HiddenSectors+2] ; Add HiddenSectors to DX:AX
-00007C88 03460E add ax,[bp+ReservedSectors] ; Add ReservedSectors to DX:AX
-00007C8B 13D1 adc dx,cx ; CX still contains zero
-00007C8D 8B7611 mov si,[bp+MaxRootEntries] ; Get MaxRootEntries in SI
-00007C90 60 pusha ; Save all registers (right now DX:AX has starting sector of root dir)
-00007C91 8946FC mov [bp-0x4],ax ; Save the starting sector of the root directory
-00007C94 8956FE mov [bp-0x2],dx ; Save it in the first 4 bytes before the boot sector
-00007C97 B82000 mov ax,0x20 ; AX == 32 (size of a directory entry)
-00007C9A F7E6 mul si ; Multiply it with MaxRootEntries (DX:AX == length in bytes of root directory)
-00007C9C 8B5E0B mov bx,[bp+BytesPerSector] ; Get the BytesPerSector in BX
-00007C9F 03C3 add ax,bx ; Add it to AX (what if this addition carries? MS should 'adc dx,0' shouldn't they?)
-00007CA1 48 dec ax ; Subtract one (basically rounding up)
-00007CA2 F7F3 div bx ; Divide DX:AX (length of root dir in bytes) by the size of a sector
-00007CA4 0146FC add [bp-0x4],ax ; Add the number of sectors of the root directory to our other value
-00007CA7 114EFE adc [bp-0x2],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
-00007CAA 61 popa ; Restore all registers (DX:AX has start sector of root dir)
-load_root_dir_sector:
-00007CAB BF0000 mov di,0x0 ; Zero out di
-00007CAE E8E600 call read_one_sector ; Read the first sector of the root directory
-00007CB1 7239 jc print_disk_error_message ; Read failed, print disk error and reboot
-search_directory:
-00007CB3 26382D cmp [es:di],ch ; If the first byte of the directory entry is zero then we have reached the end
-00007CB6 7417 jz print_ntldr_error_message; of the directory and NTLDR is not here so reboot
-00007CB8 60 pusha ; Save all registers
-00007CB9 B10B mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
-00007CBB BEA17D mov si,NTLDR ; Put offset of filename string in DS:SI
-00007CBE F3A6 repe cmpsb ; Compare this directory entry against 'NTLDR '
-00007CC0 61 popa ; Restore all the registers
-00007CC1 7432 jz found_ntldr ; If we found NTLDR then jump
-00007CC3 4E dec si ; SI holds MaxRootEntries, subtract one
-00007CC4 7409 jz print_ntldr_error_message; If we are out of root dir entries then reboot
-00007CC6 83C720 add di,byte +0x20 ; Increment DI by the size of a directory entry
-00007CC9 3BFB cmp di,bx ; Compare DI to BX (DI has offset to next dir entry, BX has address of end of directory sector in memory)
-00007CCB 72E6 jc search_directory ; If DI is less than BX loop again
-00007CCD EBDC jmp short load_root_dir_sector ; Didn't find NTLDR in this directory sector, try again
-print_ntldr_error_message:
-00007CCF A0FB7D mov al,[NTLDR_ERR_offset_from_0x7d00]
-putchars:
-00007CD2 B47D mov ah,0x7d
-00007CD4 8BF0 mov si,ax
-get_another_char:
-00007CD6 AC lodsb
-00007CD7 98 cbw
-00007CD8 40 inc ax
-00007CD9 740C jz print_reboot_message
-00007CDB 48 dec ax
-00007CDC 7413 jz reboot
-00007CDE B40E mov ah,0xe
-00007CE0 BB0700 mov bx,0x7
-00007CE3 CD10 int 0x10
-00007CE5 EBEF jmp short get_another_char
-print_reboot_message:
-00007CE7 A0FD7D mov al,[RESTART_ERR_offset_from_0x7d00]
-00007CEA EBE6 jmp short putchars
-print_disk_error_message:
-00007CEC A0FC7D mov al,[DISK_ERR_offset_from_0x7d00]
-00007CEF EBE1 jmp short putchars
-reboot:
-00007CF1 CD16 int 0x16
-00007CF3 CD19 int 0x19
-found_ntldr:
-00007CF5 268B551A mov dx,[es:di+0x1a] ; Get NTLDR start cluster in DX
-00007CF9 52 push dx ; Save it on the stack
-00007CFA B001 mov al,0x1 ; Read 1 cluster? Or is this one sector?
-00007CFC BB0000 mov bx,0x0 ; ES:BX is the load address (2000:0000)
-00007CFF E83B00 call read_cluster ; Do the read
-00007D02 72E8 jc print_disk_error_message ; If it failed then reboot
-00007D04 5B pop bx ; Get the start cluster of NTLDR in BX
-00007D05 8A5624 mov dl,[bp+BootDrive] ; Get boot drive in DL
-00007D08 BE0B7C mov si,0x7c0b
-00007D0B 8BFC mov di,sp
-00007D0D C746F03D7D mov word [bp-0x10],read_cluster
-00007D12 C746F4297D mov word [bp-0xc],0x7d29
-00007D17 8CD9 mov cx,ds
-00007D19 894EF2 mov [bp-0xe],cx
-00007D1C 894EF6 mov [bp-0xa],cx
-00007D1F C606967DCB mov byte [0x7d96],0xcb
-00007D24 EA03000020 jmp 0x2000:0x3
-00007D29 0FB6C8 movzx cx,al
-00007D2C 668B46F8 mov eax,[bp-0x8]
-00007D30 6603461C add eax,[bp+HiddenSectors]
-00007D34 668BD0 mov edx,eax
-00007D37 66C1EA10 shr edx,0x10
-00007D3B EB5E jmp short 0x7d9b
-read_cluster:
-00007D3D 0FB6C8 movzx cx,al
-00007D40 4A dec dx
-00007D41 4A dec dx
-00007D42 8A460D mov al,[bp+SectsPerCluster]
-00007D45 32E4 xor ah,ah
-00007D47 F7E2 mul dx
-00007D49 0346FC add ax,[bp-0x4]
-00007D4C 1356FE adc dx,[bp-0x2]
-00007D4F EB4A jmp short 0x7d9b
-
-read_sectors:
-00007D51 52 push dx
-00007D52 50 push ax
-00007D53 06 push es
-00007D54 53 push bx
-00007D55 6A01 push byte +0x1
-00007D57 6A10 push byte +0x10
-00007D59 91 xchg ax,cx
-00007D5A 8B4618 mov ax,[bp+SectorsPerTrack]
-00007D5D 96 xchg ax,si
-00007D5E 92 xchg ax,dx
-00007D5F 33D2 xor dx,dx
-00007D61 F7F6 div si
-00007D63 91 xchg ax,cx
-00007D64 F7F6 div si
-00007D66 42 inc dx
-00007D67 87CA xchg cx,dx
-00007D69 F7761A div word [bp+NumberOfHeads]
-00007D6C 8AF2 mov dh,dl
-00007D6E 8AE8 mov ch,al
-00007D70 C0CC02 ror ah,0x2
-00007D73 0ACC or cl,ah
-00007D75 B80102 mov ax,0x201
-00007D78 807E020E cmp byte [bp+0x2],0xe
-00007D7C 7504 jnz 0x7d82
-00007D7E B442 mov ah,0x42
-00007D80 8BF4 mov si,sp
-00007D82 8A5624 mov dl,[bp+BootDrive]
-00007D85 CD13 int 0x13
-00007D87 61 popa
-00007D88 61 popa
-00007D89 720B jc 0x7d96
-00007D8B 40 inc ax
-00007D8C 7501 jnz 0x7d8f
-00007D8E 42 inc dx
-00007D8F 035E0B add bx,[bp+BytesPerSector]
-00007D92 49 dec cx
-00007D93 7506 jnz 0x7d9b
-00007D95 F8 clc
-00007D96 C3 ret
-
-read_one_sector:
-00007D97 41 inc cx
-00007D98 BB0000 mov bx,0x0
-00007D9B 60 pusha
-00007D9C 666A00 o32 push byte +0x0
-00007D9F EBB0 jmp short 0x7d51
-
-
-NTLDR db 'NTLDR '
-
-
-NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
-DISK_ERR db 0dh,0ah,'Disk error',0ffh
-RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
-
-filler times 18 db 0
-
-
-NTLDR_offset_from_0x7d00 db 0
-NTLDR_ERR_offset_from_0x7d00 db 0ach
-DISK_ERR_offset_from_0x7d00 db 0bfh
-RESTART_ERR_offset_from_0x7d00 db 0cch
-
- dw 0
- dw 0aa55h