diff --git a/freeldr/bootsect/Makefile b/freeldr/bootsect/Makefile index ebde83fa865..97607a4634a 100644 --- a/freeldr/bootsect/Makefile +++ b/freeldr/bootsect/Makefile @@ -26,12 +26,10 @@ export NASM_CMD = nasm .PHONY : clean -all: fat.bin fat32.bin bin2c.exe split.exe stubit.exe +all: fat.bin fat32.bin bin2c.exe -fat.bin: fat.asm bin2c.exe split.exe - $(NASM_CMD) -o fat_tmp.bin -f bin fat.asm - split fat_tmp.bin fat.bin fatstub.bin 512 - $(RM) fat_tmp.bin +fat.bin: fat.asm bin2c.exe + $(NASM_CMD) -o fat.bin -f bin fat.asm bin2c fat.bin fat.h fat_data @@ -42,12 +40,6 @@ fat32.bin: fat32.asm bin2c.exe bin2c.exe: bin2c.c $(CC) -o bin2c.exe bin2c.c -split.exe: split.c - $(CC) -o split.exe split.c - -stubit.exe: stubit.c - $(CC) -o stubit.exe stubit.c - clean: $(RM) *.bin $(RM) *.exe diff --git a/freeldr/bootsect/bin2c.c b/freeldr/bootsect/bin2c.c index 88de4b76c50..abde1ff5fa3 100644 --- a/freeldr/bootsect/bin2c.c +++ b/freeldr/bootsect/bin2c.c @@ -45,4 +45,4 @@ int main(int argc, char *argv[]) fclose(out); return 0; -} \ No newline at end of file +} diff --git a/freeldr/bootsect/fat.asm b/freeldr/bootsect/fat.asm index 94d4ab34500..b5c27b10436 100644 --- a/freeldr/bootsect/fat.asm +++ b/freeldr/bootsect/fat.asm @@ -1,6 +1,6 @@ ; FAT.ASM ; FAT12/16 Boot Sector -; Copyright (c) 1998, 2001 Brian Palmer +; Copyright (c) 1998, 2001, 2002 Brian Palmer @@ -9,11 +9,27 @@ ; for the file freeldr.sys and loads it into ; memory. ; -; The stack is set to 0000:7C00 so that the first -; DWORD pushed will be placed at 0000:7BFC +; 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:7E00 +; load the first sector of the file to 0000:8000 ; With the help of this sector we should be able ; to load the entire file off the disk, no matter ; how fragmented it is. @@ -23,6 +39,16 @@ ; boots dramatically. +BootSectorStackTop equ 0x7bf2 +DataAreaStartHigh equ 0x2 +DataAreaStartLow equ 0x4 +BiosCHSDriveSize equ 0x6 +BiosCHSDriveSizeHigh equ 0x6 +BiosCHSDriveSizeLow equ 0x8 +ReadSectorsOffset equ 0xa +ReadClusterOffset equ 0xc +PutCharsOffset equ 0xe + org 7c00h @@ -55,180 +81,150 @@ VolumeLabel db 'NO NAME ' FileSystem db 'FAT12 ' main: - cli - cld xor ax,ax mov ss,ax mov bp,7c00h - mov sp,bp ; Setup a stack - mov ax,cs ; Setup segment registers - mov ds,ax ; Make DS correct - mov es,ax ; Make ES correct + mov sp,BootSectorStackTop ; Setup a stack + mov ds,ax ; Make DS correct + mov es,ax ; Make ES correct - sti ; Enable ints now - mov [BYTE bp+BootDrive],dl ; Save the boot drive - xor ax,ax ; Zero out AX + 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 - ; Reset disk controller - int 13h - jnc Continue1 - jmp BadBoot ; Reset failed... -Continue1: ; Now we must find our way to the first sector of the root directory xor ax,ax - xor dx,dx - mov al,[BYTE bp+NumberOfFats] ; Number of fats - mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat + 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,byte 0 ; Add carry bit - push ax ; Store it on the stack - push dx ; Save 32-bit logical start sector - push ax - push dx ; Save it for later use also + 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 - mov ax,0020h ; Size of dir entry - mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries + 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 + div bx ; Divided by the size of a sector + ; AX now has the number of root directory sectors - xchg ax,cx ; Now CX has number of sectors - pop dx - pop ax ; Restore logical sector start - push cx ; Save number of root dir sectors for later use - mov bx,7c0h ; We will load the root directory - add bx,byte 20h ; Right after the boot sector in memory - mov es,bx - xor bx,bx ; We will load it to [0000:7e00h] - call ReadSectors ; Read the 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) - ; Now we have to find our way through the root directory to - ; The OSLOADER.SYS file - mov bx,[BYTE bp+MaxRootEntries]; Search entire root directory - mov ax,7e0h ; We loaded at 07e0: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 ErrBoot +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 LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again -FindFile: - mov ax,es ; We didn't find it in the previous dir entry - add ax,byte 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? - jmp ErrBoot - -FoundFile: +FoundFreeLoader: ; We found freeldr.sys on the disk ; so we need to load the first 512 - ; bytes of it to 0000:7E00 - xor di,di ; ES:DI has dir entry - xor dx,dx - mov ax,WORD [es:di+1ah]; Get start cluster - 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] ; Times sectors per cluster - mul cx - pop cx ; Get number of sectors for root dir - add ax,cx ; Add it to the start sector of freeldr.sys - adc dx,byte 0 - pop cx ; Get logical start sector of - pop bx ; Root directory - add ax,bx ; Now we have DX:AX with the logical start - adc dx,cx ; Sector of OSLOADER.SYS - mov cx,1 ; We will load 1 sector - push WORD [es:di+1ah] ; Save start cluster - mov bx,7e0h - mov es,bx - xor bx,bx - call ReadSectors ; Load it - pop ax ; Restore start cluster - jmp LoadFile + ; bytes of it to 0000:8000 + ; 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 800h ; Put 800h on the stack and load it + pop es ; Into ES so that we load the cluster at 0000:8000 + 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:8000. 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. + ;jmp 0000:8003h + jmp 8003h + + +; 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 OSLOADER.SYS + xor bx,bx ; We will load it to [ES:0000], ES loaded before function call + mov cl,BYTE [BYTE bp+SectsPerCluster] + call ReadSectors + 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 -ReadSectors: - push ax - push dx - push cx - 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,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 BadBoot - - pop cx - pop dx - pop ax - inc ax ;Increment Sector to Read - jnz NoCarry - inc dx - - -NoCarry: - push bx - mov bx,es - add bx,byte 20h - mov es,bx - pop bx - ; Increment read buffer for next sector - loop ReadSectors ; Read next sector - - ret - - - -; Displays a bad boot message -; And reboots -BadBoot: - mov si,msgDiskError ; Bad boot disk message - call PutChars ; Display it - mov si,msgAnyKey ; Press any key message - call PutChars ; Display it - - jmp Reboot ; Displays an error message ; And reboots @@ -254,246 +250,131 @@ PutChars: Done: retn +; Displays a bad boot message +; And reboots +BadBoot: + mov si,msgDiskError ; Bad boot disk message + call PutChars ; Display it + mov si,msgAnyKey ; Press any key message + call PutChars ; Display it + + jmp Reboot + +; Reads logical sectors into [ES:BX] +; DX:AX has logical sector number to read +; CX has number of sectors to read +ReadSectors: + cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh]; Check if they are reading a sector within CHS range + 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: + pushad ; 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,0x10 ; Remove disk address packet from stack + + popad ; Restore sector count & logical sector number + + inc ax ; Increment Sector to Read + jnz NoCarry + inc dx + + +NoCarry: + mov dx,es + add dx,byte 20h ; Increment read buffer for next sector + mov es,dx + + loop ReadSectorsLBA ; 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: + pushad + 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,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 BadBoot + + popad + 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 ReadSectorsCHS ; Read next sector + + ret + + msgDiskError db 'Disk error',0dh,0ah,0 msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0 -msgAnyKey db 'Press any key to restart',0dh,0ah,0 +; Sorry, need the space... +;msgAnyKey db 'Press any key to restart',0dh,0ah,0 +msgAnyKey db 'Press any key',0dh,0ah,0 filename db 'FREELDR SYS' times 510-($-$$) db 0 ; Pad to 510 bytes dw 0aa55h ; BootSector signature - - - -; End of bootsector -; -; Now starts the extra boot code that we will store -; in the first 512 bytes of freeldr.sys - - - -LoadFile: - - push ax ; First save AX - the start cluster of freeldr.sys - - - ; Display "Loading FreeLoader..." message - mov si,msgLoading ; Loading message - call PutChars ; Display it - - - pop ax ; Restore AX - - ; AX has start cluster of freeldr.sys - push ax - call ReadFatIntoMemory - pop ax - - mov bx,7e0h - mov es,bx - -LoadFile2: - push ax - call IsFat12 - pop ax - jnc LoadFile3 - cmp ax,0ff8h ; Check to see if this is the last cluster in the chain - jmp LoadFile4 -LoadFile3: - cmp ax,0fff8h -LoadFile4: - jae LoadFile_Done ; If so continue, if not then read then next one - push ax - xor bx,bx ; Load ROSLDR starting at 0000:8000h - push es - call ReadCluster - pop es - - xor bx,bx - mov bl,BYTE [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 - - call IsFat12 - pop ax - push es - jnc LoadFile5 - call GetFatEntry12 ; Get the next entry - jmp LoadFile6 -LoadFile5: - call GetFatEntry16 -LoadFile6: - pop es - - jmp LoadFile2 ; Load the next cluster (if any) - -LoadFile_Done: - mov dl,BYTE [BYTE bp+BootDrive] - xor ax,ax - push ax - mov ax,8000h - push ax ; We will do a far return to 0000:8000h - retf ; Transfer control to ROSLDR - - -; Reads the entire FAT into memory at 7000:0000 -ReadFatIntoMemory: - mov ax,WORD [BYTE bp+HiddenSectors] - mov dx,WORD [BYTE bp+HiddenSectors+2] - add ax,WORD [BYTE bp+ReservedSectors] - adc dx,byte 0 - mov cx,WORD [BYTE bp+SectorsPerFat] - mov bx,7000h - mov es,bx - xor bx,bx - call ReadSectors - ret - - -; Returns the FAT entry for a given cluster number for 16-bit FAT -; On entry AX has cluster number -; On return AX has FAT entry for that cluster -GetFatEntry16: - - xor dx,dx - mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes) - mul cx - shl dx,0fh - - mov bx,7000h - add bx,dx - mov es,bx - mov bx,ax ; Restore FAT entry offset - mov ax,WORD [es:bx] ; Get FAT entry - - ret - - -; Returns the FAT entry for a given cluster number for 12-bit FAT -; On entry AX has cluster number -; On return AX has FAT entry for that cluster -GetFatEntry12: - - push ax - mov cx,ax - shr ax,1 - add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits) - - mov bx,7000h - mov es,bx - mov bx,ax ; Put FAT entry offset into BX - mov ax,WORD [es:bx] ; Get FAT entry - pop cx ; Get cluster number from stack - and cx,1 - jz UseLow12Bits - and ax,0fff0h - shr ax,4 - jmp GetFatEntry12_Done - -UseLow12Bits: - and ax,0fffh - -GetFatEntry12_Done: - - ret - - -; Reads cluster number in AX into [ES:0000] -ReadCluster: - ; StartSector = ((Cluster - 2) * SectorsPerCluster) + + ReservedSectors + HiddenSectors; - - dec ax - dec ax - xor dx,dx - movzx bx,BYTE [BYTE bp+SectsPerCluster] - mul bx - push ax - push dx - ; Now calculate the size of the root directory - mov ax,0020h ; Size of dir entry - mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries - mov bx,WORD [BYTE bp+BytesPerSector] - add ax,bx - dec ax - div bx ; Divided by the size of a sector - mov cx,ax - ; CX now has the number of root directory sectors - xor dx,dx - movzx ax,BYTE [BYTE bp+NumberOfFats] - mul WORD [BYTE bp+SectorsPerFat] - add ax,WORD [BYTE bp+ReservedSectors] - adc dx,byte 0 - add ax,WORD [BYTE bp+HiddenSectors] - adc dx,WORD [BYTE bp+HiddenSectors+2] - add ax,cx - adc dx,byte 0 - pop cx - pop bx - add ax,bx - adc dx,cx - xor bx,bx ; We will load it to [ES:0000], ES loaded before function call - movzx cx,BYTE [BYTE bp+SectsPerCluster] - call ReadSectors - ret - -; Returns CF = 1 if this is a FAT12 file system -; Otherwise CF = 0 for FAT16 -IsFat12: - - ; Now calculate the size of the root directory - mov ax,0020h ; Size of dir entry - mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries - mov bx,WORD [BYTE bp+BytesPerSector] - add ax,bx ; Plus (BytesPerSector - 1) - dec ax - div bx ; Divided by the size of a sector - ; AX now has the number of root directory sectors - - mov bx,ax - ; Now we must find our way to the first sector of the root directory - xor ax,ax - xor dx,dx - mov al,BYTE [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,[BYTE bp+ReservedSectors] ; Add the number of reserved sectors - adc dx,byte 0 ; Add carry bit - add ax,bx - adc dx,byte 0 ; Add carry bit - ; DX:AX now has the number of the starting sector of the data area - - xor cx,cx - mov bx,WORD [BYTE bp+TotalSectors] - cmp bx,byte 0 - jnz IsFat12_2 - mov bx,WORD [BYTE bp+TotalSectorsBig] - mov cx,WORD [BYTE bp+TotalSectorsBig+2] - - ; CX:BX now contains the number of sectors on the volume -IsFat12_2: - sub bx,ax ; Subtract data area start sector - sub cx,dx ; from total sectors of volume - mov ax,bx - mov dx,cx - - ; DX:AX now contains the number of data sectors on the volume - movzx bx,BYTE [BYTE bp+SectsPerCluster] - div bx - ; AX now has the number of clusters on the volume - stc - cmp ax,4085 - jb IsFat12_Done - clc - -IsFat12_Done: - ret - - - - times 998-($-$$) db 0 ; Pad to 998 bytes - -msgLoading db 'Loading FreeLoader...',0dh,0ah,0 - - dw 0aa55h ; BootSector signature diff --git a/freeldr/bootsect/fat32.asm b/freeldr/bootsect/fat32.asm index 619f4771b66..84e86cd5c83 100644 --- a/freeldr/bootsect/fat32.asm +++ b/freeldr/bootsect/fat32.asm @@ -1,9 +1,8 @@ ; FAT32.ASM ; FAT32 Boot Sector -; Copyright (c) 1998, 2000, 2001 Brian Palmer +; Copyright (c) 1998, 2000, 2001, 2002 Brian Palmer -;org 7c00h -org 0 +org 7c00h segment .text @@ -43,32 +42,12 @@ VolumeLabel db 'NO NAME ' FileSystem db 'FAT32 ' main: - cli - cld - - ; Lets copy ourselves from 0000:7c00 to 9000:0000 - ; and transfer control to the new code - xor ax,ax - mov ds,ax - mov si,7c00h - mov ax,9000h - mov es,ax - xor di,di - mov cx,512 - rep movsb - jmp 0x9000:RealMain - - ; Now we are executing at 9000:xxxx - ; We are now free to load freeldr.sys at 0000:7e00 -RealMain: - xor ax,ax - mov bp,ax - mov sp,ax ; Setup a stack - mov ax,cs ; Setup segment registers + xor ax,ax ; Setup segment registers mov ds,ax ; Make DS correct mov es,ax ; Make ES correct mov ss,ax ; Make SS correct - sti ; Enable ints now + mov bp,7c00h + mov sp,7c00h ; Setup a stack @@ -121,13 +100,13 @@ CalcDriveSize: LoadExtraBootCode: ; First we have to load our extra boot code at - ; sector 14 into memory at [9000:0200h] + ; 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 - mov bx,9000h - mov es,bx ; Read sector to [9000:0200h] - mov bx,0200h + xor bx,bx + mov es,bx ; Read sector to [0000:7e00h] + mov bx,7e00h call ReadSectors jmp StartSearch @@ -291,8 +270,8 @@ StartSearch: jb ContinueSearch ; If not continue, if so then we didn't find freeldr.sys jmp PrintFileNotFound ContinueSearch: - mov bx,7e0h - mov es,bx ; Read cluster to [0000:7e00h] + mov bx,800h + mov es,bx ; Read cluster to [0000:8000h] call ReadCluster ; Read the cluster @@ -301,7 +280,7 @@ ContinueSearch: xor bx,bx mov bl,[BYTE bp+SectsPerCluster] shl bx,4 ; BX = BX * 512 / 32 - mov ax,7e0h ; We loaded at 07e0:0000 + mov ax,800h ; We loaded at 0800:0000 mov es,ax xor di,di mov si,filename @@ -354,14 +333,14 @@ CheckEndCluster: jmp PrintFileSystemError ; If so exit with error InitializeLoadSegment: - mov bx,7e0h + mov bx,800h 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:7e00h + xor bx,bx ; Load ROSLDR starting at 0000:8000h push es call ReadCluster pop es @@ -382,8 +361,8 @@ LoadFile: LoadFileDone: mov dl,[BYTE bp+BootDrive] - xor ax,ax ; We loaded at 0000:7e00 but the entry point is 0000:8000 - push ax ; because the first 512 bytes is fat helper code + xor ax,ax + push ax ; We loaded at 0000:8000 push WORD 8000h ; We will do a far return to 0000:8000h retf ; Transfer control to ROSLDR diff --git a/freeldr/bootsect/split.c b/freeldr/bootsect/split.c deleted file mode 100644 index 2a170ec8e35..00000000000 --- a/freeldr/bootsect/split.c +++ /dev/null @@ -1,55 +0,0 @@ -#include - -FILE *in; -FILE *out; -FILE *new; - -int main(int argc, char *argv[]) -{ - unsigned char ch; - int cnt; - int split_offset; - - if (argc < 5) - { - printf("usage: split infile.bin outfile.bin newfile.bin split_offset\n"); - return -1; - } - - if ((in = fopen(argv[1], "rb")) == NULL) - { - printf("Couldn't open data file.\n"); - return -1; - } - if ((out = fopen(argv[2], "wb")) == NULL) - { - printf("Couldn't open output file.\n"); - return -1; - } - if ((new = fopen(argv[3], "wb")) == NULL) - { - printf("Couldn't open new file.\n"); - return -1; - } - - split_offset = atoi(argv[4]); - - for (cnt=0; cnt - -FILE *in; -FILE *in2; -FILE *out; - -int main(int argc, char *argv[]) -{ - unsigned char ch; - - if (argc < 4) - { - printf("usage: stubit infile1.bin infile2.sys outfile.bin\n"); - return -1; - } - - if ((in = fopen(argv[1], "rb")) == NULL) - { - printf("Couldn't open data file.\n"); - return -1; - } - if ((in2 = fopen(argv[2], "rb")) == NULL) - { - printf("Couldn't open data file.\n"); - return -1; - } - if ((out = fopen(argv[3], "wb")) == NULL) - { - printf("Couldn't open output file.\n"); - return -1; - } - - ch = fgetc(in); - while (!feof(in)) - { - fputc(ch, out); - ch = fgetc(in); - } - - ch = fgetc(in2); - while (!feof(in2)) - { - fputc(ch, out); - ch = fgetc(in2); - } - - fclose(in); - fclose(in2); - fclose(out); - - return 0; -} \ No newline at end of file diff --git a/freeldr/bootsect/win2k.asm b/freeldr/bootsect/win2k.asm index 8b66697c019..9152a4c1724 100644 --- a/freeldr/bootsect/win2k.asm +++ b/freeldr/bootsect/win2k.asm @@ -19,6 +19,8 @@ ; sector number of the start of the data area. ; +org 7c00h + segment .text bits 16 @@ -49,7 +51,7 @@ FSInfoSector dw 0 BackupBootSector dw 6 Reserved1 times 12 db 0 ; End FAT32 Inserted Info -BootDrive db 0 +BootDrive db 80h Reserved db 0 ExtendSig db 29h SerialNumber dd 00000000h diff --git a/freeldr/bootsect/wxpfat16.asm b/freeldr/bootsect/wxpfat16.asm new file mode 100644 index 00000000000..b4e3abd2f92 --- /dev/null +++ b/freeldr/bootsect/wxpfat16.asm @@ -0,0 +1,249 @@ + +; +; 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 diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile index a9427fdb6d2..ef9e0eccdef 100644 --- a/freeldr/freeldr/Makefile +++ b/freeldr/freeldr/Makefile @@ -34,8 +34,7 @@ LIB_FILES2 = comm/comm.a disk/disk.a mm/mm.a cache/cache.a inifile/inifile.a all: freeldr.sys freeldr.sys: c_code.a end.o - $(LD) -N -Ttext=0x8000 --oformat=binary -s -o f.sys c_code.a end.o - ../bootsect/stubit ../bootsect/fatstub.bin f.sys freeldr.sys + $(LD) -N -Ttext=0x8000 --oformat=binary -s -o freeldr.sys c_code.a end.o freeldr.exe: asmcode.a c_code.a $(LD) -o freeldr.exe asmcode.a c_code.a diff --git a/freeldr/freeldr/arch/i386/Makefile b/freeldr/freeldr/arch/i386/Makefile index 9f33c68ad0e..93bae16c150 100644 --- a/freeldr/freeldr/arch/i386/Makefile +++ b/freeldr/freeldr/arch/i386/Makefile @@ -19,7 +19,7 @@ include ../../rules.mk -OBJS = arch.o boot.o mb.o mem.o disk.o +OBJS = fathelp.o arch.o boot.o mb.o mem.o disk.o .PHONY : clean @@ -30,6 +30,9 @@ arch.a: $(OBJS) - $(RM) ..\arch.a $(CP) arch.a ..\arch.a +fathelp.o: fathelp.asm + $(NASM_CMD) -o fathelp.o -f coff fathelp.asm + arch.o: arch.S $(CC) $(FLAGS) -o arch.o -c arch.S diff --git a/freeldr/freeldr/arch/i386/arch.S b/freeldr/freeldr/arch/i386/arch.S index 3d1b1db9ec6..ee586cb02f6 100644 --- a/freeldr/freeldr/arch/i386/arch.S +++ b/freeldr/freeldr/arch/i386/arch.S @@ -24,7 +24,7 @@ #include "arch.h" -EXTERN(start) +EXTERN(RealEntryPoint) cli diff --git a/freeldr/freeldr/arch/i386/fathelp.asm b/freeldr/freeldr/arch/i386/fathelp.asm new file mode 100644 index 00000000000..81a0ddeb8ce --- /dev/null +++ b/freeldr/freeldr/arch/i386/fathelp.asm @@ -0,0 +1,226 @@ +; FATHELP.ASM +; FAT12/16 Boot Sector Helper Code +; Copyright (c) 1998, 2001, 2002 Brian Palmer + + + +;org 8000h + +segment .text + +bits 16 + + +BootSectorStackTop equ 0x7bf2 +DataAreaStartHigh equ 0x2 +DataAreaStartLow equ 0x4 +BiosCHSDriveSize equ 0x6 +BiosCHSDriveSizeHigh equ 0x6 +BiosCHSDriveSizeLow equ 0x8 +ReadSectorsOffset equ 0xa +ReadClusterOffset equ 0xc +PutCharsOffset equ 0xe + +OEMName equ 3 +BytesPerSector equ 11 +SectsPerCluster equ 13 +ReservedSectors equ 14 +NumberOfFats equ 16 +MaxRootEntries equ 17 +TotalSectors equ 19 +MediaDescriptor equ 21 +SectorsPerFat equ 22 +SectorsPerTrack equ 24 +NumberOfHeads equ 26 +HiddenSectors equ 28 +TotalSectorsBig equ 32 +BootDrive equ 36 +Reserved equ 37 +ExtendSig equ 38 +SerialNumber equ 39 +VolumeLabel equ 43 +FileSystem equ 54 + + +; This code will be stored in the first 512 bytes +; of freeldr.sys. The first 3 bytes will be a jmp +; instruction to skip past the FAT helper code +; that is stored in the rest of the 512 bytes. +; +; This code is loaded at 0000:8000 so we have to +; encode a jmp instruction to jump to 0000:8200 + +global start +start: + db 0xe9 + db 0xfd + db 0x01 + +; Now starts the extra boot code that we will store +; in the first 512 bytes of freeldr.sys. This code +; allows the FAT12/16 bootsector to navigate the +; FAT table so that we can still load freeldr.sys +; even if it is fragmented. + + +FatHelperEntryPoint: + + push ax ; First save AX - the start cluster of freeldr.sys + + + ; Display "Loading FreeLoader..." message + mov esi,msgLoading ; Loading message + call [bp-PutCharsOffset] ; Display it + + + call ReadFatIntoMemory + + pop ax ; Restore AX (start cluster) + ; AX has start cluster of freeldr.sys + + mov bx,800h + mov es,bx + +LoadFile: + push ax + call IsFat12 + pop ax + jnc LoadFile2 + cmp ax,0ff8h ; Check to see if this is the last cluster in the chain + jmp LoadFile3 +LoadFile2: + cmp ax,0fff8h +LoadFile3: + jae LoadFile_Done ; If so continue, if not then read then next one + push ax + xor bx,bx ; Load ROSLDR starting at 0000:8000h + push es + call [bp-ReadClusterOffset] + pop es + + xor bx,bx + mov bl,BYTE [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 + + call IsFat12 + pop ax + push es + jnc LoadFile4 + call GetFatEntry12 ; Get the next entry + jmp LoadFile5 +LoadFile4: + call GetFatEntry16 +LoadFile5: + pop es + + jmp LoadFile ; Load the next cluster (if any) + +LoadFile_Done: + mov dl,BYTE [BYTE bp+BootDrive] ; Load the boot drive into DL + push WORD 0x0000 + push WORD 0x8000 ; We will do a far return to 0000:8000h + retf ; Transfer control to ROSLDR + + +; Reads the entire FAT into memory at 7000:0000 +ReadFatIntoMemory: + mov ax,WORD [BYTE bp+HiddenSectors] + mov dx,WORD [BYTE bp+HiddenSectors+2] + add ax,WORD [BYTE bp+ReservedSectors] + adc dx,byte 0 + mov cx,WORD [BYTE bp+SectorsPerFat] + mov bx,7000h + mov es,bx + xor bx,bx + call [bp-ReadSectorsOffset] + ret + + +; Returns the FAT entry for a given cluster number for 16-bit FAT +; On entry AX has cluster number +; On return AX has FAT entry for that cluster +GetFatEntry16: + + mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes) + mul cx + shl dx,0fh + + mov bx,7000h + add bx,dx + mov es,bx + mov bx,ax ; Restore FAT entry offset + mov ax,WORD [es:bx] ; Get FAT entry + + ret + + +; Returns the FAT entry for a given cluster number for 12-bit FAT +; On entry AX has cluster number +; On return AX has FAT entry for that cluster +GetFatEntry12: + + push ax + mov cx,ax + shr ax,1 + add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits) + + mov bx,7000h + mov es,bx + mov bx,ax ; Put FAT entry offset into BX + mov ax,WORD [es:bx] ; Get FAT entry + pop cx ; Get cluster number from stack + and cx,1 + jz UseLow12Bits + and ax,0fff0h + shr ax,4 + jmp GetFatEntry12_Done + +UseLow12Bits: + and ax,0fffh + +GetFatEntry12_Done: + + ret + + +; Returns CF = 1 if this is a FAT12 file system +; Otherwise CF = 0 for FAT16 +IsFat12: + + mov bx,[BYTE bp-DataAreaStartLow] + mov cx,[BYTE bp-DataAreaStartHigh] + ; CX:BX now has the number of the starting sector of the data area + + xor dx,dx + mov ax,WORD [BYTE bp+TotalSectors] + cmp ax,byte 0 + jnz IsFat12_2 + mov ax,WORD [BYTE bp+TotalSectorsBig] + mov dx,WORD [BYTE bp+TotalSectorsBig+2] + + ; DX:AX now contains the number of sectors on the volume +IsFat12_2: + sub ax,bx ; Subtract data area start sector + sub dx,cx ; from total sectors of volume + + ; DX:AX now contains the number of data sectors on the volume + movzx bx,BYTE [BYTE bp+SectsPerCluster] + div bx + ; AX now has the number of clusters on the volume + stc + cmp ax,4085 + jb IsFat12_Done + clc + +IsFat12_Done: + ret + + + +msgLoading db 'Loading FreeLoader...',0dh,0ah,0 + + times 510-($-$$) db 0 ; Pad to 510 bytes + dw 0aa55h ; BootSector signature diff --git a/freeldr/freeldr/debug.c b/freeldr/freeldr/debug.c index 77cedc5e1a3..b94189193d1 100644 --- a/freeldr/freeldr/debug.c +++ b/freeldr/freeldr/debug.c @@ -28,7 +28,7 @@ // DPRINT_UI | DPRINT_DISK | DPRINT_CACHE; ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | DPRINT_UI | DPRINT_DISK; -//ULONG DebugPrintMask = DPRINT_CACHE; +//ULONG DebugPrintMask = DPRINT_INIFILE; #define SCREEN 0 #define RS232 1 @@ -41,9 +41,9 @@ ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | #define BOCHS_OUTPUT_PORT 0xe9 -ULONG DebugPort = RS232; +//ULONG DebugPort = RS232; //ULONG DebugPort = SCREEN; -//ULONG DebugPort = BOCHS; +ULONG DebugPort = BOCHS; ULONG ComPort = COM1; //ULONG BaudRate = 19200; ULONG BaudRate = 115200; diff --git a/freeldr/freeldr/freeldr.c b/freeldr/freeldr/freeldr.c index 5e4b1c435b3..f651897dbc0 100644 --- a/freeldr/freeldr/freeldr.c +++ b/freeldr/freeldr/freeldr.c @@ -107,6 +107,7 @@ VOID BootMain(VOID) MessageBox("Press ENTER to reboot.\n"); goto reboot; } + TimeOut = -1; // Try to open the operating system section in the .ini file if (!IniOpenSection(OperatingSystemSectionNames[SelectedOperatingSystem], &SectionId)) diff --git a/freeldr/freeldr/mm/init.c b/freeldr/freeldr/mm/init.c index 319ec6a50bd..0d93349d3fa 100644 --- a/freeldr/freeldr/mm/init.c +++ b/freeldr/freeldr/mm/init.c @@ -32,7 +32,6 @@ PVOID HeapBaseAddress = NULL; ULONG HeapLengthInBytes = 0; ULONG HeapMemBlockCount = 0; PMEMBLOCK HeapMemBlockArray = NULL; -ULONG Stack; VOID InitMemoryManager(VOID) { @@ -42,6 +41,12 @@ VOID InitMemoryManager(VOID) // Round up to the next page of memory RealFreeLoaderModuleEnd = ROUND_UP(FreeLoaderModuleEnd, 4096); + // FIXME: + // Add extra space for .data & .bss sections + // which are listed after FreeLoaderModuleEnd + // because it is in the .text section. + // I need to have everything in one section... + RealFreeLoaderModuleEnd += 0x2000; BaseAddress = RealFreeLoaderModuleEnd; Length = (MAXLOWMEMADDR - RealFreeLoaderModuleEnd); @@ -64,22 +69,17 @@ VOID InitMemoryManager(VOID) // Adjust the heap length so we can reserve // enough storage space for the MEMBLOCK array Length -= (MemBlocks * sizeof(MEMBLOCK)); - DbgPrint((DPRINT_MEMORY, "We get here.\n")); // Initialize our tracking variables HeapBaseAddress = (PVOID)BaseAddress; HeapLengthInBytes = Length; HeapMemBlockCount = (HeapLengthInBytes / MEM_BLOCK_SIZE); HeapMemBlockArray = (PMEMBLOCK)(HeapBaseAddress + HeapLengthInBytes); - DbgPrint((DPRINT_MEMORY, "We get here2.\n")); // Clear the memory - __asm__("movl %esp,_Stack"); - DbgPrint((DPRINT_MEMORY, "HeapBaseAddress: 0x%x HeapLengthInBytes: %d Stack: %d.\n", HeapBaseAddress, HeapLengthInBytes, Stack)); + DbgPrint((DPRINT_MEMORY, "HeapBaseAddress: 0x%x HeapLengthInBytes: %d\n", HeapBaseAddress, HeapLengthInBytes)); RtlZeroMemory(HeapBaseAddress, HeapLengthInBytes); - DbgPrint((DPRINT_MEMORY, "We get here3.\n")); RtlZeroMemory(HeapMemBlockArray, (HeapMemBlockCount * sizeof(MEMBLOCK))); - DbgPrint((DPRINT_MEMORY, "We get here4.\n")); #ifdef DEBUG DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount)); diff --git a/freeldr/freeldr/rules.mk b/freeldr/freeldr/rules.mk index 521c9a40a31..e66cb53f881 100644 --- a/freeldr/freeldr/rules.mk +++ b/freeldr/freeldr/rules.mk @@ -18,12 +18,13 @@ # -CC = gcc -LD = ld -AR = ar -RM = cmd /C del -CP = cmd /C copy -MAKE = make +CC = gcc +LD = ld +AR = ar +RM = cmd /C del +CP = cmd /C copy +MAKE = make +NASM_CMD = nasm # For a release build uncomment this line #FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -I../../ -O3 diff --git a/freeldr/freeldr/ui/tui.c b/freeldr/freeldr/ui/tui.c index 3ed5257e67d..cb19a6ac783 100644 --- a/freeldr/freeldr/ui/tui.c +++ b/freeldr/freeldr/ui/tui.c @@ -724,6 +724,11 @@ void ShowMessageBoxesInSection(PUCHAR SectionName) UCHAR SettingValue[80]; ULONG SectionId; + // + // Zero out message line text + // + strcpy(szMessageBoxLineText, ""); + if (!IniOpenSection(SectionName, &SectionId)) { sprintf(SettingName, "Section %s not found in freeldr.ini.\n", SectionName);