BIOS Int 13h Extensions Support
authorBrian Palmer <brianp@sginet.com>
Thu, 15 Nov 2001 07:48:33 +0000 (07:48 +0000)
committerBrian Palmer <brianp@sginet.com>
Thu, 15 Nov 2001 07:48:33 +0000 (07:48 +0000)
New .ini file format (sort of) - changed some parameter names, etc.
More efficient .ini file parsing code
More efficient use of memory, smaller image file
Total rewrite of file system code (the old stuff sucked)
VFAT Long File Names now supported!
ReactOS is the only boot type supported currently, disabled all others (temporarily)

svn path=/trunk/; revision=2372

34 files changed:
freeldr/FREELDR.INI
freeldr/Makefile
freeldr/bootsect/Makefile
freeldr/bootsect/fat.asm
freeldr/bootsect/fat32.asm
freeldr/freeldr/Makefile
freeldr/freeldr/asmcode.S
freeldr/freeldr/asmcode.h
freeldr/freeldr/debug.c
freeldr/freeldr/debug.h
freeldr/freeldr/fat.c [new file with mode: 0644]
freeldr/freeldr/fat.h [new file with mode: 0644]
freeldr/freeldr/freeldr.c
freeldr/freeldr/freeldr.h
freeldr/freeldr/fs.c
freeldr/freeldr/fs.h
freeldr/freeldr/fs_fat.c [deleted file]
freeldr/freeldr/linux.c
freeldr/freeldr/memory.c
freeldr/freeldr/menu.c
freeldr/freeldr/menu.h
freeldr/freeldr/miscboot.c
freeldr/freeldr/multiboot.c
freeldr/freeldr/options.c
freeldr/freeldr/oslist.c [new file with mode: 0644]
freeldr/freeldr/oslist.h [new file with mode: 0644]
freeldr/freeldr/parseini.c
freeldr/freeldr/parseini.h
freeldr/freeldr/reactos.c
freeldr/freeldr/stdlib.c
freeldr/freeldr/stdlib.h
freeldr/freeldr/tui.c
freeldr/freeldr/tui.h
freeldr/notes.txt

index c54291d..a10095e 100644 (file)
 
 [FREELOADER]
 MessageLine=Welcome to FreeLoader!
-MessageLine=Copyright (c) 2000 by Brian Palmer <brianp@sginet.com>
+MessageLine=Copyright (c) 2001 by Brian Palmer <brianp@sginet.com>
 MessageLine=
 MessageBox=Edit your FREELDR.INI file to change your boot settings.
+OS=ReactOS (HD)
+OS=ReactOS (Floppy)
+#OS=ReactOS (Debug)
+#OS=Linux
+OS=3« Floppy (A:)
+OS=Microsoft Windows (C:)
+OS=Drive D:
+DefaultOS=ReactOS (Floppy)
+TimeOut=10
+
+[Display]
 TitleText=Boot Menu
 StatusBarColor=Cyan
 StatusBarTextColor=Black
@@ -89,18 +100,11 @@ MenuColor=Blue
 TextColor=Yellow
 SelectedTextColor=Black
 SelectedColor=Gray
-OS=ReactOS (HD)
-OS=ReactOS (Floppy)
-#OS=ReactOS (Debug)
-#OS=Linux
-OS=3« Floppy (A:)
-OS=Microsoft Windows (C:)
-OS=Drive D:
-#TimeOut=0
 
 # Load ReactOS from harddisk (drive C:)
 #  - does not work on large harddisks
 [ReactOS (HD)]
+Name="ReactOS (HardDrive)"
 BootType=ReactOS
 SystemPath=multi(0)disk(0)rdisk(0)partition(1)\reactos
 Options=/DEBUGPORT=SCREEN
@@ -110,14 +114,16 @@ Driver=VFATFS.SYS
 
 # Load ReactOS from floppy (drive A:)
 [ReactOS (Floppy)]
+Name="ReactOS (Floppy)"
 BootType=ReactOS
 SystemPath=multi(0)disk(0)fdisk(0)
 Options=/DEBUGPORT=SCREEN
-Kernel=NTOSKRNL.EXE
-Driver=IDE.SYS
-Driver=VFATFS.SYS
+Kernel=\reactos\NTOSKRNL.EXE
+Driver=\reactos\IDE.SYS
+Driver=\reactos\VFATFS.SYS
 
 #[ReactOS (Debug)]
+#Name="ReactOS (Debug)"
 #BootType=ReactOS
 #BootDrive=0
 #Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200
@@ -126,20 +132,24 @@ Driver=VFATFS.SYS
 #Driver=\DRIVERS\VFATFS.SYS
 
 #[Linux]
+#Name="Linux"
 # Linux boot type not implemented yet
 #BootType=Partition
 #BootDrive=0x80
 #BootPartition=2
 
 [3« Floppy (A:)]
+Name="3« Floppy (A:)"
 BootType=Drive
 BootDrive=0
 
 [Microsoft Windows (C:)]
+Name="Microsoft Windows (C:)"
 BootType=Drive
 BootDrive=0x80
 
 [Drive D:]
+Name="Drive D:"
 BootType=Partition
 BootDrive=0x81
 BootPartition=1
index 63239b0..fa8a21a 100644 (file)
 #
        
 
-export CC      = gcc
-export LD      = ld
-export AR      = ar
-export RM      = cmd /C del
-export CP      = cmd /C copy
+export CC              = gcc
+export LD              = ld
+export AR              = ar
+export RM              = cmd /C del
+export CP              = cmd /C copy
 export NASM_CMD        = nasm
-export MAKE    = make
+export MAKE            = make
 
 .PHONY : bootsect freeldr install clean
 
index a0c5f8d..ebde83f 100644 (file)
 #  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
 
-
-export CC = gcc
-export LD = ld
-export AR = ar
-export RM = cmd /C del
-export CP = cmd /C copy
-export NASM_CMD = nasm
+export CC              = gcc
+export LD              = ld
+export AR              = ar
+export RM              = cmd /C del
+export CP              = cmd /C copy
+export NASM_CMD        = nasm
 
 .PHONY : clean
 
index ce44006..c541c93 100644 (file)
@@ -256,7 +256,7 @@ Done:
 
 msgDiskError db 'Disk error',0dh,0ah,0
 msgFreeLdr   db 'FREELDR.SYS not found',0dh,0ah,0
-msgAnyKey    db 'Press any key to continue.',0dh,0ah,0
+msgAnyKey    db 'Press any key to restart',0dh,0ah,0
 filename     db 'FREELDR SYS'
 
         times 510-($-$$) db 0   ; Pad to 510 bytes
@@ -272,11 +272,34 @@ filename     db 'FREELDR SYS'
 
 
 LoadFile:
+
+               push ax                                                 ; First save AX - the start cluster of freeldr.sys
+
+
+               ; Lets save the contents of the screen
+               ; from B800:0000 to 9000:8000
+               push ds
+               mov  ax,0b800h
+               mov  ds,ax
+               xor  si,si
+               mov  ax,9800h
+               mov  es,ax
+               xor  di,di
+               mov  cx,2000                                    ; Copy 2000 characters [words] (screen is 80x25)
+               rep  movsw                                              ; 2 bytes a character (one is the attribute byte)
+               pop  ds
+
+               mov  ah,03h                                             ; AH = 03h
+               xor  bx,bx                                              ; BH = video page
+               int  10h                                                ; BIOS Int 10h Func 3 - Read Cursor Position and Size
+               mov  [es:di],dx                                 ; DH = row, DL = column
+
                ; Display "Loading FreeLoader..." message
-               push ax
-        mov  si,msgLoading      ; Loading message
-        call PutChars           ; Display it
-               pop  ax
+        mov  si,msgLoading                             ; Loading message
+        call PutChars                                  ; Display it
+
+
+               pop  ax                                                 ; Restore AX
 
                ; AX has start cluster of freeldr.sys
                push ax
index cdf935b..6126418 100644 (file)
@@ -2,7 +2,8 @@
 ; FAT32 Boot Sector
 ; Copyright (c) 1998, 2000, 2001 Brian Palmer
 
-org 7c00h
+;org 7c00h
+org 0
 
 segment .text
 
@@ -14,15 +15,15 @@ start:
 
 OEMName                                db 'FrLdr1.0'
 BytesPerSector         dw 512
-SectsPerCluster                db 1
+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 18
-NumberOfHeads          dw 2
+SectorsPerTrack                dw 0
+NumberOfHeads          dw 0
 HiddenSectors          dd 0
 TotalSectorsBig                dd 0
 ; FAT32 Inserted Info
@@ -44,122 +45,209 @@ 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 ss,ax
-        mov sp,7c00h            ; Setup a stack
+               mov bp,ax
+        mov sp,ax               ; Setup a stack
         mov ax,cs               ; 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 [BootDrive],dl      ; Save the boot drive
-        xor ax,ax               ; Zero out AX
 
-        cmp    word [TotalSectors],byte 0x00   ; Check the old 16-bit value of TotalSectors
-        jnz    ErrBoot                                                 ; If it is non-zero then exit with an error
 
-        cmp word [FSVersion],byte 0x00         ; Check the file system version word
-        ja ErrBoot                                                     ; If it is not zero then exit with an error
 
 
-        ; Reset disk controller
-        int 13h         
-        jnc LoadExtraBootCode
-        jmp BadBoot             ; Reset failed...
+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]
-               xor  dx,dx
-               mov  ax,0eh
-        add  ax,WORD [HiddenSectors] 
-        adc  dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors 
+               ; sector 14 into memory at [9000:0200h]
+               mov  eax,0eh
+        add  eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors 
                mov  cx,1
-        mov  bx,7e0h
-        mov  es,bx                             ; Read sector to [0000:7e00h]
-               xor  bx,bx
+        mov  bx,9000h
+        mov  es,bx                                                             ; Read sector to [9000:0200h]
+               mov  bx,0200h
                call ReadSectors
                jmp  StartSearch
 
 
 
-
 ; Reads logical sectors into [ES:BX]
-; DX:AX has logical sector number to read
+; EAX 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 [SectorsPerTrack]
-        xchg ax,cx                    
-        div  WORD [SectorsPerTrack]    ; Divide logical by SectorsPerTrack
-        inc  dx                        ; Sectors numbering starts at 1 not 0
-        xchg cx,dx
-        div  WORD [NumberOfHeads]      ; Number of heads
-        mov  dh,dl                     ; Head to DH, drive to DL
-        mov  dl,[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
+               cmp eax,DWORD [BiosCHSDriveSize]                ; 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 eax                                                                ; Put 64-bit logical 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
+
+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   PrintDiskError                                             ; If the read failed then abort
+
+               add  sp,0x10                                                    ; Remove disk address packet from stack
+
+               popad                                                                   ; Restore sector count & logical sector number
+
+        inc  eax                                                               ; Increment sector to read
+        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]
+; EAX has logical sector number to read
+; CX has number of sectors to read
+ReadSectorsCHS:
+        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   BadBoot
+        jc    PrintDiskError                                           ; If the read failed then abort
 
-        pop  cx
-        pop  dx
-        pop  ax
-        inc  ax       ;Increment Sector to Read
-        jnz  NoCarry
-        inc  dx
+        popad
 
+        inc   eax                                                                      ; Increment Sector to Read
 
-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
+        mov   dx,es
+        add   dx,byte 20h                                                      ; Increment read buffer for next sector
+        mov   es,dx
+
+        loop  ReadSectorsCHS                                           ; Read next sector
 
         ret   
 
 
 
 
-; Displays a bad boot message
+; Displays a disk error 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
+PrintDiskError:
+        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
+; Displays a file system error message
 ; And reboots
-ErrBoot:
-        mov  si,msgFreeLdr      ; FreeLdr not found message
-        call PutChars           ; Display it
-        mov  si,msgAnyKey       ; Press any key message
-        call PutChars           ; Display it
+PrintFileSystemError:
+        mov  si,msgFileSystemError             ; FreeLdr not found message
+        call PutChars                                  ; Display it
+        mov  si,msgAnyKey                              ; Press any key message
+        call PutChars                                  ; Display it
 
 Reboot:
         xor ax,ax       
-        int 16h                 ; Wait for a keypress
-        int 19h                 ; Reboot
+        int 16h                                                        ; Wait for a keypress
+        int 19h                                                        ; Reboot
 
 PutChars:
         lodsb
@@ -172,10 +260,13 @@ PutChars:
 Done:
         retn
 
-msgDiskError db 'Disk error',0dh,0ah,0
-msgFreeLdr   db 'FREELDR.SYS not found',0dh,0ah,0
-msgAnyKey    db 'Press any key to continue.',0dh,0ah,0
-filename     db 'FREELDR SYS'
+
+
+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 510-($-$$) db 0   ; Pad to 510 bytes
         dw 0aa55h       ; BootSector signature
@@ -190,29 +281,27 @@ filename     db 'FREELDR SYS'
 ; 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
-;
-; Note: Win2k uses sector 12 for this purpose
 
 
 
 StartSearch:
         ; Now we must get the first cluster of the root directory
-               mov  eax,DWORD [RootDirStartCluster]
+               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 BadBoot
-               jmp  ErrBoot
+               jb       ContinueSearch         ; If not continue, if so then we didn't find freeldr.sys
+               jmp  PrintFileNotFound
 ContinueSearch:
-        mov  bx,800h
-        mov  es,bx                             ; Read cluster to [0000:8000h]
+        mov  bx,7e0h
+        mov  es,bx                             ; Read cluster to [0000:7e00h]
         call ReadCluster        ; Read the cluster
 
 
         ; Now we have to find our way through the root directory to
         ; The OSLOADER.SYS file
                xor  bx,bx
-        mov  bl,[SectsPerCluster]
+        mov  bl,[BYTE bp+SectsPerCluster]
                shl  bx,4                               ; BX = BX * 512 / 32
-        mov  ax,800h            ; We loaded at 0800:0000
+        mov  ax,7e0h            ; We loaded at 07e0:0000
         mov  es,ax
         xor  di,di
         mov  si,filename
@@ -221,7 +310,7 @@ ContinueSearch:
         jz   FoundFile          ; If same we found it
         dec  bx
         jnz  FindFile
-        jmp  ErrBoot
+        jmp  PrintFileNotFound
 
 FindFile:
         mov  ax,es              ; We didn't find it in the previous dir entry
@@ -236,36 +325,67 @@ FindFile:
         jnz  FindFile           ; Last entry?
 
                ; Get the next root dir cluster and try again until we run out of clusters
-               mov  eax,DWORD [RootDirStartCluster]
+               mov  eax,DWORD [BYTE bp+RootDirStartCluster]
                call GetFatEntry
-               mov  [RootDirStartCluster],eax
+               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
+               ; Lets save the contents of the screen
+               ; from B800:0000 to 9000:8000
+               pushad
+
+               mov  ax,0b800h
+               mov  ds,ax
+               xor  si,si
+               mov  ax,9800h
+               mov  es,ax
+               xor  di,di
+               mov  cx,2000                                    ; Copy 2000 characters (screen is 80x25)
+               rep  movsw                                              ; 2 bytes a character (one is the attribute byte)
+
+               mov  ah,03h                                             ; AH = 03h
+               xor  bx,bx                                              ; BH = video page
+               int  10h                                                ; BIOS Int 10h Func 3 - Read Cursor Position and Size
+               mov  [es:di],dx                                 ; DH = row, DL = column
+
+                                                                               ; Display "Loading FreeLoader..." message
+        mov  si,msgLoading                             ; Loading message
+        call PutChars                                  ; Display it
+
+               popad
+
+        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
 
-        mov  bx,800h
+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,7e0h
         mov  es,bx
 
-FoundFile2:
+LoadFile:
                cmp  eax,0ffffff8h              ; Check to see if this is the last cluster in the chain
-               jae      FoundFile3                     ; If so continue, if not then read then next one
+               jae      LoadFileDone           ; If so continue, if not then read the next one
                push eax
-        xor  bx,bx              ; Load ROSLDR starting at 0000:8000h
+        xor  bx,bx              ; Load ROSLDR starting at 0000:7e00h
                push es
                call ReadCluster
                pop  es
 
                xor  bx,bx
-        mov  bl,[SectsPerCluster]
+        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
@@ -276,14 +396,13 @@ FoundFile2:
                call GetFatEntry                ; Get the next entry
                pop  es
 
-        jmp  FoundFile2                        ; Load the next cluster (if any)
+        jmp  LoadFile                  ; Load the next cluster (if any)
 
-FoundFile3:
-        mov  dl,[BootDrive]
-        xor  ax,ax
-        push ax
-        mov  ax,8000h
-        push ax                 ; We will do a far return to 0000:8000h
+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
+        push WORD 8000h                        ; We will do a far return to 0000:8000h
         retf                    ; Transfer control to ROSLDR
 
 
@@ -292,57 +411,52 @@ FoundFile3:
 ; 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
+               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 [BytesPerSector]
+               movzx ebx,WORD [BYTE bp+BytesPerSector]
                push  ebx
-               div   ebx                                               ; FAT Sector Number = EAX / BytesPerSector
-               movzx ebx,WORD [ReservedSectors]
-               add   eax,ebx                                   ; FAT Sector Number += ReservedSectors
-               mov   ebx,DWORD [HiddenSectors]
-               add   eax,ebx                                   ; FAT Sector Number += HiddenSectors
+               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 [ExtendedFlags]  ; Get extended flags and put into ebx
-               and   bx,0x0f                                   ; Mask off upper 8 bits
-               jz    GetFatEntry2                              ; If fat is mirrored then skip fat calcs
-               cmp   bl,[NumberOfFats]                 ; Compare bl to number of fats
-               jc    GetFatEntry1
-               jmp   ErrBoot                                   ; If bl is bigger than numfats exit with error
-GetFatEntry1:
-               mov   edx,eax                                   ; Put logical FAT sector number in edx
-               mov   eax,[SectorsPerFatBig]    ; Get the number of sectors occupied by one fat in eax
-               mul   ebx                                               ; Multiplied by the active FAT index we have in ebx
-               add   eax,edx                                   ; Add the current FAT sector offset
-
-GetFatEntry2:
+               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
-               ror   eax,16
-               mov   dx,ax
-               ror   eax,16
-               ; DX:AX holds logical FAT sector number
+               ; EAX holds logical FAT sector number
         mov  bx,7000h
         mov  es,bx
-        xor  bx,bx              ; We will load it to [7000:0000h]
+        xor  bx,bx                                                             ; We will load it to [7000:0000h]
                mov  cx,1
                call ReadSectors
-               jnc  GetFatEntry3
-               jmp  BadBoot
-GetFatEntry3:
         mov  bx,7000h
         mov  es,bx
                pop  ecx
-               mov  eax,DWORD [es:ecx]         ; Get FAT entry
-               and  eax,0fffffffh                      ; Mask off reserved bits
+               mov  eax,DWORD [es:ecx]                                 ; Get FAT entry
+               and  eax,0fffffffh                                              ; Mask off reserved bits
 
                ret
 
@@ -354,27 +468,38 @@ ReadCluster:
                dec   eax
                dec   eax
                xor   edx,edx
-               movzx ebx,BYTE [SectsPerCluster]
+               movzx ebx,BYTE [BYTE bp+SectsPerCluster]
                mul   ebx
                push  eax
                xor   edx,edx
-               movzx eax,BYTE [NumberOfFats]
-               mul   DWORD [SectorsPerFatBig]
-               movzx ebx,WORD [ReservedSectors]
+               movzx eax,BYTE [BYTE bp+NumberOfFats]
+               mul   DWORD [BYTE bp+SectorsPerFatBig]
+               movzx ebx,WORD [BYTE bp+ReservedSectors]
                add   eax,ebx
-               add   eax,DWORD [HiddenSectors]
+               add   eax,DWORD [BYTE bp+HiddenSectors]
                pop   ebx
                add   eax,ebx                   ; EAX now contains the logical sector number of the cluster
-               ror   eax,16
-               mov   dx,ax
-               ror   eax,16
         xor   bx,bx                            ; We will load it to [ES:0000], ES loaded before function call
-               movzx cx,BYTE [SectsPerCluster]
+               movzx cx,BYTE [BYTE bp+SectsPerCluster]
                call  ReadSectors
                ret
 
-        times 998-($-$$) db 0   ; Pad to 998 bytes
 
+; 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
index 8823afa..6ade1ca 100644 (file)
@@ -25,17 +25,17 @@ export RM = cmd /C del
 export CP = cmd /C copy
 
 #FLAGS = -Wall -nostdinc -fno-builtin
-#FLAGS = -Wall -fno-builtin -DDEBUG
-FLAGS = -Wall -fno-builtin
+FLAGS = -Wall -fno-builtin -DDEBUG
+#FLAGS = -Wall -fno-builtin
 
 # asmcode.o has to be first in the link line because it contains the startup code
-OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
+OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fat.o \
        reactos.o tui.o menu.o miscboot.o options.o linux.o multiboot.o arcname.o \
        mem.o memory.o debug.o parseini.o
 ASM_OBJS = asmcode.o mb.o boot.o mem.o
 C_OBJS = freeldr.o stdlib.o fs.a reactos.o tui.o menu.o miscboot.o options.o linux.o \
        multiboot.o
-C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o
+C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o oslist.o
 
 .PHONY : clean
 
@@ -66,14 +66,14 @@ freeldr.o:  freeldr.c freeldr.h stdlib.h fs.h reactos.h tui.h asmcode.h menu.h mi
 stdlib.o:      stdlib.c freeldr.h stdlib.h Makefile
        $(CC) $(FLAGS) -o stdlib.o -c stdlib.c
 
-fs.a:  fs.o fs_fat.o Makefile
-       $(LD) -r -o fs.a fs.o fs_fat.o
+fs.a:  fs.o fat.o Makefile
+       $(LD) -r -o fs.a fs.o fat.o
 
 fs.o:  fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile
        $(CC) $(FLAGS) -o fs.o -c fs.c
 
-fs_fat.o:      fs_fat.c freeldr.h fs.h stdlib.h tui.h Makefile
-       $(CC) $(FLAGS) -o fs_fat.o -c fs_fat.c
+fat.o: fat.c fat.h freeldr.h fs.h stdlib.h tui.h Makefile
+       $(CC) $(FLAGS) -o fat.o -c fat.c
 
 reactos.o:     reactos.c freeldr.h reactos.h stdlib.h fs.h tui.h multiboot.h Makefile
        $(CC) $(FLAGS) -o reactos.o -c reactos.c
@@ -123,6 +123,9 @@ rs232.o:    rs232.c rs232.h Makefile
 portio.o:      portio.c portio.h Makefile
        $(CC) $(FLAGS) -o portio.o -c portio.c
 
+oslist.o:      oslist.c oslist.h Makefile
+       $(CC) $(FLAGS) -o oslist.o -c oslist.c
+
 clean:
        $(RM) *.o
        $(RM) *.a
index 440a233..f4d2913 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
@@ -376,10 +376,8 @@ EXTERN(_gotoxy)
        ret
 
 /*
- * int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer);
+ * BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer);
  */
-_biosdisk_cmd:
-       .long   0
 _biosdisk_drive:
        .long   0
 _biosdisk_head:
@@ -396,7 +394,7 @@ _biosdisk_retval:
        .long   0
 _biosdisk_retrycount:
        .byte   0
-EXTERN(_biosdisk)
+EXTERN(_BiosInt13Read)
        .code32
 
        push    %ebp
@@ -408,18 +406,16 @@ EXTERN(_biosdisk)
 
        /* Get parameters */
        movl    0x1c(%esp),%eax
-       movl    %eax,_biosdisk_cmd
-       movl    0x20(%esp),%eax
        movl    %eax,_biosdisk_drive
-       movl    0x24(%esp),%eax
+       movl    0x20(%esp),%eax
        movl    %eax,_biosdisk_head
-       movl    0x28(%esp),%eax
+       movl    0x24(%esp),%eax
        movl    %eax,_biosdisk_track
-       movl    0x2c(%esp),%eax
+       movl    0x28(%esp),%eax
        movl    %eax,_biosdisk_sector
-       movl    0x30(%esp),%eax
+       movl    0x2c(%esp),%eax
        movl    %eax,_biosdisk_nsects
-       movl    0x34(%esp),%eax
+       movl    0x30(%esp),%eax
        movl    %eax,_biosdisk_buffer
 
        call    switch_to_real
@@ -429,9 +425,11 @@ EXTERN(_biosdisk)
        movb    $3,_biosdisk_retrycount // Set the retry count to 3
 
 _biosdisk_read:
-       movw    $SCRATCHSEG,%ax                 // Load ES with 7000
-       movw    %ax,%es                                 //  and BX with 0
-       movw    $SCRATCHOFF,%bx                 //  so that the sector gets loaded to 7000:0000
+       movl    _biosdisk_buffer,%eax   // Get buffer address in eax
+       shrl    $4,%eax                                 // Make linear address into segment
+       movw    %ax,%es                                 // Load ES with segment
+       movl    _biosdisk_buffer,%ebx   //  and BX with offset
+       andl    $0x0f,%ebx                              //  so that data gets loaded to [ES:BX]
        movb    _biosdisk_sector,%cl    // Get the sector in CL
     movw       _biosdisk_track,%ax             // Cylinder in AX
        movb    %al,%ch                                 // Now put it in CH
@@ -487,17 +485,6 @@ _biosdisk_done:
 
        .code32
 
-       /* Copy the sector contents from 7000:0000 to the buffer */
-       cld
-       movl    $SCRATCHAREA,%esi
-       movl    _biosdisk_buffer,%edi
-       movl    _biosdisk_nsects,%eax
-       movl    $0x100,%ebx
-       mull    %ebx
-       movl    %eax,%ecx
-       rep
-       movsw
-
        movl    _biosdisk_retval,%eax   // Get return value
        //movl  $1,%eax
 
@@ -509,6 +496,176 @@ _biosdisk_done:
        pop             %ebp
        ret
 
+/*
+ * BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer);
+ */
+_disk_address_packet:
+_packet_size:
+       .byte   0x10
+_packet_reserved:
+       .byte   0
+_packet_sector_count:
+       .word   0
+_packet_transfer_buffer_segment:
+       .word   0
+_packet_transfer_buffer_offset:
+       .word   0
+_packet_lba_sector_number:
+       .quad   0
+_packet_64bit_flat_address:
+       .quad   0
+_int13_extended_drive:
+       .long   0
+_int13_extended_sector_count:
+       .long   0
+_int13_extended_retval:
+       .long   0
+_int13_extended_retrycount:
+       .byte   0
+EXTERN(_BiosInt13ReadExtended)
+       .code32
+
+       push    %ebp
+       push    %esi
+       push    %edi
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       /* Get parameters */
+       movl    0x1c(%esp),%eax
+       movl    %eax,_int13_extended_drive
+       movl    0x20(%esp),%eax
+       movl    %eax,_packet_lba_sector_number
+       movl    0x24(%esp),%eax
+       movw    %ax,_packet_sector_count
+       movl    %eax,_int13_extended_sector_count
+       movl    0x28(%esp),%eax                                                 // Get buffer address in eax
+       shrl    $4,%eax                                                                 // Make linear address into segment
+       movw    %ax,_packet_transfer_buffer_segment             // Save segment
+       movl    0x28(%esp),%eax                                                 // Get buffer address in eax
+       andl    $0x0f,%eax                                                              // Make linear address into offset
+       movw    %ax,_packet_transfer_buffer_offset              // Save offset
+
+       call    switch_to_real
+
+       .code16
+       pushw   %es                                                                             // Save this just in case
+       movb    $3,_int13_extended_retrycount                   // Set the retry count to 3
+
+_int13_extended_read:
+       movb    _int13_extended_drive,%dl                               // Get the drive
+       movb    $42,%ah                                                                 // BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
+       movw    $_disk_address_packet,%si                               // DS:SI -> disk address packet
+       int             $0x13                                                                   // Read sectors
+
+       movb    $1,%al                                                                  // Set the return value to be one (will be set to zero later if needed)
+       jc              _int13_extended_error                                   // Jump if error (CF = 1 on error)
+
+       movl    _int13_extended_sector_count,%eax               // Get the sector count in eax
+       cmpw    _packet_sector_count,%ax                                // See how many sectors we actually read (returned in disk address packet sector count)
+       jne             _int13_extended_error                                   // Jump if not equal
+
+       jmp             _int13_extended_done
+
+
+_int13_extended_error:
+       cmpb    $0x11,%ah                                                               // Check and see if it was a corrected ECC error
+       je              _int13_extended_done                                    // If so then the data is still good, if not fail
+
+       movb    _int13_extended_retrycount,%al                  // Get the current retry count
+       decb    %al                                                                             // Decrement it
+       movb    %al,_int13_extended_retrycount                  // Save it
+       cmpb    $0,%al                                                                  // Is it zero?
+       jz              _int13_extended_zero                                    // Yes, return zero
+
+       movb    $0,%ah                                                                  // BIOS int 0x13, function 0 - Reset Disk System
+       movb    _int13_extended_drive,%dl                               // Get the drive
+       int             $0x13                                                                   // Reset the disk system
+       jmp             _int13_extended_read                                    // Try reading again
+
+_int13_extended_zero:
+       movb    $0,%al                                                                  // We will return zero
+
+_int13_extended_done:
+       movzbl  %al,%eax                                                                // Put the number of sectors read into EAX
+       movl    %eax,_int13_extended_retval                             // Save it as the return value
+
+       popw    %es                                                                             // Restore ES
+       call    switch_to_prot
+
+       .code32
+
+       movl    _int13_extended_retval,%eax                             // Get return value
+       //movl  $1,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %edi
+       pop             %esi
+       pop             %ebp
+       ret
+
+/*
+ * BOOL BiosInt13ExtensionsSupported(ULONG Drive);
+ */
+_int13_extension_check_drive:
+       .long   0
+_int13_extension_check_retval:
+       .long   0
+EXTERN(_BiosInt13ExtensionsSupported)
+       .code32
+
+       push    %ebp
+       push    %esi
+       push    %edi
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       /* Get parameters */
+       movl    0x1c(%esp),%eax
+       movl    %eax,_int13_extension_check_drive
+
+       call    switch_to_real
+
+       .code16
+                                                                                               // Now make sure this computer supports extended reads
+       movb    $0x41,%ah                                                       // AH = 41h
+       movw    $0x55aa,%bx                                                     // BX = 55AAh
+       movb    _int13_extension_check_drive,%dl        // DL = drive (80h-FFh)
+       int             $0x13                                                           // IBM/MS INT 13 Extensions - INSTALLATION CHECK
+       jc              _int13_extension_check_error            // CF set on error (extensions not supported)
+       cmpw    $0x55aa,%bx                                                     // BX = AA55h if installed
+       jne             _int13_extension_check_error
+       testb   $1,%cl                                                          // CX = API subset support bitmap
+       jz              _int13_extension_check_error            // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
+
+                                                                                               // If we get here then we passed all the int13 extension tests
+       movl    $1,_int13_extension_check_retval        // Set return value to TRUE
+       jmp             _int13_extension_check_done
+
+_int13_extension_check_error:
+
+       movl    $0,_int13_extension_check_retval        // The tests failed so return FALSE
+
+_int13_extension_check_done:
+
+       call    switch_to_prot
+
+       .code32
+
+       movl    _int13_extension_check_retval,%eax                              // Get return value
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %edi
+       pop             %esi
+       pop             %ebp
+       ret
+
 /*
  * int getyear(void);
  */
@@ -996,7 +1153,7 @@ EXTERN(_get_heads)
        jmp             _get_heads_done
 
 _get_heads_error:
-       movl    $0x0e,_biosdisk_retval
+       movl    $0xff,_biosdisk_retval
 
 _get_heads_done:
 
@@ -1049,7 +1206,7 @@ EXTERN(_get_cylinders)
        jmp             _get_cylinders_done
 
 _get_cylinders_error:
-       movl    $0x00,_biosdisk_retval
+       movl    $0xff,_biosdisk_retval
 
 _get_cylinders_done:
 
@@ -1098,7 +1255,7 @@ EXTERN(_get_sectors)
        jmp             _get_sectors_done
 
 _get_sectors_error:
-       movl    $0x00,_biosdisk_retval
+       movl    $0xff,_biosdisk_retval
 
 _get_sectors_done:
 
index 11dd28a..7d7381a 100644 (file)
 #define        NR_TASKS        128             /* Space reserved in the GDT for TSS descriptors */
 
 #define STACK16ADDR    0x7000  /* The 16-bit stack top will be at 0000:7000 */
-#define STACK32ADDR    0x60000 /* The 32-bit stack top will be at 6000:0000, or 0x60000 */
+#define STACK32ADDR    0xA0000 /* The 32-bit stack top will be at 9000:FFFF, or 0x9FFFF */
 
-#define FILESYSADDR    0x80000 /* The filesystem data address will be at 8000:0000, or 0x80000 */
+#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */
 
-#define FATCLUSTERBUF  0x60000 /* The fat filesystem's cluster buffer */
-
-#define SCREENBUFFER   0x68000 /* The screen contents will be saved here */
-#define FREELDRINIADDR 0x6C000 /* The freeldr.ini load address will be at 6000:C000, or 0x6C000 */
-
-#define        SCRATCHSEG      0x7000  /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
-#define        SCRATCHOFF      0x0000  /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
-#define        SCRATCHAREA     0x70000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
+#define SCREENBUFFER   0x98000 /* The screen contents will be saved here */
+#define SCREENXCOORD   0x98FA0 /* Address of the byte that contains the current column of the cursor */
+#define SCREENYCOORD   0x98FA1 /* Address of the byte that contains the current row of the cursor */
 
 /* Makes "x" a global variable or label */
 #define EXTERN(x)      .global x; x:
index e65c12b..b8178c8 100644 (file)
 #include "stdlib.h"
 #include "rs232.h"
 #include "parseini.h"
+#include "portio.h"
 
 #ifdef DEBUG
 
-ULONG  DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY;
+ULONG  DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | DPRINT_UI;
 
-#define        SCREEN          0
-#define        RS232           1
+#define        SCREEN                          0
+#define        RS232                           1
+#define BOCHS                          2
 
-#define        COM1            1
-#define        COM2            2
-#define        COM3            3
-#define        COM4            4
+#define        COM1                            1
+#define        COM2                            2
+#define        COM3                            3
+#define        COM4                            4
 
-ULONG  DebugPort = RS232; //SCREEN;
+#define BOCHS_OUTPUT_PORT      0xe9
+
+//ULONG        DebugPort = RS232;
+//ULONG        DebugPort = SCREEN;
+ULONG  DebugPort = BOCHS;
 ULONG  ComPort = COM1;
 ULONG  BaudRate = 19200;
 
@@ -47,13 +53,30 @@ VOID DebugInit(VOID)
        }
 }
 
-void DebugPrint(ULONG Mask, char *format, ...)
+VOID DebugPrintChar(UCHAR Character)
+{
+       if (DebugPort == RS232)
+       {
+               Rs232PortPutByte(Character);
+               if (Character == '\n')
+               {
+                       Rs232PortPutByte('\r');
+               }
+       }
+       else if (DebugPort == BOCHS)
+       {
+               WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
+       }
+       else
+       {
+               putchar(Character);
+       }
+}
+
+VOID DebugPrint(ULONG Mask, char *format, ...)
 {
        int *dataptr = (int *) &format;
        char c, *ptr, str[16];
-       char buffer[512];
-       char *p = buffer;
-       int i;
        
        // Mask out unwanted debug messages
        if (!(Mask & DebugPrintMask))
@@ -65,60 +88,50 @@ void DebugPrint(ULONG Mask, char *format, ...)
 
        while ((c = *(format++)))
        {
-         if (c != '%')
-         {
-       *p = c;
-       p++;
-         }
-         else
-       switch (c = *(format++))
-         {
-         case 'd': case 'u': case 'x':
-               *convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
-
-               ptr = str;
-
-               while (*ptr)
+               if (c != '%')
                {
-                 *p = *(ptr++);
-                 p++;
+                       DebugPrintChar(c);
                }
-               break;
+               else
+               {
+                       switch (c = *(format++))
+                       {
+                       case 'd': case 'u': case 'x':
+                               
+                               *convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
 
-         case 'c':
-               *p = (*(dataptr++))&0xff;
-               p++;
-               break;
+                               ptr = str;
 
-         case 's':
-               ptr = (char *)(*(dataptr++));
+                               while (*ptr)
+                               {
+                                       DebugPrintChar(*(ptr++));
+                               }
+                               break;
 
-               while ((c = *(ptr++)))
-               {
-                 *p = c;
-                 p++;
-               }
-               break;
-         }
-       }
-       *p=0;
+                       case 'c':
 
+                               DebugPrintChar((*(dataptr++))&0xff);
+                               break;
 
-       if (DebugPort == RS232)
-       {
-               for (i=0; buffer[i] != 0; i++)
-               {
-                       Rs232PortPutByte(buffer[i]);
-                       if (buffer[i] == '\n')
-                       {
-                               Rs232PortPutByte('\r');
+                       case 's':
+
+                               ptr = (char *)(*(dataptr++));
+
+                               while ((c = *(ptr++)))
+                               {
+                                       DebugPrintChar(c);
+                               }
+                               break;
                        }
                }
        }
-       else
+
+
+       if (DebugPort == SCREEN)
        {
-               print(buffer);
+               //getch();
        }
+
 }
 
 #endif // defined DEBUG
index 7bade77..57514cf 100644 (file)
 
 #ifdef DEBUG
 
-#define DPRINT_WARNING         0x00000001              // OR this with DebugPrintMask to enable debugger messages and other misc stuff
-#define DPRINT_MEMORY          0x00000002              // OR this with DebugPrintMask to enable memory management messages
-
-VOID   DebugInit(VOID);
-void   DebugPrint(ULONG Mask, char *format, ...);
-
-#define BugCheck0(format) \
-                       { \
-                               DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
-                               DebugPrint(DPRINT_WARNING, format); \
-                               for (;;); \
-                       }
-
-#define BugCheck1(format, arg1) \
-                       { \
-                               DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
-                               DebugPrint(DPRINT_WARNING, format, arg1); \
-                               for (;;); \
-                       }
-
-#define BugCheck2(format, arg1, arg2) \
-                       { \
-                               DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
-                               DebugPrint(DPRINT_WARNING, format, arg1, arg2); \
-                               for (;;); \
-                       }
-
-#define BugCheck3(format, arg1, arg2, arg3) \
-                       { \
-                               DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
-                               DebugPrint(DPRINT_WARNING, format, arg1, arg2, arg3); \
-                               for (;;); \
-                       }
+       #define DPRINT_WARNING          0x00000001              // OR this with DebugPrintMask to enable debugger messages and other misc stuff
+       #define DPRINT_MEMORY           0x00000002              // OR this with DebugPrintMask to enable memory management messages
+       #define DPRINT_FILESYSTEM       0x00000004              // OR this with DebugPrintMask to enable file system messages
+       #define DPRINT_INIFILE          0x00000008              // OR this with DebugPrintMask to enable .ini file messages
+       #define DPRINT_UI                       0x00000010              // OR this with DebugPrintMask to enable user interface messages
+
+       VOID    DebugInit(VOID);
+       VOID    DebugPrint(ULONG Mask, char *format, ...);
+
+       #define DbgPrint(_x_)   DebugPrint _x_
+       #define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); DebugPrint _x_ ; for (;;); }
+
+#else
+
+       #define DbgPrint(_x_)
+       #define BugCheck(_x_)
 
 #endif // defined DEBUG
 
diff --git a/freeldr/freeldr/fat.c b/freeldr/freeldr/fat.c
new file mode 100644 (file)
index 0000000..6ef7ba5
--- /dev/null
@@ -0,0 +1,1163 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "freeldr.h"
+#include "fs.h"
+#include "fat.h"
+#include "stdlib.h"
+#include "tui.h"
+#include "asmcode.h"
+#include "memory.h"
+#include "debug.h"
+
+
+PFAT_BOOTSECTOR                FatVolumeBootSector = NULL;
+PFAT32_BOOTSECTOR      Fat32VolumeBootSector = NULL;
+
+ULONG                          RootDirSectorStart;             // Starting sector of the root directory (fat12/16)
+ULONG                          DataSectorStart;                // Starting sector of the data area
+ULONG                          SectorsPerFat;                  // Sectors per FAT table
+ULONG                          RootDirSectors;                 // Number of sectors of the root directory (fat32)
+
+ULONG                          FatType = 0;                    // FAT12, FAT16, or FAT32
+
+
+BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTrack, ULONG VolumeStartSector, ULONG FatFileSystemType)
+{
+       FatType = FatFileSystemType;
+
+       //
+       // Free any memory previously allocated
+       //
+       if (FatVolumeBootSector != NULL)
+       {
+               FreeMemory(FatVolumeBootSector);
+
+               FatVolumeBootSector = NULL;
+               Fat32VolumeBootSector = NULL;
+       }
+
+       //
+       // Now allocate the memory to hold the boot sector
+       //
+       FatVolumeBootSector = (PFAT_BOOTSECTOR) AllocateMemory(512);
+       Fat32VolumeBootSector = (PFAT32_BOOTSECTOR) FatVolumeBootSector;
+
+       //
+       // Make sure we got the memory
+       //
+       if (FatVolumeBootSector == NULL)
+       {
+               FileSystemError("Out of memory.");
+               return FALSE;
+       }
+
+       //
+       // Now try to read the boot sector
+       // If this fails then abort
+       //
+       if (!BiosInt13Read(DriveNumber, VolumeStartHead, VolumeStartTrack, VolumeStartSector, 1, FatVolumeBootSector))
+       {
+               return FALSE;
+       }
+
+#ifdef DEBUG
+
+       DbgPrint((DPRINT_FILESYSTEM, "Dumping boot sector:\n"));
+
+       if (FatFileSystemType == FAT32)
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR)));
+
+               DbgPrint((DPRINT_FILESYSTEM, "JumpBoot: 0x%x 0x%x 0x%x\n", Fat32VolumeBootSector->JumpBoot[0], Fat32VolumeBootSector->JumpBoot[1], Fat32VolumeBootSector->JumpBoot[2]));
+               DbgPrint((DPRINT_FILESYSTEM, "OemName: %c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->OemName[0], Fat32VolumeBootSector->OemName[1], Fat32VolumeBootSector->OemName[2], Fat32VolumeBootSector->OemName[3], Fat32VolumeBootSector->OemName[4], Fat32VolumeBootSector->OemName[5], Fat32VolumeBootSector->OemName[6], Fat32VolumeBootSector->OemName[7]));
+               DbgPrint((DPRINT_FILESYSTEM, "BytesPerSector: %d\n", Fat32VolumeBootSector->BytesPerSector));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerCluster: %d\n", Fat32VolumeBootSector->SectorsPerCluster));
+               DbgPrint((DPRINT_FILESYSTEM, "ReservedSectors: %d\n", Fat32VolumeBootSector->ReservedSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "NumberOfFats: %d\n", Fat32VolumeBootSector->NumberOfFats));
+               DbgPrint((DPRINT_FILESYSTEM, "RootDirEntries: %d\n", Fat32VolumeBootSector->RootDirEntries));
+               DbgPrint((DPRINT_FILESYSTEM, "TotalSectors: %d\n", Fat32VolumeBootSector->TotalSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "MediaDescriptor: 0x%x\n", Fat32VolumeBootSector->MediaDescriptor));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerFat: %d\n", Fat32VolumeBootSector->SectorsPerFat));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerTrack: %d\n", Fat32VolumeBootSector->SectorsPerTrack));
+               DbgPrint((DPRINT_FILESYSTEM, "NumberOfHeads: %d\n", Fat32VolumeBootSector->NumberOfHeads));
+               DbgPrint((DPRINT_FILESYSTEM, "HiddenSectors: %d\n", Fat32VolumeBootSector->HiddenSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "TotalSectorsBig: %d\n", Fat32VolumeBootSector->TotalSectorsBig));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerFatBig: %d\n", Fat32VolumeBootSector->SectorsPerFatBig));
+               DbgPrint((DPRINT_FILESYSTEM, "ExtendedFlags: 0x%x\n", Fat32VolumeBootSector->ExtendedFlags));
+               DbgPrint((DPRINT_FILESYSTEM, "FileSystemVersion: 0x%x\n", Fat32VolumeBootSector->FileSystemVersion));
+               DbgPrint((DPRINT_FILESYSTEM, "RootDirStartCluster: %d\n", Fat32VolumeBootSector->RootDirStartCluster));
+               DbgPrint((DPRINT_FILESYSTEM, "FsInfo: %d\n", Fat32VolumeBootSector->FsInfo));
+               DbgPrint((DPRINT_FILESYSTEM, "BackupBootSector: %d\n", Fat32VolumeBootSector->BackupBootSector));
+               DbgPrint((DPRINT_FILESYSTEM, "Reserved: 0x%x\n", Fat32VolumeBootSector->Reserved));
+               DbgPrint((DPRINT_FILESYSTEM, "DriveNumber: 0x%x\n", Fat32VolumeBootSector->DriveNumber));
+               DbgPrint((DPRINT_FILESYSTEM, "Reserved1: 0x%x\n", Fat32VolumeBootSector->Reserved1));
+               DbgPrint((DPRINT_FILESYSTEM, "BootSignature: 0x%x\n", Fat32VolumeBootSector->BootSignature));
+               DbgPrint((DPRINT_FILESYSTEM, "VolumeSerialNumber: 0x%x\n", Fat32VolumeBootSector->VolumeSerialNumber));
+               DbgPrint((DPRINT_FILESYSTEM, "VolumeLabel: %c%c%c%c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->VolumeLabel[0], Fat32VolumeBootSector->VolumeLabel[1], Fat32VolumeBootSector->VolumeLabel[2], Fat32VolumeBootSector->VolumeLabel[3], Fat32VolumeBootSector->VolumeLabel[4], Fat32VolumeBootSector->VolumeLabel[5], Fat32VolumeBootSector->VolumeLabel[6], Fat32VolumeBootSector->VolumeLabel[7], Fat32VolumeBootSector->VolumeLabel[8], Fat32VolumeBootSector->VolumeLabel[9], Fat32VolumeBootSector->VolumeLabel[10]));
+               DbgPrint((DPRINT_FILESYSTEM, "FileSystemType: %c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->FileSystemType[0], Fat32VolumeBootSector->FileSystemType[1], Fat32VolumeBootSector->FileSystemType[2], Fat32VolumeBootSector->FileSystemType[3], Fat32VolumeBootSector->FileSystemType[4], Fat32VolumeBootSector->FileSystemType[5], Fat32VolumeBootSector->FileSystemType[6], Fat32VolumeBootSector->FileSystemType[7]));
+               DbgPrint((DPRINT_FILESYSTEM, "BootSectorMagic: 0x%x\n", Fat32VolumeBootSector->BootSectorMagic));
+       }
+       else
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "sizeof(FAT_BOOTSECTOR) = 0x%x.\n", sizeof(FAT_BOOTSECTOR)));
+
+               DbgPrint((DPRINT_FILESYSTEM, "JumpBoot: 0x%x 0x%x 0x%x\n", FatVolumeBootSector->JumpBoot[0], FatVolumeBootSector->JumpBoot[1], FatVolumeBootSector->JumpBoot[2]));
+               DbgPrint((DPRINT_FILESYSTEM, "OemName: %c%c%c%c%c%c%c%c\n", FatVolumeBootSector->OemName[0], FatVolumeBootSector->OemName[1], FatVolumeBootSector->OemName[2], FatVolumeBootSector->OemName[3], FatVolumeBootSector->OemName[4], FatVolumeBootSector->OemName[5], FatVolumeBootSector->OemName[6], FatVolumeBootSector->OemName[7]));
+               DbgPrint((DPRINT_FILESYSTEM, "BytesPerSector: %d\n", FatVolumeBootSector->BytesPerSector));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerCluster: %d\n", FatVolumeBootSector->SectorsPerCluster));
+               DbgPrint((DPRINT_FILESYSTEM, "ReservedSectors: %d\n", FatVolumeBootSector->ReservedSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "NumberOfFats: %d\n", FatVolumeBootSector->NumberOfFats));
+               DbgPrint((DPRINT_FILESYSTEM, "RootDirEntries: %d\n", FatVolumeBootSector->RootDirEntries));
+               DbgPrint((DPRINT_FILESYSTEM, "TotalSectors: %d\n", FatVolumeBootSector->TotalSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "MediaDescriptor: 0x%x\n", FatVolumeBootSector->MediaDescriptor));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerFat: %d\n", FatVolumeBootSector->SectorsPerFat));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorsPerTrack: %d\n", FatVolumeBootSector->SectorsPerTrack));
+               DbgPrint((DPRINT_FILESYSTEM, "NumberOfHeads: %d\n", FatVolumeBootSector->NumberOfHeads));
+               DbgPrint((DPRINT_FILESYSTEM, "HiddenSectors: %d\n", FatVolumeBootSector->HiddenSectors));
+               DbgPrint((DPRINT_FILESYSTEM, "TotalSectorsBig: %d\n", FatVolumeBootSector->TotalSectorsBig));
+               DbgPrint((DPRINT_FILESYSTEM, "DriveNumber: 0x%x\n", FatVolumeBootSector->DriveNumber));
+               DbgPrint((DPRINT_FILESYSTEM, "Reserved1: 0x%x\n", FatVolumeBootSector->Reserved1));
+               DbgPrint((DPRINT_FILESYSTEM, "BootSignature: 0x%x\n", FatVolumeBootSector->BootSignature));
+               DbgPrint((DPRINT_FILESYSTEM, "VolumeSerialNumber: 0x%x\n", FatVolumeBootSector->VolumeSerialNumber));
+               DbgPrint((DPRINT_FILESYSTEM, "VolumeLabel: %c%c%c%c%c%c%c%c%c%c%c\n", FatVolumeBootSector->VolumeLabel[0], FatVolumeBootSector->VolumeLabel[1], FatVolumeBootSector->VolumeLabel[2], FatVolumeBootSector->VolumeLabel[3], FatVolumeBootSector->VolumeLabel[4], FatVolumeBootSector->VolumeLabel[5], FatVolumeBootSector->VolumeLabel[6], FatVolumeBootSector->VolumeLabel[7], FatVolumeBootSector->VolumeLabel[8], FatVolumeBootSector->VolumeLabel[9], FatVolumeBootSector->VolumeLabel[10]));
+               DbgPrint((DPRINT_FILESYSTEM, "FileSystemType: %c%c%c%c%c%c%c%c\n", FatVolumeBootSector->FileSystemType[0], FatVolumeBootSector->FileSystemType[1], FatVolumeBootSector->FileSystemType[2], FatVolumeBootSector->FileSystemType[3], FatVolumeBootSector->FileSystemType[4], FatVolumeBootSector->FileSystemType[5], FatVolumeBootSector->FileSystemType[6], FatVolumeBootSector->FileSystemType[7]));
+               DbgPrint((DPRINT_FILESYSTEM, "BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic));
+       }
+
+#endif // defined DEBUG
+
+       //
+       // Check the boot sector magic
+       //
+       if (FatVolumeBootSector->BootSectorMagic != 0xaa55)
+       {
+               FileSystemError("Invalid boot sector magic (0xaa55)");
+               return FALSE;
+       }
+
+       SetDriveGeometry(get_cylinders(DriveNumber), get_heads(DriveNumber), get_sectors(DriveNumber), FatVolumeBootSector->BytesPerSector);
+       SetVolumeProperties(FatVolumeBootSector->HiddenSectors);
+
+       //
+       // Check the FAT cluster size
+       // We do not support clusters bigger than 64k
+       //
+       if ((FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector) > (64 * 1024))
+       {
+               FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this.");
+               return FALSE;
+       }
+
+       //
+       // Clear our variables
+       //
+       RootDirSectorStart = 0;
+       DataSectorStart = 0;
+       SectorsPerFat = 0;
+       RootDirSectors = 0;
+
+       //
+       // Get the sectors per FAT,
+       // root directory starting sector,
+       // and data sector start
+       //
+       if (FatType != FAT32)
+       {
+               SectorsPerFat = FatVolumeBootSector->SectorsPerFat;
+
+               RootDirSectorStart = (FatVolumeBootSector->NumberOfFats * SectorsPerFat) + FatVolumeBootSector->ReservedSectors;
+               RootDirSectors = ((FatVolumeBootSector->RootDirEntries * 32) + (FatVolumeBootSector->BytesPerSector - 1)) / FatVolumeBootSector->BytesPerSector;
+
+               DataSectorStart = FatVolumeBootSector->ReservedSectors + (FatVolumeBootSector->NumberOfFats * FatVolumeBootSector->SectorsPerFat) + RootDirSectors;
+       }
+       else
+       {
+               SectorsPerFat = Fat32VolumeBootSector->SectorsPerFatBig;
+
+               DataSectorStart = FatVolumeBootSector->ReservedSectors + (FatVolumeBootSector->NumberOfFats * Fat32VolumeBootSector->SectorsPerFatBig) + RootDirSectors;
+               
+
+               //
+               // Check version
+               // we only work with version 0
+               //
+               if (Fat32VolumeBootSector->FileSystemVersion != 0)
+               {
+                       FileSystemError("FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+PVOID FatBufferDirectory(UINT32 DirectoryStartCluster, PUINT32 EntryCountPointer, BOOL RootDirectory)
+{
+       UINT32  RootDirectoryStartSector;
+       UINT32  RootDirectorySectorCount;
+       PVOID   DirectoryBuffer;
+       UINT32  DirectorySize;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatBufferDirectory() DirectoryStartCluster = %d RootDirectory = %s\n", DirectoryStartCluster, (RootDirectory ? "TRUE" : "FALSE")));
+
+       //
+       // Calculate the size of the directory
+       //
+       if ((RootDirectory) && (FatType != FAT32))
+       {
+               DirectorySize = (FatVolumeBootSector->RootDirEntries / 32) * 512;
+       }
+       else
+       {
+               if (RootDirectory)
+               {
+                       DirectorySize = (FatCountClustersInChain(Fat32VolumeBootSector->RootDirStartCluster) * Fat32VolumeBootSector->SectorsPerCluster) * Fat32VolumeBootSector->BytesPerSector;
+               }
+               else
+               {
+                       DirectorySize = (FatCountClustersInChain(DirectoryStartCluster) * FatVolumeBootSector->SectorsPerCluster) * FatVolumeBootSector->BytesPerSector;
+               }
+       }
+
+       //
+       // Attempt to allocate memory for directory buffer
+       //
+       DirectoryBuffer = AllocateMemory(DirectorySize);
+
+       if (DirectoryBuffer == NULL)
+       {
+               return NULL;
+       }
+
+       //
+       // Now read directory contents into DirectoryBuffer
+       //
+       if (RootDirectory)
+       {
+               if (FatType == FAT32)
+               {
+                       if (!FatReadClusterChain(Fat32VolumeBootSector->RootDirStartCluster, 0xFFFFFFFF, DirectoryBuffer))
+                       {
+                               FreeMemory(DirectoryBuffer);
+                               return NULL;
+                       }
+               }
+               else
+               {
+                       //
+                       // FAT type is not FAT32 so the root directory comes right after the fat table
+                       //
+                       RootDirectoryStartSector = FatVolumeBootSector->ReservedSectors + (FatVolumeBootSector->NumberOfFats * FatVolumeBootSector->SectorsPerFat);
+                       RootDirectorySectorCount = FatVolumeBootSector->RootDirEntries / 32;
+
+                       if (!ReadMultipleLogicalSectors(RootDirectoryStartSector, RootDirectorySectorCount, DirectoryBuffer))
+                       {
+                               FreeMemory(DirectoryBuffer);
+                               return NULL;
+                       }
+               }
+       }
+       else
+       {
+               if (!FatReadClusterChain(DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer))
+               {
+                       FreeMemory(DirectoryBuffer);
+                       return NULL;
+               }
+       }
+
+       *EntryCountPointer = (DirectorySize / 32);
+
+       return DirectoryBuffer;
+}
+
+BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, UINT32 EntryCount, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
+{
+       ULONG                   CurrentEntry;
+       PDIRENTRY               DirEntry;
+       PLFN_DIRENTRY   LfnDirEntry;
+       UCHAR                   LfnNameBuffer[261];
+       UCHAR                   ShortNameBuffer[13];
+       UINT32                  StartCluster;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName));
+
+       memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
+       memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
+
+       for (CurrentEntry=0; CurrentEntry<EntryCount; CurrentEntry++)
+       {
+               DirEntry = (PDIRENTRY)(DirectoryBuffer + (CurrentEntry * 32) );
+               LfnDirEntry = (PLFN_DIRENTRY)DirEntry;
+
+               //
+               // Check if this is the last file in the directory
+               // If DirEntry[0] == 0x00 then that means all the
+               // entries after this one are unused. If this is the
+               // last entry then we didn't find the file in this directory.
+               //
+               if (DirEntry->FileName[0] == 0x00)
+               {
+                       return FALSE;
+               }
+
+               //
+               // Check if this is a deleted entry or not
+               //
+               if (DirEntry->FileName[0] == 0xE5)
+               {
+                       memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
+                       memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
+                       continue;
+               }
+
+               //
+               // Check if this is a LFN entry
+               // If so it needs special handling
+               //
+               if (DirEntry->Attr == ATTR_LONG_NAME)
+               {
+                       //
+                       // Check to see if this is a deleted LFN entry, if so continue
+                       //
+                       if (LfnDirEntry->SequenceNumber & 0x80)
+                       {
+                               continue;
+                       }
+
+                       //
+                       // Mask off high two bits of sequence number
+                       // and make the sequence number zero-based
+                       //
+                       LfnDirEntry->SequenceNumber &= 0x3F;
+                       LfnDirEntry->SequenceNumber--;
+
+                       //
+                       // Get all 13 LFN entry characters
+                       //
+                       if (LfnDirEntry->Name0_4[0] != 0xFFFF)
+                       {
+                               LfnNameBuffer[0 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[0];
+                       }
+                       if (LfnDirEntry->Name0_4[1] != 0xFFFF)
+                       {
+                               LfnNameBuffer[1 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[1];
+                       }
+                       if (LfnDirEntry->Name0_4[2] != 0xFFFF)
+                       {
+                               LfnNameBuffer[2 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[2];
+                       }
+                       if (LfnDirEntry->Name0_4[3] != 0xFFFF)
+                       {
+                               LfnNameBuffer[3 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[3];
+                       }
+                       if (LfnDirEntry->Name0_4[4] != 0xFFFF)
+                       {
+                               LfnNameBuffer[4 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[4];
+                       }
+                       if (LfnDirEntry->Name5_10[0] != 0xFFFF)
+                       {
+                               LfnNameBuffer[5 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[0];
+                       }
+                       if (LfnDirEntry->Name5_10[1] != 0xFFFF)
+                       {
+                               LfnNameBuffer[6 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[1];
+                       }
+                       if (LfnDirEntry->Name5_10[2] != 0xFFFF)
+                       {
+                               LfnNameBuffer[7 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[2];
+                       }
+                       if (LfnDirEntry->Name5_10[3] != 0xFFFF)
+                       {
+                               LfnNameBuffer[8 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[3];
+                       }
+                       if (LfnDirEntry->Name5_10[4] != 0xFFFF)
+                       {
+                               LfnNameBuffer[9 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[4];
+                       }
+                       if (LfnDirEntry->Name5_10[5] != 0xFFFF)
+                       {
+                               LfnNameBuffer[10 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[5];
+                       }
+                       if (LfnDirEntry->Name11_12[0] != 0xFFFF)
+                       {
+                               LfnNameBuffer[11 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[0];
+                       }
+                       if (LfnDirEntry->Name11_12[1] != 0xFFFF)
+                       {
+                               LfnNameBuffer[12 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[1];
+                       }
+
+                       continue;
+               }
+
+               //
+               // Check for the volume label attribute
+               // and skip over this entry if found
+               //
+               if (DirEntry->Attr & ATTR_VOLUMENAME)
+               {
+                       memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
+                       memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
+                       continue;
+               }
+
+               //
+               // If we get here then we've found a short file name
+               // entry and LfnNameBuffer contains the long file
+               // name or zeroes. All we have to do now is see if the
+               // file name matches either the short or long file name
+               // and fill in the FAT_FILE_INFO structure if it does
+               // or zero our buffers and continue looking.
+               //
+
+               //
+               // Get short file name
+               //
+               FatParseShortFileName(ShortNameBuffer, DirEntry);
+
+               DbgPrint((DPRINT_FILESYSTEM, "Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer));
+               DbgPrint((DPRINT_FILESYSTEM, "Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer));
+
+               //
+               // See if the file name matches either the short or long name
+               //
+               if (((strlen(FileName) == strlen(LfnNameBuffer)) && (stricmp(FileName, LfnNameBuffer) == 0)) ||
+                       ((strlen(FileName) == strlen(ShortNameBuffer)) && (stricmp(FileName, ShortNameBuffer) == 0)))
+               {
+                       //
+                       // We found the entry, now fill in the FAT_FILE_INFO struct
+                       //
+                       FatFileInfoPointer->FileSize = DirEntry->Size;
+                       FatFileInfoPointer->FilePointer = 0;
+
+                       //
+                       // Get the cluster chain
+                       //
+                       StartCluster = ((UINT32)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
+                       FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(StartCluster);
+
+                       //
+                       // See if memory allocation failed
+                       //
+                       if (FatFileInfoPointer->FileFatChain == NULL)
+                       {
+                               return FALSE;
+                       }
+
+                       return TRUE;
+               }
+
+               //
+               // Nope, no match - zero buffers and continue looking
+               //
+               memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
+               memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
+               continue;
+       }
+
+       return FALSE;
+}
+
+/*
+ * FatLookupFile()
+ * This function searches the file system for the
+ * specified filename and fills in a FAT_STRUCT structure
+ * with info describing the file, etc. returns true
+ * if the file exists or false otherwise
+ */
+BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
+{
+       int                             i;
+       ULONG                   NumberOfPathParts;
+       UCHAR                   PathPart[261];
+       PVOID                   DirectoryBuffer;
+       UINT32                  DirectoryStartCluster = 0;
+       ULONG                   DirectoryEntryCount;
+       FAT_FILE_INFO   FatFileInfo;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatLookupFile() FileName = %s\n", FileName));
+
+       memset(FatFileInfoPointer, 0, sizeof(FAT_FILE_INFO));
+
+       //
+       // Check and see if the first character is '\' and remove it if so
+       //
+       while (*FileName == '\\')
+       {
+               FileName++;
+       }
+
+       //
+       // Figure out how many sub-directories we are nested in
+       //
+       NumberOfPathParts = FatGetNumPathParts(FileName);
+
+       //
+       // Loop once for each part
+       //
+       for (i=0; i<NumberOfPathParts; i++)
+       {
+               //
+               // Get first path part
+               //
+               FatGetFirstNameFromPath(PathPart, FileName);
+
+               //
+               // Advance to the next part of the path
+               //
+               for (; (*FileName != '\\') && (*FileName != '\0'); FileName++)
+               {
+               }
+               FileName++;
+
+               //
+               // Buffer the directory contents
+               //
+               DirectoryBuffer = FatBufferDirectory(DirectoryStartCluster, &DirectoryEntryCount, (i == 0) );
+               if (DirectoryBuffer == NULL)
+               {
+                       return FALSE;
+               }
+
+               //
+               // Search for file name in directory
+               //
+               if (!FatSearchDirectoryBufferForFile(DirectoryBuffer, DirectoryEntryCount, PathPart, &FatFileInfo))
+               {
+                       FreeMemory(DirectoryBuffer);
+                       return FALSE;
+               }
+
+               FreeMemory(DirectoryBuffer);
+
+               //
+               // If we have another sub-directory to go then
+               // grab the start cluster and free the fat chain array
+               //
+               if ((i+1) < NumberOfPathParts)
+               {
+                       DirectoryStartCluster = FatFileInfo.FileFatChain[0];
+                       FreeMemory(FatFileInfo.FileFatChain);
+               }
+       }
+
+       memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
+
+       return TRUE;
+}
+
+/*
+ * FatGetNumPathParts()
+ * This function parses a path in the form of dir1\dir2\file1.ext
+ * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
+ */
+ULONG FatGetNumPathParts(PUCHAR Path)
+{
+       ULONG   i;
+       ULONG   num;
+
+       for (i=0,num=0; i<(int)strlen(Path); i++)
+       {
+               if (Path[i] == '\\')
+               {
+                       num++;
+               }
+       }
+       num++;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num));
+
+       return num;
+}
+
+/*
+ * FatGetFirstNameFromPath()
+ * This function parses a path in the form of dir1\dir2\file1.ext
+ * and puts the first name of the path (e.g. "dir1") in buffer
+ * compatible with the MSDOS directory structure
+ */
+VOID FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
+{
+       ULONG   i;
+
+       // Copy all the characters up to the end of the
+       // string or until we hit a '\' character
+       // and put them in Buffer
+       for (i=0; i<(int)strlen(Path); i++)
+       {
+               if (Path[i] == '\\')
+               {
+                       break;
+               }
+               else
+               {
+                       Buffer[i] = Path[i];
+               }
+       }
+
+       Buffer[i] = 0;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer));
+}
+
+/*
+ * FatParseFileName()
+ * This function parses a directory entry name which
+ * is in the form of "FILE   EXT" and puts it in Buffer
+ * in the form of "file.ext"
+ */
+void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry)
+{
+       ULONG   Idx;
+
+       Idx = 0;
+
+       //
+       // Fixup first character
+       //
+       if (DirEntry->FileName[0] == 0x05)
+       {
+               DirEntry->FileName[0] = 0xE5;
+       }
+
+       //
+       // Get the file name
+       //
+       while (Idx < 8)
+       {
+               if (DirEntry->FileName[Idx] == ' ')
+               {
+                       break;
+               }
+
+               Buffer[Idx] = DirEntry->FileName[Idx];
+               Idx++;
+       }
+
+       //
+       // Get extension
+       //
+       if ((DirEntry->FileName[8] != ' '))
+       {
+               Buffer[Idx++] = '.';
+               Buffer[Idx++] = (DirEntry->FileName[8] == ' ') ? '\0' : DirEntry->FileName[8];
+               Buffer[Idx++] = (DirEntry->FileName[9] == ' ') ? '\0' : DirEntry->FileName[9];
+               Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10];
+       }
+
+       //
+       // Null-Terminate string
+       //
+       Buffer[Idx + 4] = '\0';
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatParseShortFileName() ShortName = %s\n", Buffer));
+}
+
+/*
+ * FatGetFatEntry()
+ * returns the Fat entry for a given cluster number
+ */
+DWORD FatGetFatEntry(DWORD nCluster)
+{
+       DWORD   fat = 0;
+       int             FatOffset;
+       int             ThisFatSecNum;
+       int             ThisFatEntOffset;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", nCluster));
+
+       switch(FatType)
+       {
+       case FAT12:
+
+               FatOffset = nCluster + (nCluster / 2);
+               ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
+               ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
+
+               DbgPrint((DPRINT_FILESYSTEM, "FatOffset: %d\n", FatOffset));
+               DbgPrint((DPRINT_FILESYSTEM, "ThisFatSecNum: %d\n", ThisFatSecNum));
+               DbgPrint((DPRINT_FILESYSTEM, "ThisFatEntOffset: %d\n", ThisFatEntOffset));
+
+               if (ThisFatEntOffset == (FatVolumeBootSector->BytesPerSector - 1))
+               {
+                       if (!ReadMultipleLogicalSectors(ThisFatSecNum, 2, DISKREADBUFFER))
+                       {
+                               return NULL;
+                       }
+               }
+               else
+               {
+                       if (!ReadLogicalSector(ThisFatSecNum, DISKREADBUFFER))
+                       {
+                               return NULL;
+                       }
+               }
+
+               fat = *((WORD *) (DISKREADBUFFER + ThisFatEntOffset));
+               if (nCluster & 0x0001) 
+                       fat = fat >> 4; /* Cluster number is ODD */
+               else
+                       fat = fat & 0x0FFF;     /* Cluster number is EVEN */
+
+               break;
+
+       case FAT16:
+               
+               FatOffset = (nCluster * 2);
+               ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
+               ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
+
+               if (!ReadLogicalSector(ThisFatSecNum, DISKREADBUFFER))
+               {
+                       return NULL;
+               }
+
+               fat = *((WORD *) (DISKREADBUFFER + ThisFatEntOffset));
+
+               break;
+
+       case FAT32:
+
+               FatOffset = (nCluster * 4);
+               ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
+               ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
+
+               if (!ReadLogicalSector(ThisFatSecNum, DISKREADBUFFER))
+               {
+                       return NULL;
+               }
+
+               // Get the fat entry
+               fat = (*((DWORD *) (DISKREADBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF;
+
+               break;
+
+       }
+
+       DbgPrint((DPRINT_FILESYSTEM, "FAT entry is 0x%x.\n", fat));
+
+       return fat;
+}
+
+/*
+ * FatOpenFile()
+ * Tries to open the file 'name' and returns true or false
+ * for success and failure respectively
+ */
+FILE* FatOpenFile(PUCHAR FileName)
+{
+       FAT_FILE_INFO           TempFatFileInfo;
+       PFAT_FILE_INFO          FileHandle;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatOpenFile() FileName = %s\n", FileName));
+
+       if (!FatLookupFile(FileName, &TempFatFileInfo))
+       {
+               return NULL;
+       }
+
+       FileHandle = AllocateMemory(sizeof(FAT_FILE_INFO));
+
+       if (FileHandle == NULL)
+       {
+               return NULL;
+       }
+
+       memcpy(FileHandle, &TempFatFileInfo, sizeof(FAT_FILE_INFO));
+
+       return (FILE*)FileHandle;
+}
+
+UINT32 FatCountClustersInChain(UINT32 StartCluster)
+{
+       UINT32  ClusterCount = 0;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() StartCluster = %d\n", StartCluster));
+
+       while (1)
+       {
+               //
+               // If end of chain then break out of our cluster counting loop
+               //
+               if (((FatType == FAT12) && (StartCluster >= 0xff8)) ||
+                       ((FatType == FAT16) && (StartCluster >= 0xfff8)) ||
+                       ((FatType == FAT32) && (StartCluster >= 0x0ffffff8)))
+               {
+                       break;
+               }
+
+               //
+               // Increment count
+               //
+               ClusterCount++;
+
+               //
+               // Get next cluster
+               //
+               StartCluster = FatGetFatEntry(StartCluster);
+       }
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() ClusterCount = %d\n", ClusterCount));
+
+       return ClusterCount;
+}
+
+PUINT32 FatGetClusterChainArray(UINT32 StartCluster)
+{
+       UINT32  ClusterCount;
+       ULONG   ArraySize;
+       PUINT32 ArrayPointer;
+       ULONG   Idx;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetClusterChainArray() StartCluster = %d\n", StartCluster));
+
+       ClusterCount = FatCountClustersInChain(StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array
+       ArraySize = ClusterCount * sizeof(UINT32);
+
+       //
+       // Allocate array memory
+       //
+       ArrayPointer = AllocateMemory(ArraySize);
+
+       if (ArrayPointer == NULL)
+       {
+               return NULL;
+       }
+
+       //
+       // Loop through and set array values
+       //
+       for (Idx=0; Idx<ClusterCount; Idx++)
+       {
+               //
+               // Set current cluster
+               //
+               ArrayPointer[Idx] = StartCluster;
+
+               //
+               // Don't try to get next cluster for last cluster
+               //
+               if (((FatType == FAT12) && (StartCluster >= 0xff8)) ||
+                       ((FatType == FAT16) && (StartCluster >= 0xfff8)) ||
+                       ((FatType == FAT32) && (StartCluster >= 0x0ffffff8)))
+               {
+                       Idx++;
+                       break;
+               }
+
+               //
+               // Get next cluster
+               //
+               StartCluster = FatGetFatEntry(StartCluster);
+       }
+
+       return ArrayPointer;
+}
+
+/*
+ * FatReadCluster()
+ * Reads the specified cluster into memory
+ * and returns the number of bytes read
+ */
+BOOL FatReadCluster(ULONG ClusterNumber, PVOID Buffer)
+{
+       ULONG   ClusterStartSector;
+
+       ClusterStartSector = ((ClusterNumber - 2) * FatVolumeBootSector->SectorsPerCluster) + DataSectorStart;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatReadCluster() ClusterNumber = %d Buffer = 0x%x ClusterStartSector = %d\n", ClusterNumber, Buffer, ClusterStartSector));
+
+       if (!ReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, DISKREADBUFFER))
+       {
+               return FALSE;
+       }
+
+       memcpy(Buffer, DISKREADBUFFER, FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector);
+
+       return TRUE;
+}
+
+/*
+ * FatReadClusterChain()
+ * Reads the specified clusters into memory
+ */
+BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer)
+{
+       ULONG   ClusterStartSector;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
+
+       while (NumberOfClusters > 0)
+       {
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
+               //
+               // Calculate starting sector for cluster
+               //
+               ClusterStartSector = ((StartClusterNumber - 2) * FatVolumeBootSector->SectorsPerCluster) + DataSectorStart;
+
+               //
+               // Read cluster into memory
+               //
+               if (!ReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, DISKREADBUFFER))
+               {
+                       return FALSE;
+               }
+
+               memcpy(Buffer, DISKREADBUFFER, FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector);
+
+               //
+               // Decrement count of clusters left to read
+               //
+               NumberOfClusters--;
+
+               //
+               // Increment buffer address by cluster size
+               //
+               Buffer += (FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector);
+
+               //
+               // Get next cluster
+               //
+               StartClusterNumber = FatGetFatEntry(StartClusterNumber);
+
+               //
+               // If end of chain then break out of our cluster reading loop
+               //
+               if (((FatType == FAT12) && (StartClusterNumber >= 0xff8)) ||
+                       ((FatType == FAT16) && (StartClusterNumber >= 0xfff8)) ||
+                       ((FatType == FAT32) && (StartClusterNumber >= 0x0ffffff8)))
+               {
+                       break;
+               }
+       }
+       
+       return TRUE;
+}
+
+/*
+ * FatReadPartialCluster()
+ * Reads part of a cluster into memory
+ */
+BOOL FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
+{
+       ULONG   ClusterStartSector;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer));
+
+       ClusterStartSector = ((ClusterNumber - 2) * FatVolumeBootSector->SectorsPerCluster) + DataSectorStart;
+
+       if (!ReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, DISKREADBUFFER))
+       {
+               return FALSE;
+       }
+
+       memcpy(Buffer, DISKREADBUFFER + StartingOffset, Length);
+
+       return TRUE;
+}
+
+/*
+ * FatReadFile()
+ * Reads BytesToRead from open file and
+ * returns the number of bytes read in BytesRead
+ */
+BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer)
+{
+       PFAT_FILE_INFO  FatFileInfo = (PFAT_FILE_INFO)FileHandle;
+       UINT32                  ClusterNumber;
+       UINT32                  OffsetInCluster;
+       UINT32                  LengthInCluster;
+       UINT32                  NumberOfClusters;
+       UINT32                  BytesPerCluster;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer));
+
+       if (BytesRead != NULL)
+       {
+               *BytesRead = 0;
+       }
+
+       //
+       // If they are trying to read past the
+       // end of the file then return success
+       // with BytesRead == 0
+       //
+       if (FatFileInfo->FilePointer >= FatFileInfo->FileSize)
+       {
+               return TRUE;
+       }
+
+       //
+       // If they are trying to read more than there is to read
+       // then adjust the amount to read
+       //
+       if ((FatFileInfo->FilePointer + BytesToRead) > FatFileInfo->FileSize)
+       {
+               BytesToRead = (FatFileInfo->FileSize - FatFileInfo->FilePointer);
+       }
+
+       //
+       // Ok, now we have to perform at most 3 calculations
+       // I'll draw you a picture (using nifty ASCII art):
+       //
+       // CurrentFilePointer -+
+       //                     |
+       //    +----------------+
+       //    |
+       // +-----------+-----------+-----------+-----------+
+       // | Cluster 1 | Cluster 2 | Cluster 3 | Cluster 4 |
+       // +-----------+-----------+-----------+-----------+
+       //    |                                    |
+       //    +---------------+--------------------+
+       //                    |
+       // BytesToRead -------+
+       //
+       // 1 - The first calculation (and read) will align
+       //     the file pointer with the next cluster.
+       //     boundary (if we are supposed to read that much)
+       // 2 - The next calculation (and read) will read
+       //     in all the full clusters that the requested
+       //     amount of data would cover (in this case
+       //     clusters 2 & 3).
+       // 3 - The last calculation (and read) would read
+       //     in the remainder of the data requested out of
+       //     the last cluster.
+       //
+
+       BytesPerCluster = (FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector);
+
+       //
+       // Only do the first read if we
+       // aren't aligned on a cluster boundary
+       //
+       if (FatFileInfo->FilePointer % BytesPerCluster)
+       {
+               //
+               // Do the math for our first read
+               //
+               ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
+               ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
+               OffsetInCluster = (FatFileInfo->FilePointer % BytesPerCluster);
+               LengthInCluster = (BytesToRead > (BytesPerCluster - OffsetInCluster)) ? (BytesPerCluster - OffsetInCluster) : BytesToRead;
+
+               //
+               // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+               //
+               if (!FatReadPartialCluster(ClusterNumber, OffsetInCluster, LengthInCluster, Buffer))
+               {
+                       return FALSE;
+               }
+               if (BytesRead != NULL)
+               {
+                       *BytesRead += LengthInCluster;
+               }
+               BytesToRead -= LengthInCluster;
+               FatFileInfo->FilePointer += LengthInCluster;
+               Buffer += LengthInCluster;
+       }
+
+       //
+       // Do the math for our second read (if any data left)
+       //
+       if (BytesToRead > 0)
+       {
+               //
+               // Determine how many full clusters we need to read
+               //
+               NumberOfClusters = (BytesToRead / BytesPerCluster);
+
+               if (NumberOfClusters > 0)
+               {
+                       ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
+                       ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
+
+                       //
+                       // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+                       //
+                       if (!FatReadClusterChain(ClusterNumber, NumberOfClusters, Buffer))
+                       {
+                               return FALSE;
+                       }
+                       if (BytesRead != NULL)
+                       {
+                               *BytesRead += (NumberOfClusters * BytesPerCluster);
+                       }
+                       BytesToRead -= (NumberOfClusters * BytesPerCluster);
+                       FatFileInfo->FilePointer += (NumberOfClusters * BytesPerCluster);
+                       Buffer += (NumberOfClusters * BytesPerCluster);
+               }
+       }
+
+       //
+       // Do the math for our third read (if any data left)
+       //
+       if (BytesToRead > 0)
+       {
+               ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
+               ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
+
+               //
+               // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
+               //
+               if (!FatReadPartialCluster(ClusterNumber, 0, BytesToRead, Buffer))
+               {
+                       return FALSE;
+               }
+               if (BytesRead != NULL)
+               {
+                       *BytesRead += BytesToRead;
+               }
+               BytesToRead -= BytesToRead;
+               FatFileInfo->FilePointer += BytesToRead;
+               Buffer += BytesToRead;
+       }
+
+       return TRUE;
+}
+
+ULONG FatGetFileSize(FILE *FileHandle)
+{
+       PFAT_FILE_INFO  FatFileHandle = (PFAT_FILE_INFO)FileHandle;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetFileSize() FileSize = %d\n", FatFileHandle->FileSize));
+
+       return FatFileHandle->FileSize;
+}
+
+VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer)
+{
+       PFAT_FILE_INFO  FatFileHandle = (PFAT_FILE_INFO)FileHandle;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatSetFilePointer() NewFilePointer = %d\n", NewFilePointer));
+
+       FatFileHandle->FilePointer = NewFilePointer;
+}
+
+ULONG FatGetFilePointer(FILE *FileHandle)
+{
+       PFAT_FILE_INFO  FatFileHandle = (PFAT_FILE_INFO)FileHandle;
+
+       DbgPrint((DPRINT_FILESYSTEM, "FatGetFilePointer() FilePointer = %d\n", FatFileHandle->FilePointer));
+
+       return FatFileHandle->FilePointer;
+}
+
diff --git a/freeldr/freeldr/fat.h b/freeldr/freeldr/fat.h
new file mode 100644 (file)
index 0000000..4444023
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 2001  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FAT_H
+#define __FAT_H
+
+typedef struct _FAT_BOOTSECTOR
+{
+       BYTE    JumpBoot[3];                            // Jump instruction to boot code
+       UCHAR   OemName[8];                                     // "MSWIN4.1" for MS formatted volumes
+       WORD    BytesPerSector;                         // Bytes per sector
+       BYTE    SectorsPerCluster;                      // Number of sectors in a cluster
+       WORD    ReservedSectors;                        // Reserved sectors, usually 1 (the bootsector)
+       BYTE    NumberOfFats;                           // Number of FAT tables
+       WORD    RootDirEntries;                         // Number of root directory entries (fat12/16)
+       WORD    TotalSectors;                           // Number of total sectors on the drive, 16-bit
+       BYTE    MediaDescriptor;                        // Media descriptor byte
+       WORD    SectorsPerFat;                          // Sectors per FAT table (fat12/16)
+       WORD    SectorsPerTrack;                        // Number of sectors in a track
+       WORD    NumberOfHeads;                          // Number of heads on the disk
+       DWORD   HiddenSectors;                          // Hidden sectors (sectors before the partition start like the partition table)
+       DWORD   TotalSectorsBig;                        // This field is the new 32-bit total count of sectors on the volume
+       BYTE    DriveNumber;                            // Int 0x13 drive number (e.g. 0x80)
+       BYTE    Reserved1;                                      // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
+       BYTE    BootSignature;                          // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
+       DWORD   VolumeSerialNumber;                     // Volume serial number
+       UCHAR   VolumeLabel[11];                        // Volume label. This field matches the 11-byte volume label recorded in the root directory
+       UCHAR   FileSystemType[8];                      // One of the strings "FAT12   ", "FAT16   ", or "FAT     "
+
+       BYTE    BootCodeAndData[448];           // The remainder of the boot sector
+
+       WORD    BootSectorMagic;                        // 0xAA55
+       
+} PACKED FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
+
+typedef struct _FAT32_BOOTSECTOR
+{
+       BYTE    JumpBoot[3];                            // Jump instruction to boot code
+       UCHAR   OemName[8];                                     // "MSWIN4.1" for MS formatted volumes
+       WORD    BytesPerSector;                         // Bytes per sector
+       BYTE    SectorsPerCluster;                      // Number of sectors in a cluster
+       WORD    ReservedSectors;                        // Reserved sectors, usually 1 (the bootsector)
+       BYTE    NumberOfFats;                           // Number of FAT tables
+       WORD    RootDirEntries;                         // Number of root directory entries (fat12/16)
+       WORD    TotalSectors;                           // Number of total sectors on the drive, 16-bit
+       BYTE    MediaDescriptor;                        // Media descriptor byte
+       WORD    SectorsPerFat;                          // Sectors per FAT table (fat12/16)
+       WORD    SectorsPerTrack;                        // Number of sectors in a track
+       WORD    NumberOfHeads;                          // Number of heads on the disk
+       DWORD   HiddenSectors;                          // Hidden sectors (sectors before the partition start like the partition table)
+       DWORD   TotalSectorsBig;                        // This field is the new 32-bit total count of sectors on the volume
+       DWORD   SectorsPerFatBig;                       // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
+       WORD    ExtendedFlags;                          // Extended flags (fat32)
+       WORD    FileSystemVersion;                      // File system version (fat32)
+       DWORD   RootDirStartCluster;            // Starting cluster of the root directory (fat32)
+       WORD    FsInfo;                                         // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
+       WORD    BackupBootSector;                       // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
+       BYTE    Reserved[12];                           // Reserved for future expansion
+       BYTE    DriveNumber;                            // Int 0x13 drive number (e.g. 0x80)
+       BYTE    Reserved1;                                      // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
+       BYTE    BootSignature;                          // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
+       DWORD   VolumeSerialNumber;                     // Volume serial number
+       UCHAR   VolumeLabel[11];                        // Volume label. This field matches the 11-byte volume label recorded in the root directory
+       UCHAR   FileSystemType[8];                      // Always set to the string "FAT32   "
+
+       BYTE    BootCodeAndData[420];           // The remainder of the boot sector
+
+       WORD    BootSectorMagic;                        // 0xAA55
+       
+} PACKED FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
+
+/*
+ * Structure of MSDOS directory entry
+ */
+typedef struct //_DIRENTRY
+{
+       UCHAR   FileName[11];   /* Filename + extension */
+       UINT8   Attr;                   /* File attributes */
+       UINT8   ReservedNT;             /* Reserved for use by Windows NT */
+       UINT8   TimeInTenths;   /* Millisecond stamp at file creation */
+       UINT16  CreateTime;             /* Time file was created */
+       UINT16  CreateDate;             /* Date file was created */
+       UINT16  LastAccessDate; /* Date file was last accessed */
+       UINT16  ClusterHigh;    /* High word of this entry's start cluster */
+       UINT16  Time;                   /* Time last modified */
+       UINT16  Date;                   /* Date last modified */
+       UINT16  ClusterLow;             /* First cluster number low word */
+       UINT32  Size;                   /* File size */
+} PACKED DIRENTRY, * PDIRENTRY;
+
+typedef struct
+{
+       UINT8   SequenceNumber;         /* Sequence number for slot */
+       WCHAR   Name0_4[5];                     /* First 5 characters in name */
+       UINT8   EntryAttributes;        /* Attribute byte */
+       UINT8   Reserved;                       /* Always 0 */
+       UINT8   AliasChecksum;          /* Checksum for 8.3 alias */
+       WCHAR   Name5_10[6];            /* 6 more characters in name */
+       UINT16  StartCluster;           /* Starting cluster number */
+       WCHAR   Name11_12[2];           /* Last 2 characters in name */
+} PACKED LFN_DIRENTRY, * PLFN_DIRENTRY;
+
+typedef struct
+{
+       ULONG   FileSize;                       // File size
+       ULONG   FilePointer;            // File pointer
+       PUINT32 FileFatChain;           // File fat chain array
+} FAT_FILE_INFO, * PFAT_FILE_INFO;
+
+
+
+BOOL   FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTrack, ULONG VolumeStartSector, ULONG FatFileSystemType);
+PVOID  FatBufferDirectory(UINT32 DirectoryStartCluster, PUINT32 EntryCountPointer, BOOL RootDirectory);
+BOOL   FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, UINT32 EntryCount, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
+BOOL   FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
+ULONG  FatGetNumPathParts(PUCHAR Path);
+VOID   FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path);
+void   FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry);
+DWORD  FatGetFatEntry(DWORD nCluster);
+FILE*  FatOpenFile(PUCHAR FileName);
+UINT32 FatCountClustersInChain(UINT32 StartCluster);
+PUINT32        FatGetClusterChainArray(UINT32 StartCluster);
+BOOL   FatReadCluster(ULONG ClusterNumber, PVOID Buffer);
+BOOL   FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer);
+BOOL   FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer);
+BOOL   FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
+ULONG  FatGetFileSize(FILE *FileHandle);
+VOID   FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
+ULONG  FatGetFilePointer(FILE *FileHandle);
+
+
+/*BOOL FatLookupFile(char *file, PFAT_STRUCT pFatStruct);
+int            FatGetNumPathParts(char *name);
+BOOL   FatGetFirstNameFromPath(char *buffer, char *name);
+void   FatParseFileName(char *buffer, char *name);
+DWORD  FatGetFatEntry(DWORD nCluster);
+int            FatReadCluster(DWORD nCluster, char *cBuffer);
+int            FatRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer);
+int            Fatfseek(PFAT_STRUCT pFatStruct, DWORD offset);
+
+FILE*  FatOpenFile(PUCHAR FileName);
+BOOL   FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
+ULONG  FatGetFileSize(FILE *FileHandle);
+VOID   FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
+ULONG  FatGetFilePointer(FILE *FileHandle);*/
+
+
+#define        EOF     -1
+
+#define        ATTR_NORMAL             0x00
+#define        ATTR_READONLY   0x01
+#define        ATTR_HIDDEN             0x02
+#define        ATTR_SYSTEM             0x04
+#define        ATTR_VOLUMENAME 0x08
+#define        ATTR_DIRECTORY  0x10
+#define        ATTR_ARCHIVE    0x20
+#define ATTR_LONG_NAME (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMENAME)
+
+#define        FAT12                   1
+#define        FAT16                   2
+#define        FAT32                   3
+
+#endif // #defined __FAT_H
\ No newline at end of file
index 3f45a27..76541de 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
 #include "memory.h"
 #include "parseini.h"
 #include "debug.h"
+#include "oslist.h"
 
 // Variable BootDrive moved to asmcode.S
-//ULONG                        BootDrive = 0;          // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
-ULONG                  BootPartition = 0;      // Boot Partition, 1-4
-BOOL                   UserInterfaceUp = FALSE; // Tells us if the user interface is displayed
+//ULONG                        BootDrive = 0;                                                  // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
+ULONG                  BootPartition = 0;                                              // Boot Partition, 1-4
 
-PUCHAR                 ScreenBuffer = (PUCHAR)(SCREENBUFFER); // Save buffer for screen contents
-int                            CursorXPos = 0; // Cursor's X Position
-int                            CursorYPos = 0; // Cursor's Y Position
+PUCHAR                 ScreenBuffer = (PUCHAR)(SCREENBUFFER);  // Save buffer for screen contents
+ULONG                  CursorXPos = 0;                                                 // Cursor's X Position
+ULONG                  CursorYPos = 0;                                                 // Cursor's Y Position
 
-OSTYPE                 OSList[16];
-int                            nNumOS = 0;
+ULONG  GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount);
+LONG   GetTimeOut(VOID);
 
-int                            nTimeOut = -1;          // Time to wait for the user before booting
-
-void BootMain(void)
+VOID BootMain(VOID)
 {
-       int             i;
-       char    name[1024];
-       char    value[1024];
-       int             nOSToBoot;
+       ULONG   Idx;
+       UCHAR   SettingName[80];
+       UCHAR   SettingValue[80];
+       ULONG   SectionId;
+       ULONG   OperatingSystemCount;
+       PUCHAR  *OperatingSystemSectionNames;
+       PUCHAR  *OperatingSystemDisplayNames;
+       ULONG   DefaultOperatingSystem;
+       LONG    TimeOut;
+       ULONG   SelectedOperatingSystem;
 
        enable_a20();
 
-       SaveScreen(ScreenBuffer);
-       CursorXPos = wherex();
-       CursorYPos = wherey();
-
-       printf("Loading FreeLoader...\n");
+       CursorXPos = (ULONG) *((PUCHAR)(SCREENXCOORD));
+       CursorYPos = (ULONG) *((PUCHAR)(SCREENYCOORD));
 
 #ifdef DEBUG
        DebugInit();
 #endif
 
-       InitMemoryManager((PVOID)0x100000, 0x20000);
+       InitMemoryManager( (PVOID) 0x20000 /* BaseAddress */, 0x70000 /* Length */);
 
        if (!ParseIniFile())
        {
@@ -72,39 +73,63 @@ void BootMain(void)
                return;
        }
 
-       clrscr();
-       hidecursor();
-       // Draw the backdrop and title box
-       DrawBackdrop();
-       UserInterfaceUp = TRUE;
+       if (!OpenSection("FreeLoader", &SectionId))
+       {
+               printf("Section [FreeLoader] not found in freeldr.ini.\n");
+               getch();
+               return;
+       }
 
-       if (nNumOS == 0)
+       if (!InitUserInterface())
        {
-               DrawStatusText(" Press ENTER to reboot");
-               MessageBox("Error: there were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
-               clrscr();
-               showcursor();
-               RestoreScreen(ScreenBuffer);
+               printf("Press any key to reboot.\n");
+               getch();
                return;
        }
+
+       if (!InitOperatingSystemList(&OperatingSystemSectionNames, &OperatingSystemDisplayNames, &OperatingSystemCount))
+       {
+               MessageBox("Press ENTER to reboot.\n");
+               goto reboot;
+       }
        
+       if (OperatingSystemCount == 0)
+       {
+               MessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
+               goto reboot;
+       }
 
-       DrawStatusText(" Press ENTER to continue");
+       DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemSectionNames, OperatingSystemCount);
+       TimeOut = GetTimeOut();
+       
+       //
        // Find all the message box settings and run them
-       for (i=1; i<=GetNumSectionItems("FREELOADER"); i++)
+       //
+       for (Idx=0; Idx<GetNumSectionItems(SectionId); Idx++)
        {
-               ReadSectionSettingByNumber("FREELOADER", i, name, value);
-               if (stricmp(name, "MessageBox") == 0)
-                       MessageBox(value);
-               if (stricmp(name, "MessageLine") == 0)
-                       MessageLine(value);
+               ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
+               
+               if (stricmp(SettingName, "MessageBox") == 0)
+               {
+                       MessageBox(SettingValue);
+               }
+               else if (stricmp(SettingName, "MessageLine") == 0)
+               {
+                       MessageLine(SettingValue);
+               }
        }
 
        for (;;)
        {
-               nOSToBoot = RunMenu();
+               if (!DisplayMenu(OperatingSystemDisplayNames, OperatingSystemCount, DefaultOperatingSystem, TimeOut, &SelectedOperatingSystem))
+               {
+                       MessageBox("Press ENTER to reboot.\n");
+                       return;
+               }
+
+               LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]);
 
-               switch (OSList[nOSToBoot].nOSType)
+               /*switch (OSList[nOSToBoot].nOSType)
                {
                case OSTYPE_REACTOS:
                        LoadAndBootReactOS(OSList[nOSToBoot].name);
@@ -121,13 +146,67 @@ void BootMain(void)
                case OSTYPE_DRIVE:
                        LoadAndBootDrive(nOSToBoot);
                        break;
-               }
-
-               DrawBackdrop();
+               }*/
        }
 
-       MessageBox("Press any key to reboot.");
+       
+reboot:
        RestoreScreen(ScreenBuffer);
        showcursor();
        gotoxy(CursorXPos, CursorYPos);
+       return;
+}
+
+ULONG GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount)
+{
+       UCHAR   DefaultOSText[80];
+       ULONG   SectionId;
+       ULONG   DefaultOS;
+       ULONG   Idx;
+
+       if (!OpenSection("FreeLoader", &SectionId))
+       {
+               return 0;
+       }
+
+       if (ReadSectionSettingByName(SectionId, "DefaultOS", DefaultOSText, 80))
+       {
+               for (Idx=0; Idx<OperatingSystemCount; Idx++)
+               {
+                       if (stricmp(DefaultOSText, OperatingSystemList[Idx]) == 0)
+                       {
+                               DefaultOS = Idx;
+                               break;
+                       }
+               }
+       }
+       else
+       {
+               DefaultOS = 0;
+       }
+
+       return DefaultOS;
+}
+
+LONG GetTimeOut(VOID)
+{
+       UCHAR   TimeOutText[20];
+       ULONG   TimeOut;
+       ULONG   SectionId;
+
+       if (!OpenSection("FreeLoader", &SectionId))
+       {
+               return -1;
+       }
+
+       if (ReadSectionSettingByName(SectionId, "TimeOut", TimeOutText, 20))
+       {
+               TimeOut = atoi(TimeOutText);
+       }
+       else
+       {
+               TimeOut = -1;
+       }
+
+       return TimeOut;
 }
index b7fa0b6..77cde42 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
 #define PWORD  WORD *
 #define VOID   void
 #define PVOID  VOID*
+#define INT8   char
+#define UINT8  unsigned char
+#define INT16  short
+#define UINT16 unsigned short
+#define INT32  long
+#define UINT32 unsigned long
+#define PUINT32        UINT32 *
+#define INT64  long long
+#define UINT64 unsigned long long
 
 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
 
-#define        OSTYPE_REACTOS          1
-#define OSTYPE_LINUX           2
-#define OSTYPE_BOOTSECTOR      3
-#define OSTYPE_PARTITION       4
-#define OSTYPE_DRIVE           5
-
-typedef struct
-{
-       char    name[260];
-       int             nOSType;                        // ReactOS or Linux or a bootsector, etc.
-} OSTYPE, *POSTYPE;
+#define PACKED __attribute__((packed))
 
 extern ULONG           BootDrive;                      // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
 extern ULONG           BootPartition;          // Boot Partition, 1-4
 extern BOOL                    UserInterfaceUp;        // Tells us if the user interface is displayed
 
 extern PUCHAR          ScreenBuffer;           // Save buffer for screen contents
-extern int                     CursorXPos;                     // Cursor's X Position
-extern int                     CursorYPos;                     // Cursor's Y Position
-
-extern OSTYPE          OSList[16]; // The OS list
-extern int                     nNumOS;         // Number of OSes listed
-
-extern int                     nTimeOut;               // Time to wait for the user before booting
+extern ULONG           CursorXPos;                     // Cursor's X Position
+extern ULONG           CursorYPos;                     // Cursor's Y Position
 
 void   BootMain(void);
 
index 8fbd811..8250306 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
 
 #include "freeldr.h"
 #include "fs.h"
+#include "fat.h"
 #include "stdlib.h"
 #include "tui.h"
 #include "asmcode.h"
+#include "debug.h"
 
-#define        FS_DO_ERROR(s)  \
-       { \
-               if (UserInterfaceUp) \
-                       MessageBox(s); \
-               else \
-               { \
-                       printf(s); \
-                       printf("\nPress any key\n"); \
-                       getch(); \
-               } \
-       }
-
-
-int            nSectorBuffered  = -1;  // Tells us which sector was read into SectorBuffer[]
 
-BYTE   SectorBuffer[512];              // 512 byte buffer space for read operations, ReadOneSector reads to here
+/////////////////////////////////////////////////////////////////////////////////////////////
+// DATA
+/////////////////////////////////////////////////////////////////////////////////////////////
 
-int            FSType = NULL;                  // Type of filesystem on boot device, set by OpenDiskDrive()
+GEOMETRY       DriveGeometry;
+ULONG          VolumeHiddenSectors;
+ULONG          CurrentlyOpenDriveNumber;
+ULONG          FileSystemType = 0;                     // Type of filesystem on boot device, set by OpenDiskDrive()
 
-char   *pFileSysData = (char *)(FILESYSADDR); // Load address for filesystem data
-char   *pFat32FATCacheIndex = (char *)(FILESYSADDR); // Load address for filesystem data
+/////////////////////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS
+/////////////////////////////////////////////////////////////////////////////////////////////
 
-BOOL OpenDiskDrive(int nDrive, int nPartition)
+VOID FileSystemError(PUCHAR ErrorString)
 {
-       int             num_bootable_partitions = 0;
-       int             boot_partition = 0;
-       int             partition_type = 0;
-       int             head, sector, cylinder;
-       int             offset;
+       DbgPrint((DPRINT_FILESYSTEM, "%s\n", ErrorString));
 
-       // Check and see if it is a floppy drive
-       if (nDrive < 0x80)
+       if (UserInterfaceUp)
        {
-               // Read boot sector
-               if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer))
-               {
-                       FS_DO_ERROR("Disk Read Error");
-                       return FALSE;
-               }
-
-               // Check for validity
-               if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
-               {
-                       FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
-                       return FALSE;
-               }
+               MessageBox(ErrorString);
        }
        else
        {
-               // Read master boot record
-               if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer))
-               {
-                       FS_DO_ERROR("Disk Read Error");
-                       return FALSE;
-               }
-
-               // Check for validity
-               if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
-               {
-                       FS_DO_ERROR("Invalid partition table magic (0xaa55)");
-                       return FALSE;
-               }
-
-               if (nPartition == 0)
-               {
-                       // Check for bootable partitions
-                       if (SectorBuffer[0x1BE] == 0x80)
-                               num_bootable_partitions++;
-                       if (SectorBuffer[0x1CE] == 0x80)
-                       {
-                               num_bootable_partitions++;
-                               boot_partition = 1;
-                       }
-                       if (SectorBuffer[0x1DE] == 0x80)
-                       {
-                               num_bootable_partitions++;
-                               boot_partition = 2;
-                       }
-                       if (SectorBuffer[0x1EE] == 0x80)
-                       {
-                               num_bootable_partitions++;
-                               boot_partition = 3;
-                       }
-
-                       // Make sure there was only one bootable partition
-                       if (num_bootable_partitions > 1)
-                       {
-                               FS_DO_ERROR("Too many boot partitions");
-                               return FALSE;
-                       }
-
-                       offset = 0x1BE + (boot_partition * 0x10);
-               }
-               else
-                       offset = 0x1BE + ((nPartition-1) * 0x10);
+               printf("%s", ErrorString);
+               printf("\nPress any key\n");
+               getch();
+       }
+}
 
-               partition_type = SectorBuffer[offset + 4];
+/*
+ *
+ * BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
+ *
+ * This function is called to open a disk drive for file access.
+ * It must be called before any of the file functions will work.
+ * It takes two parameters:
+ *
+ * Drive: The BIOS drive number of the disk to open
+ * Partition: This is zero for floppy drives.
+ *            If the disk is a hard disk then this specifies
+ *            The partition number to open (1 - 4)
+ *            If it is zero then it opens the active (bootable) partition
+ *
+ */
+BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
+{
+       ULONG                           BootablePartitionCount = 0;
+       ULONG                           BootPartition = 0;
+       ULONG                           PartitionStartHead;
+       ULONG                           PartitionStartSector;
+       ULONG                           PartitionStartCylinder;
+       MASTER_BOOT_RECORD      DriveMasterBootRecord;
 
-               // Check for valid partition
-               if (partition_type == 0)
-               {
-                       FS_DO_ERROR("Invalid boot partition");
-                       return FALSE;
-               }
+       DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
 
-               head = SectorBuffer[offset + 1];
-               sector = (SectorBuffer[offset + 2] & 0x3F);
-               cylinder = SectorBuffer[offset + 3];
-               if (SectorBuffer[offset + 2] & 0x80)
-                       cylinder += 0x200;
-               if (SectorBuffer[offset + 2] & 0x40)
-                       cylinder += 0x100;
+       CurrentlyOpenDriveNumber = DriveNumber;
 
-               // Read partition boot sector
-               if (!biosdisk(_DISK_READ, nDrive, head, cylinder, sector, 1, SectorBuffer))
-               {
-                       FS_DO_ERROR("Disk Read Error");
-                       return FALSE;
-               }
+       //
+       // Check and see if it is a floppy drive
+       // If so then just assume FAT12 file system type
+       //
+       if (DriveNumber < 0x80)
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
 
-               // Check for validity
-               if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
-               {
-                       FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
-                       return FALSE;
-               }
+               FileSystemType = FS_FAT;
+               return FatOpenVolume(DriveNumber, 0, 0, 1, FAT12);
        }
 
+       //
+       // Read master boot record
+       //
+       if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &DriveMasterBootRecord))
+       {
+               FileSystemError("Disk read error.");
+               return FALSE;
+       }
 
-       // Reset data
-       nBytesPerSector = 0;
-       nSectorsPerCluster = 0;
-       nReservedSectors = 0;
-       nNumberOfFATs = 0;
-       nRootDirEntries = 0;
-       nTotalSectors16 = 0;
-       nSectorsPerFAT16 = 0;
-       nSectorsPerTrack = 0;
-       nNumberOfHeads = 0;
-       nHiddenSectors = 0;
-       nTotalSectors32 = 0;
-
-       nSectorsPerFAT32 = 0;
-       nExtendedFlags = 0;
-       nFileSystemVersion = 0;
-       nRootDirStartCluster = 0;
-
-       nRootDirSectorStart = 0;
-       nDataSectorStart = 0;
-       nSectorsPerFAT = 0;
-       nRootDirSectors = 0;
-       nTotalSectors = 0;
-       nNumberOfClusters = 0;
-
-       // Get data
-       memcpy(&nBytesPerSector, SectorBuffer + BPB_BYTESPERSECTOR, 2);
-       memcpy(&nSectorsPerCluster, SectorBuffer + BPB_SECTORSPERCLUSTER, 1);
-       memcpy(&nReservedSectors, SectorBuffer + BPB_RESERVEDSECTORS, 2);
-       memcpy(&nNumberOfFATs, SectorBuffer + BPB_NUMBEROFFATS, 1);
-       memcpy(&nRootDirEntries, SectorBuffer + BPB_ROOTDIRENTRIES, 2);
-       memcpy(&nTotalSectors16, SectorBuffer + BPB_TOTALSECTORS16, 2);
-       memcpy(&nSectorsPerFAT16, SectorBuffer + BPB_SECTORSPERFAT16, 2);
-       memcpy(&nSectorsPerTrack, SectorBuffer + BPB_SECTORSPERTRACK, 2);
-       memcpy(&nNumberOfHeads, SectorBuffer + BPB_NUMBEROFHEADS, 2);
-       memcpy(&nHiddenSectors, SectorBuffer + BPB_HIDDENSECTORS, 4);
-       memcpy(&nTotalSectors32, SectorBuffer + BPB_TOTALSECTORS32, 4);
-
-       memcpy(&nSectorsPerFAT32, SectorBuffer + BPB_SECTORSPERFAT32, 4);
-       memcpy(&nExtendedFlags, SectorBuffer + BPB_EXTENDEDFLAGS32, 2);
-       memcpy(&nFileSystemVersion, SectorBuffer + BPB_FILESYSTEMVERSION32, 2);
-       memcpy(&nRootDirStartCluster, SectorBuffer + BPB_ROOTDIRSTARTCLUSTER32, 4);
-
-       // Calc some stuff
-       if (nTotalSectors16 != 0)
-               nTotalSectors = nTotalSectors16;
-       else
-               nTotalSectors = nTotalSectors32; 
 
-       if (nSectorsPerFAT16 != 0)
-               nSectorsPerFAT = nSectorsPerFAT16;
-       else
-               nSectorsPerFAT = nSectorsPerFAT32; 
+#ifdef DEBUG
 
-       nRootDirSectorStart = (nNumberOfFATs * nSectorsPerFAT) + nReservedSectors;
-       nRootDirSectors = ((nRootDirEntries * 32) + (nBytesPerSector - 1)) / nBytesPerSector;
-       nDataSectorStart = nReservedSectors + (nNumberOfFATs * nSectorsPerFAT) + nRootDirSectors;
-       nNumberOfClusters = (nTotalSectors - nDataSectorStart) / nSectorsPerCluster;
+       DbgPrint((DPRINT_FILESYSTEM, "Drive is a hard disk, dumping partition table:\n"));
+       DbgPrint((DPRINT_FILESYSTEM, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD)));
 
-       // Determine FAT type
-       if (nNumberOfClusters < 4085)
+       for (BootPartition=0; BootPartition<4; BootPartition++)
        {
-               /* Volume is FAT12 */
-               nFATType = FAT12;
+               DbgPrint((DPRINT_FILESYSTEM, "-------------------------------------------\n"));
+               DbgPrint((DPRINT_FILESYSTEM, "Partition %d\n", (BootPartition + 1)));
+               DbgPrint((DPRINT_FILESYSTEM, "BootIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].BootIndicator));
+               DbgPrint((DPRINT_FILESYSTEM, "StartHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartHead));
+               DbgPrint((DPRINT_FILESYSTEM, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartSector));
+               DbgPrint((DPRINT_FILESYSTEM, "StartCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartCylinder));
+               DbgPrint((DPRINT_FILESYSTEM, "SystemIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SystemIndicator));
+               DbgPrint((DPRINT_FILESYSTEM, "EndHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndHead));
+               DbgPrint((DPRINT_FILESYSTEM, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndSector));
+               DbgPrint((DPRINT_FILESYSTEM, "EndCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndCylinder));
+               DbgPrint((DPRINT_FILESYSTEM, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SectorCountBeforePartition));
+               DbgPrint((DPRINT_FILESYSTEM, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].PartitionSectorCount));
        }
-       else if (nNumberOfClusters < 65525)
+
+#endif // defined DEBUG
+
+
+       //
+       // Check the partition table magic value
+       //
+       if (DriveMasterBootRecord.MasterBootRecordMagic != 0xaa55)
        {
-               /* Volume is FAT16 */
-               nFATType = FAT16;
+               FileSystemError("Invalid partition table magic (0xaa55)");
+               return FALSE;
        }
-       else
+
+       if (PartitionNumber == 0)
        {
-               /* Volume is FAT32 */
-               nFATType = FAT32;
+               //
+               // Count the bootable partitions
+               //
+               if (DriveMasterBootRecord.PartitionTable[0].BootIndicator == 0x80)
+               {
+                       BootablePartitionCount++;
+                       BootPartition = 1;
+               }
+               if (DriveMasterBootRecord.PartitionTable[1].BootIndicator == 0x80)
+               {
+                       BootablePartitionCount++;
+                       BootPartition = 2;
+               }
+               if (DriveMasterBootRecord.PartitionTable[2].BootIndicator == 0x80)
+               {
+                       BootablePartitionCount++;
+                       BootPartition = 3;
+               }
+               if (DriveMasterBootRecord.PartitionTable[3].BootIndicator == 0x80)
+               {
+                       BootablePartitionCount++;
+                       BootPartition = 4;
+               }
 
-               // Check version
-               // we only work with version 0
-               if (*((WORD*)(SectorBuffer + BPB_FILESYSTEMVERSION32)) != 0)
+               //
+               // Make sure there was only one bootable partition
+               //
+               if (BootablePartitionCount != 1)
                {
-                       FS_DO_ERROR("Error: FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
+                       FileSystemError("Too many bootable partitions or none found.");
                        return FALSE;
                }
+               else
+               {
+                       //
+                       // We found the boot partition, so set the partition number
+                       //
+                       PartitionNumber = BootPartition;
+               }
        }
 
-       FSType = FS_FAT;
+       //
+       // Right now the partition number is one-based
+       // and we need zero based
+       //
+       PartitionNumber--;
 
-       // Buffer the FAT table if it is small enough
-       if ((FSType == FS_FAT) && (nFATType == FAT12))
-       {
-               if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData))
-                       return FALSE;
-       }
-       else if ((FSType == FS_FAT) && (nFATType == FAT16))
+       //
+       // Check for valid partition
+       //
+       if (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator == PARTITION_ENTRY_UNUSED)
        {
-               if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData))
-                       return FALSE;
+               FileSystemError("Invalid partition.");
+               return FALSE;
        }
-       else if ((FSType == FS_FAT) && (nFATType == FAT32))
+
+       PartitionStartHead = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartHead;
+       PartitionStartSector = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector & 0x3F;
+       PartitionStartCylinder = MAKE_CYLINDER(
+               DriveMasterBootRecord.PartitionTable[PartitionNumber].StartCylinder,
+               DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector);
+
+       DbgPrint((DPRINT_FILESYSTEM, "PartitionStartHead: %d\n", PartitionStartHead));
+       DbgPrint((DPRINT_FILESYSTEM, "PartitionStartSector: %d\n", PartitionStartSector));
+       DbgPrint((DPRINT_FILESYSTEM, "PartitionStartCylinder: %d\n", PartitionStartCylinder));
+       DbgPrint((DPRINT_FILESYSTEM, "PartitionNumber: %d\n", PartitionNumber));
+
+       switch (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator)
        {
-               // The FAT table is too big to be buffered so
-               // we will initialize our cache and cache it
-               // on demand
-               for (offset=0; offset<256; offset++)
-                       ((int*)pFat32FATCacheIndex)[offset] = -1;
+       case PARTITION_FAT_12:
+               FileSystemType = FS_FAT;
+               return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT12);
+       case PARTITION_FAT_16:
+       case PARTITION_HUGE:
+       case PARTITION_XINT13:
+               FileSystemType = FS_FAT;
+               return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT16);
+       case PARTITION_FAT32:
+       case PARTITION_FAT32_XINT13:
+               FileSystemType = FS_FAT;
+               return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT32);
+       default:
+               FileSystemType = 0;
+               FileSystemError("Unsupported file system.");
+               return FALSE;
        }
 
        return TRUE;
 }
 
-BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
+VOID SetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
+{
+       DriveGeometry.Cylinders = Cylinders;
+       DriveGeometry.Heads = Heads;
+       DriveGeometry.Sectors = Sectors;
+       DriveGeometry.BytesPerSector = BytesPerSector;
+
+       DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Cylinders: %d\n", DriveGeometry.Cylinders));
+       DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Heads: %d\n", DriveGeometry.Heads));
+       DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Sectors: %d\n", DriveGeometry.Sectors));
+       DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.BytesPerSector: %d\n", DriveGeometry.BytesPerSector));
+}
+
+VOID SetVolumeProperties(ULONG HiddenSectors)
 {
-       BOOL    bRetVal;
+       VolumeHiddenSectors = HiddenSectors;
+}
+
+BOOL ReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
+{
+       /*BOOL  bRetVal;
        int             PhysicalSector;
        int             PhysicalHead;
        int             PhysicalTrack;
@@ -292,7 +279,7 @@ BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
                                nNum = nNumberOfSectors;
                }
 
-               bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
+               bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
 
                if (!bRetVal)
                {
@@ -303,124 +290,203 @@ BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
                pBuffer += (nNum * 512);
                nNumberOfSectors -= nNum;
                nSect += nNum;
+       }*/
+
+       ULONG   CurrentSector;
+       PVOID   RealBuffer = Buffer;
+
+       for (CurrentSector=SectorNumber; CurrentSector<(SectorNumber + SectorCount); CurrentSector++)
+       {
+               if (!ReadLogicalSector(CurrentSector, RealBuffer) )
+               {
+                       return FALSE;
+               }
+
+               RealBuffer += DriveGeometry.BytesPerSector;
        }
 
        return TRUE;
 }
 
-BOOL ReadOneSector(int nSect)
+BOOL ReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
 {
-       BOOL    bRetVal;
-       int             PhysicalSector;
-       int             PhysicalHead;
-       int             PhysicalTrack;
+       ULONG   PhysicalSector;
+       ULONG   PhysicalHead;
+       ULONG   PhysicalTrack;
 
-       nSectorBuffered = nSect;
-
-       nSect += nHiddenSectors;
-       PhysicalSector = 1 + (nSect % nSectorsPerTrack);
-       PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
-       PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
+       DbgPrint((DPRINT_FILESYSTEM, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber, Buffer));
 
+       SectorNumber += VolumeHiddenSectors;
+       PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
+       PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
+       PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
 
-       bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, 1, SectorBuffer);
+       //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
+       //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
+       //DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
+       if (PhysicalHead >= DriveGeometry.Heads)
+       {
+               BugCheck((DPRINT_FILESYSTEM, "PhysicalHead >= DriveGeometry.Heads\nPhysicalHead = %d\nDriveGeometry.Heads = %d\n", PhysicalHead, DriveGeometry.Heads));
+       }
+       if (PhysicalTrack >= DriveGeometry.Cylinders)
+       {
+               BugCheck((DPRINT_FILESYSTEM, "PhysicalTrack >= DriveGeometry.Cylinders\nPhysicalTrack = %d\nDriveGeometry.Cylinders = %d\n", PhysicalTrack, DriveGeometry.Cylinders));
+       }
+       if (PhysicalSector > DriveGeometry.Sectors)
+       {
+               BugCheck((DPRINT_FILESYSTEM, "PhysicalSector > DriveGeometry.Sectors\nPhysicalSector = %d\nDriveGeometry.Sectors = %d\n", PhysicalSector, DriveGeometry.Sectors));
+       }
 
-       if (!bRetVal)
+       if ((CurrentlyOpenDriveNumber >= 0x80) &&
+               (BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber)) &&
+               (SectorNumber > (DriveGeometry.Cylinders * DriveGeometry.Heads * DriveGeometry.Sectors)))
        {
-               FS_DO_ERROR("Disk Error");
-               return FALSE;
+               DbgPrint((DPRINT_FILESYSTEM, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", CurrentlyOpenDriveNumber, BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber) ? "TRUE" : "FALSE"));
+               if ( !BiosInt13ReadExtended(CurrentlyOpenDriveNumber, SectorNumber, 1, Buffer) )
+               {
+                       FileSystemError("Disk read error.");
+                       return FALSE;
+               }
+       }
+       else
+       {
+               if ( !BiosInt13Read(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer) )
+               {
+                       FileSystemError("Disk read error.");
+                       return FALSE;
+               }
        }
 
        return TRUE;
 }
 
-BOOL OpenFile(char *filename, FILE *pFile)
+PFILE OpenFile(PUCHAR FileName)
 {
-       switch(FSType)
+       PFILE   FileHandle = NULL;
+
+       //
+       // Print status message
+       //
+       DbgPrint((DPRINT_FILESYSTEM, "Opening file '%s'...\n", FileName));
+       
+       //
+       // Check file system type and pass off to appropriate handler
+       //
+       if (FileSystemType == FS_FAT)
        {
-       case FS_FAT:
-               if(!FATOpenFile(filename, &(pFile->fat)))
-                       return FALSE;
-               pFile->filesize = pFile->fat.dwSize;
-               break;
-       default:
-               FS_DO_ERROR("Error: Unknown filesystem.");
-               return FALSE;
-               break;
+               FileHandle = FatOpenFile(FileName);
+       }
+       else
+       {
+               FileSystemError("Error: Unknown filesystem.");
        }
 
-       return TRUE;
+#ifdef DEBUG
+       //
+       // Check return value
+       //
+       if (FileHandle != NULL)
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
+       }
+       else
+       {
+               DbgPrint((DPRINT_FILESYSTEM, "OpenFile() failed.\n"));
+       }
+#endif // defined DEBUG
+
+       return FileHandle;
+}
+
+VOID CloseFile(PFILE FileHandle)
+{
 }
 
 /*
  * ReadFile()
  * returns number of bytes read or EOF
  */
-int ReadFile(FILE *pFile, int count, void *buffer)
+BOOL ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer)
 {
-       switch(FSType)
+       //
+       // Set the number of bytes read equal to zero
+       //
+       if (BytesRead !=NULL)
+       {
+               *BytesRead = 0;
+       }
+
+       switch (FileSystemType)
        {
        case FS_FAT:
-               return FATRead(&(pFile->fat), count, buffer);
+
+               return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
+
        default:
-               FS_DO_ERROR("Error: Unknown filesystem.");
-               return EOF;
-       }
 
-       return 0;
-}
+               FileSystemError("Unknown file system.");
+               return FALSE;
+       }
 
-DWORD GetFileSize(FILE *pFile)
-{
-       return pFile->filesize;
+       return FALSE;
 }
 
-DWORD Rewind(FILE *pFile)
+ULONG GetFileSize(PFILE FileHandle)
 {
-       switch (FSType)
+       switch (FileSystemType)
        {
        case FS_FAT:
-               pFile->fat.dwCurrentCluster = pFile->fat.dwStartCluster;
-               pFile->fat.dwCurrentReadOffset = 0;
-               break;
+
+               return FatGetFileSize(FileHandle);
+
        default:
-               FS_DO_ERROR("Error: Unknown filesystem.");
+               FileSystemError("Unknown file system.");
                break;
        }
 
-       return pFile->filesize;
+       return 0;
 }
 
-int feof(FILE *pFile)
+VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
 {
-       switch (FSType)
+       switch (FileSystemType)
        {
        case FS_FAT:
-               if (pFile->fat.dwCurrentReadOffset >= pFile->fat.dwSize)
-                       return TRUE;
-               else
-                       return FALSE;
+
+               FatSetFilePointer(FileHandle, NewFilePointer);
                break;
+
        default:
-               FS_DO_ERROR("Error: Unknown filesystem.");
-               return TRUE;
+               FileSystemError("Unknown file system.");
                break;
        }
-
-       return TRUE;
 }
 
-int fseek(FILE *pFile, DWORD offset)
+ULONG GetFilePointer(PFILE FileHandle)
 {
-       switch (FSType)
+       switch (FileSystemType)
        {
        case FS_FAT:
-               return FATfseek(&(pFile->fat), offset);
+
+               return FatGetFilePointer(FileHandle);
                break;
+
        default:
-               FS_DO_ERROR("Error: Unknown filesystem.");
+               FileSystemError("Unknown file system.");
                break;
        }
 
-       return -1;
+       return 0;
+}
+
+BOOL IsEndOfFile(PFILE FileHandle)
+{
+       if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle))
+       {
+               return TRUE;
+       }
+       else
+       {
+               return FALSE;
+       }
 }
index e80dadb..b8c133e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef __FS_FAT_H
-#define __FS_FAT_H
-
-// Bootsector BPB defines
-#define BPB_JMPBOOT                                    0
-#define BPB_OEMNAME                                    3
-#define BPB_BYTESPERSECTOR                     11
-#define BPB_SECTORSPERCLUSTER          13
-#define BPB_RESERVEDSECTORS                    14
-#define BPB_NUMBEROFFATS                       16
-#define BPB_ROOTDIRENTRIES                     17
-#define BPB_TOTALSECTORS16                     19
-#define BPB_MEDIADESCRIPTOR                    21
-#define BPB_SECTORSPERFAT16                    22
-#define BPB_SECTORSPERTRACK                    24
-#define BPB_NUMBEROFHEADS                      26
-#define BPB_HIDDENSECTORS                      28
-#define BPB_TOTALSECTORS32                     32
-
-// Fat12/16 extended BPB defines
-#define BPB_DRIVENUMBER16                      36
-#define BPB_RESERVED16_1                       37
-#define BPB_BOOTSIGNATURE16                    38
-#define BPB_VOLUMESERIAL16                     39
-#define BPB_VOLUMELABEL16                      43
-#define BPB_FILESYSTEMTYPE16           54
-
-// Fat32 extended BPB defines
-#define BPB_SECTORSPERFAT32                    36
-#define BPB_EXTENDEDFLAGS32                    40
-#define BPB_FILESYSTEMVERSION32                42
-#define BPB_ROOTDIRSTARTCLUSTER32      44
-#define BPB_FILESYSTEMINFOSECTOR32     48
-#define BPB_BACKUPBOOTSECTOR32         50
-#define BPB_RESERVED32_1                       52
-#define BPB_DRIVENUMBER32                      64
-#define BPB_RESERVED32_2                       65
-#define BPB_BOOTSIGNATURE32                    66
-#define BPB_VOLUMESERIAL32                     67
-#define BPB_VOLUMELABEL32                      71
-#define BPB_FILESYSTEMTYPE32           82
+#ifndef __FS_H
+#define __FS_H
 
-/*
- * Structure of MSDOS directory entry
- */
-typedef struct //_DIRENTRY
+//
+// Define the structure of a partition table entry
+//
+typedef struct _PARTITION_TABLE_ENTRY
 {
-       BYTE    cFileName[11];  /* Filename + extension */
-       BYTE    cAttr;                  /* File attributes */
-       BYTE    cReserved[10];  /* Reserved area */
-       WORD    wTime;                  /* Time last modified */
-       WORD    wData;                  /* Date last modified */
-       WORD    wCluster;               /* First cluster number */
-       DWORD   dwSize;                 /* File size */
-} DIRENTRY, * PDIRENTRY;
-
-/*
- * Structure of internal file control block
- */
-typedef struct //_FCB
-{
-       BYTE            cAttr;                  /* Open attributes */
-       BYTE            cSector;                /* Sector within cluster */
-       PDIRENTRY       pDirptr;                /* Pointer to directory entry */
-       WORD            wDirSector;             /* Directory sector */
-       WORD            wFirstCluster;  /* First cluster in file */
-       WORD            wLastCluster;   /* Last cluster read/written */
-       WORD            wNextCluster;   /* Next cluster to read/write */
-       WORD            wOffset;                /* Read/Write offset within sector */
-       DWORD           dwSize;                 /* File size */
-       BYTE            cBuffer[512];   /* Data transfer buffer */
-} FCB, * PFCB;
-
-typedef struct //_FAT_STRUCT
+       BYTE    BootIndicator;                                  // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only)
+       BYTE    StartHead;                                              // Beginning head number
+       BYTE    StartSector;                                    // Beginning sector (2 high bits of cylinder #)
+       BYTE    StartCylinder;                                  // Beginning cylinder# (low order bits of cylinder #)
+       BYTE    SystemIndicator;                                // System indicator
+       BYTE    EndHead;                                                // Ending head number
+       BYTE    EndSector;                                              // Ending sector (2 high bits of cylinder #)
+       BYTE    EndCylinder;                                    // Ending cylinder# (low order bits of cylinder #)
+       DWORD   SectorCountBeforePartition;             // Number of sectors preceding the partition
+       DWORD   PartitionSectorCount;                   // Number of sectors in the partition
+
+} PACKED PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
+
+//
+// This macro will return the cylinder when you pass it a cylinder/sector
+// pair where the high 2 bits of the cylinder are stored in the sector byte
+//
+#define MAKE_CYLINDER(cylinder, sector) ( cylinder + ((((WORD)sector) & 0xC0) << 2) )
+
+//
+// Define the structure of the master boot record
+//
+typedef struct _MASTER_BOOT_RECORD
 {
-       DWORD   dwStartCluster;         // File's starting cluster
-       DWORD   dwCurrentCluster;       // Current read cluster number
-       DWORD   dwSize;                         // File size
-       DWORD   dwCurrentReadOffset;// Amount of data already read
-} FAT_STRUCT, * PFAT_STRUCT;
-
-typedef struct //_FILE
+       BYTE                                    MasterBootRecordCodeAndData[0x1be];
+       PARTITION_TABLE_ENTRY   PartitionTable[4];
+       WORD                                    MasterBootRecordMagic;
+
+} PACKED MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
+
+//
+// Partition type defines
+//
+#define PARTITION_ENTRY_UNUSED          0x00      // Entry unused
+#define PARTITION_FAT_12                0x01      // 12-bit FAT entries
+#define PARTITION_XENIX_1               0x02      // Xenix
+#define PARTITION_XENIX_2               0x03      // Xenix
+#define PARTITION_FAT_16                0x04      // 16-bit FAT entries
+#define PARTITION_EXTENDED              0x05      // Extended partition entry
+#define PARTITION_HUGE                  0x06      // Huge partition MS-DOS V4
+#define PARTITION_IFS                   0x07      // IFS Partition
+#define PARTITION_OS2BOOTMGR            0x0A      // OS/2 Boot Manager/OPUS/Coherent swap
+#define PARTITION_FAT32                 0x0B      // FAT32
+#define PARTITION_FAT32_XINT13          0x0C      // FAT32 using extended int13 services
+#define PARTITION_XINT13                0x0E      // Win95 partition using extended int13 services
+#define PARTITION_XINT13_EXTENDED       0x0F      // Same as type 5 but uses extended int13 services
+#define PARTITION_PREP                  0x41      // PowerPC Reference Platform (PReP) Boot Partition
+#define PARTITION_LDM                   0x42      // Logical Disk Manager partition
+#define PARTITION_UNIX                  0x63      // Unix
+
+typedef struct _GEOMETRY
 {
-       //DIRENTRY              de;
-       //FCB                           fcb;
-       FAT_STRUCT              fat;
-       unsigned long   filesize;
-} FILE;
-
-extern int             nSectorBuffered;        // Tells us which sector was read into SectorBuffer[]
-extern BYTE    SectorBuffer[512];      // 512 byte buffer space for read operations, ReadOneSector reads to here
-
-extern int             nFATType;
-
-extern DWORD   nBytesPerSector;                // Bytes per sector
-extern DWORD   nSectorsPerCluster;             // Number of sectors in a cluster
-extern DWORD   nReservedSectors;               // Reserved sectors, usually 1 (the bootsector)
-extern DWORD   nNumberOfFATs;                  // Number of FAT tables
-extern DWORD   nRootDirEntries;                // Number of root directory entries (fat12/16)
-extern DWORD   nTotalSectors16;                // Number of total sectors on the drive, 16-bit
-extern DWORD   nSectorsPerFAT16;               // Sectors per FAT table (fat12/16)
-extern DWORD   nSectorsPerTrack;               // Number of sectors in a track
-extern DWORD   nNumberOfHeads;                 // Number of heads on the disk
-extern DWORD   nHiddenSectors;                 // Hidden sectors (sectors before the partition start like the partition table)
-extern DWORD   nTotalSectors32;                // Number of total sectors on the drive, 32-bit
-
-extern DWORD   nSectorsPerFAT32;               // Sectors per FAT table (fat32)
-extern DWORD   nExtendedFlags;                 // Extended flags (fat32)
-extern DWORD   nFileSystemVersion;             // File system version (fat32)
-extern DWORD   nRootDirStartCluster;   // Starting cluster of the root directory (fat32)
-
-extern DWORD   nRootDirSectorStart;    // Starting sector of the root directory (fat12/16)
-extern DWORD   nDataSectorStart;               // Starting sector of the data area
-extern DWORD   nSectorsPerFAT;                 // Sectors per FAT table
-extern DWORD   nRootDirSectors;                // Number of sectors of the root directory (fat32)
-extern DWORD   nTotalSectors;                  // Total sectors on the drive
-extern DWORD   nNumberOfClusters;              // Number of clusters on the drive
-
-extern int     FSType;                                         // Type of filesystem on boot device, set by OpenDiskDrive()
-
-extern char *pFileSysData;                             // Load address for filesystem data
-extern char *pFat32FATCacheIndex;              // Load address for filesystem data
-
-BOOL   OpenDiskDrive(int nDrive, int nPartition);      // Opens the disk drive device for reading
-BOOL   ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer);// Reads a sector from the open device
-BOOL   ReadOneSector(int nSect);                               // Reads one sector from the open device
-BOOL   OpenFile(char *filename, FILE *pFile);  // Opens a file
-int            ReadFile(FILE *pFile, int count, void *buffer); // Reads count bytes from pFile into buffer
-DWORD  GetFileSize(FILE *pFile);
-DWORD  Rewind(FILE *pFile);    // Rewinds a file and returns it's size
-int            feof(FILE *pFile);
-int            fseek(FILE *pFILE, DWORD offset);
-
-BOOL   FATLookupFile(char *file, PFAT_STRUCT pFatStruct);
-int            FATGetNumPathParts(char *name);
-BOOL   FATGetFirstNameFromPath(char *buffer, char *name);
-void   FATParseFileName(char *buffer, char *name);
-DWORD  FATGetFATEntry(DWORD nCluster);
-BOOL   FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct);
-int            FATReadCluster(DWORD nCluster, char *cBuffer);
-int            FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer);
-int            FATfseek(PFAT_STRUCT pFatStruct, DWORD offset);
+       ULONG   Cylinders;
+       ULONG   Heads;
+       ULONG   Sectors;
+       ULONG   BytesPerSector;
+
+} GEOMETRY, *PGEOMETRY;
+
+#define FILE VOID
+#define PFILE FILE *
+
+VOID   FileSystemError(PUCHAR ErrorString);
+BOOL   OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
+VOID   SetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector);
+VOID   SetVolumeProperties(ULONG HiddenSectors);
+BOOL   ReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
+BOOL   ReadLogicalSector(ULONG SectorNumber, PVOID Buffer);
+PFILE  OpenFile(PUCHAR FileName);
+VOID   CloseFile(PFILE FileHandle);
+BOOL   ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
+ULONG  GetFileSize(PFILE FileHandle);
+VOID   SetFilePointer(PFILE FileHandle, ULONG NewFilePointer);
+ULONG  GetFilePointer(PFILE FileHandle);
+BOOL   IsEndOfFile(PFILE FileHandle);
 
 
 #define        EOF     -1
@@ -179,4 +120,4 @@ int         FATfseek(PFAT_STRUCT pFatStruct, DWORD offset);
 #define        FAT16                   2
 #define        FAT32                   3
 
-#endif // #defined __FS_FAT_H
\ No newline at end of file
+#endif // #defined __FS_H
\ No newline at end of file
diff --git a/freeldr/freeldr/fs_fat.c b/freeldr/freeldr/fs_fat.c
deleted file mode 100644 (file)
index 828d1dc..0000000
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
- *
- *  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; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "freeldr.h"
-#include "fs.h"
-#include "stdlib.h"
-#include "tui.h"
-#include "asmcode.h"
-
-int            nFATType = FAT12;
-
-DWORD  nBytesPerSector;                // Bytes per sector
-DWORD  nSectorsPerCluster;             // Number of sectors in a cluster
-DWORD  nReservedSectors;               // Reserved sectors, usually 1 (the bootsector)
-DWORD  nNumberOfFATs;                  // Number of FAT tables
-DWORD  nRootDirEntries;                // Number of root directory entries (fat12/16)
-DWORD  nTotalSectors16;                // Number of total sectors on the drive, 16-bit
-DWORD  nSectorsPerFAT16;               // Sectors per FAT table (fat12/16)
-DWORD  nSectorsPerTrack;               // Number of sectors in a track
-DWORD  nNumberOfHeads;                 // Number of heads on the disk
-DWORD  nHiddenSectors;                 // Hidden sectors (sectors before the partition start like the partition table)
-DWORD  nTotalSectors32;                // Number of total sectors on the drive, 32-bit
-
-DWORD  nSectorsPerFAT32;               // Sectors per FAT table (fat32)
-DWORD  nExtendedFlags;                 // Extended flags (fat32)
-DWORD  nFileSystemVersion;             // File system version (fat32)
-DWORD  nRootDirStartCluster;   // Starting cluster of the root directory (fat32)
-
-DWORD  nRootDirSectorStart;    // Starting sector of the root directory (fat12/16)
-DWORD  nDataSectorStart;               // Starting sector of the data area
-DWORD  nSectorsPerFAT;                 // Sectors per FAT table
-DWORD  nRootDirSectors;                // Number of sectors of the root directory (fat32)
-DWORD  nTotalSectors;                  // Total sectors on the drive
-DWORD  nNumberOfClusters;              // Number of clusters on the drive
-
-BOOL FATReadRootDirectoryEntry(int nDirEntry, void *pDirEntryBuf)
-{
-       DWORD   nDirEntrySector;
-       int             nOffsetWithinSector;
-
-       nDirEntrySector = nRootDirSectorStart + ((nDirEntry * 32) / nBytesPerSector);
-
-       if (!ReadOneSector(nDirEntrySector))
-               return FALSE;
-
-       nOffsetWithinSector = (nDirEntry * 32) % nBytesPerSector;
-
-       memcpy(pDirEntryBuf, SectorBuffer + nOffsetWithinSector, 32);
-
-       if (*((char *)pDirEntryBuf) == 0x05)
-               *((char *)pDirEntryBuf) = 0xE5;
-
-       return TRUE;
-}
-
-BOOL FATReadDirectoryEntry(DWORD nDirStartCluster, int nDirEntry, void *pDirEntryBuf)
-{
-       DWORD   nRealDirCluster;
-       int             nSectorWithinCluster;
-       int             nOffsetWithinSector;
-       int             nSectorToRead;
-       int             i;
-
-       i = (nDirEntry * 32) / (nSectorsPerCluster * nBytesPerSector);
-       //if ((nDirEntry * 32) % (nSectorsPerCluster * nBytesPerSector))
-       //      i++;
-
-       for (nRealDirCluster = nDirStartCluster; i; i--)
-               nRealDirCluster = FATGetFATEntry(nRealDirCluster);
-
-       nSectorWithinCluster = ((nDirEntry * 32) % (nSectorsPerCluster * nBytesPerSector)) / nBytesPerSector;
-
-       nSectorToRead = ((nRealDirCluster - 2) * nSectorsPerCluster) + nDataSectorStart + nSectorWithinCluster;
-
-       if (!ReadOneSector(nSectorToRead))
-               return FALSE;
-
-       nOffsetWithinSector = (nDirEntry * 32) % nBytesPerSector;
-
-       memcpy(pDirEntryBuf, SectorBuffer + nOffsetWithinSector, 32);
-
-       if (*((char *)pDirEntryBuf) == 0x05)
-               *((char *)pDirEntryBuf) = 0xE5;
-
-       return TRUE;
-}
-
-/*
- * FATLookupFile()
- * This function searches the file system for the
- * specified filename and fills in a FAT_STRUCT structure
- * with info describing the file, etc. returns true
- * if the file exists or false otherwise
- */
-BOOL FATLookupFile(char *file, PFAT_STRUCT pFatStruct)
-{
-       int                     i, j;
-       int                     numparts;
-       char            filename[12];
-       BYTE            direntry[32];
-       int                     nNumDirEntries;
-       FAT_STRUCT      fatstruct;
-       BOOL            bFound;
-       DWORD           cluster;
-
-       memset(pFatStruct, 0, sizeof(FAT_STRUCT));
-
-       // Check and see if the first character is '\' and remove it if so
-       if (*file == '\\')
-               file++;
-
-       // Figure out how many sub-directories we are nested in
-       numparts = FATGetNumPathParts(file);
-
-       // Loop once for each part
-       for (i=0; i<numparts; i++)
-       {
-               // Make filename compatible with MSDOS dir entry
-               if (!FATGetFirstNameFromPath(filename, file))
-                       return FALSE;
-               // Advance to the next part of the path
-               for (; (*file != '\\') && (*file != '\0'); file++);
-               file++;
-
-               // If we didn't find the correct sub-directory the fail
-               if ((i != 0) && !bFound)
-                       return FALSE;
-
-               bFound = FALSE;
-
-               // Check if we are pulling from the root directory of a fat12/fat16 disk
-               if ((i == 0) && ((nFATType == FAT12) || (nFATType == FAT16)))
-                       nNumDirEntries = nRootDirEntries;
-               else if ((i == 0) && (nFATType == FAT32))
-               {
-                       cluster = nRootDirStartCluster;
-                       fatstruct.dwSize = nSectorsPerCluster * nBytesPerSector;
-                       while((cluster = FATGetFATEntry(cluster)) < 0x0FFFFFF8)
-                               fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
-
-                       fatstruct.dwStartCluster = nRootDirStartCluster;
-                       nNumDirEntries = fatstruct.dwSize / 32;
-               }
-               else
-                       nNumDirEntries = fatstruct.dwSize / 32;
-
-               // Loop through each directory entry
-               for (j=0; j<nNumDirEntries; j++)
-               {
-                       // Read the entry
-                       if ((i == 0) && ((nFATType == FAT12) || (nFATType == FAT16)))
-                       {
-                               if (!FATReadRootDirectoryEntry(j, direntry))
-                                       return FALSE;
-                       }
-                       else
-                       {
-                               if (!FATReadDirectoryEntry(fatstruct.dwStartCluster, j, direntry))
-                                       return FALSE;
-                       }
-
-                       if (memcmp(direntry, filename, 11) == 0)
-                       {
-                               fatstruct.dwStartCluster = 0;
-                               fatstruct.dwCurrentCluster = 0;
-                               memcpy(&fatstruct.dwStartCluster, direntry + 26, sizeof(WORD));
-                               memcpy(&fatstruct.dwCurrentCluster, direntry + 20, sizeof(WORD));
-                               fatstruct.dwStartCluster += (fatstruct.dwCurrentCluster * 0x10000);
-
-                               if (direntry[11] & ATTR_DIRECTORY)
-                               {
-                                       fatstruct.dwSize = nSectorsPerCluster * nBytesPerSector;
-                                       cluster = fatstruct.dwStartCluster;
-                                       switch (nFATType)
-                                       {
-                                       case FAT12:
-                                               while((cluster = FATGetFATEntry(cluster)) < 0xFF8)
-                                                       fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
-                                               break;
-                                       case FAT16:
-                                               while((cluster = FATGetFATEntry(cluster)) < 0xFFF8)
-                                                       fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
-                                               break;
-                                       case FAT32:
-                                               while((cluster = FATGetFATEntry(cluster)) < 0x0FFFFFF8)
-                                                       fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
-                                               break;
-                                       }
-                               }
-
-                               // If we have more parts to go and this isn't a directory then fail
-                               if ((i < (numparts-1)) && !(direntry[11] & ATTR_DIRECTORY))
-                                       return FALSE;
-
-                               // If this is supposed to be a file and it is a directory then fail
-                               if ((i == (numparts-1)) && (direntry[11] & ATTR_DIRECTORY))
-                                       return FALSE;
-
-                               bFound = TRUE;
-                               break;
-                       }
-               }
-       }
-
-       if(!bFound)
-               return FALSE;
-
-       memcpy(&pFatStruct->dwStartCluster, direntry + 26, sizeof(WORD));
-       memcpy(&pFatStruct->dwCurrentCluster, direntry + 20, sizeof(WORD));
-       pFatStruct->dwStartCluster += (pFatStruct->dwCurrentCluster * 0x10000);
-       pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster;
-
-       memcpy(&pFatStruct->dwSize, direntry + 28, sizeof(DWORD));
-       pFatStruct->dwCurrentReadOffset = 0;
-
-       return TRUE;
-}
-
-/*
- * FATGetNumPathParts()
- * This function parses a path in the form of dir1\dir2\file1.ext
- * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
- */
-int FATGetNumPathParts(char *name)
-{
-       int     i, num;
-
-       for(i=0,num=0; i<(int)strlen(name); i++)
-       {
-               if(name[i] == '\\')
-                       num++;
-       }
-       num++;
-
-       return num;
-}
-
-/*
- * FATGetFirstNameFromPath()
- * This function parses a path in the form of dir1\dir2\file1.ext
- * and puts the first name of the path (e.g. "dir1") in buffer
- * compatible with the MSDOS directory structure
- */
-BOOL FATGetFirstNameFromPath(char *buffer, char *name)
-{
-       int             i;
-       char    temp[260];
-
-       // Copy all the characters up to the end of the
-       // string or until we hit a '\' character
-       // and put them in temp
-       for(i=0; i<(int)strlen(name); i++)
-       {
-               if(name[i] == '\\')
-                       break;
-               else
-                       temp[i] = name[i];
-       }
-       temp[i] = 0;
-
-       // If the filename is too long then fail
-       if(strlen(temp) > 12)
-               return FALSE;
-
-       FATParseFileName(buffer, temp);
-
-       return TRUE;
-}
-
-/*
- * FATParseFileName()
- * This function parses "name" which is in the form of file.ext
- * and puts it in "buffer" in the form of "FILE   EXT" which
- * is compatible with the MSDOS directory structure
- */
-void FATParseFileName(char *buffer, char *name)
-{
-       int i, j;
-
-       i = 0;
-       j = 0;
-
-       while(i < 8)
-               buffer[i++] = (name[j] && (name[j] != '.')) ? toupper(name[j++]) : ' ';
-
-       if(name[j] == '.')
-               j++;
-
-       while(i < 11)
-               buffer[i++] = name[j] ? toupper(name[j++]) : ' ';
-
-       buffer[i] = 0;
-}
-
-/*
- * FATGetFATEntry()
- * returns the FAT entry for a given cluster number
- */
-DWORD FATGetFATEntry(DWORD nCluster)
-{
-       DWORD   fat;
-       int             FATOffset;
-       int             ThisFATSecNum;
-       int             ThisFATEntOffset;
-       int             Idx;
-       BOOL    bEntryFound;
-
-       switch(nFATType)
-       {
-       case FAT12:
-               FATOffset = nCluster + (nCluster / 2);
-               ThisFATSecNum = (FATOffset / nBytesPerSector);
-               ThisFATEntOffset = (FATOffset % nBytesPerSector);
-               fat = *((WORD *) (pFileSysData + (ThisFATSecNum * nBytesPerSector) + ThisFATEntOffset));
-               if (nCluster & 0x0001) 
-                       fat = fat >> 4; /* Cluster number is ODD */
-               else
-                       fat = fat & 0x0FFF;     /* Cluster number is EVEN */
-
-               return fat;
-               break;
-       case FAT16:
-               FATOffset = (nCluster * 2);
-               //ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector);
-               //ThisFATEntOffset = (FATOffset % nBytesPerSector);
-
-               //if (!ReadOneSector(ThisFATSecNum))
-               //      return NULL;
-
-               //fat = *((WORD *) &SectorBuffer[ThisFATEntOffset]);
-               fat = *((WORD *) (pFileSysData + FATOffset));
-
-               return fat;
-               break;
-       case FAT32:
-               //if (!ReadOneSector(ThisFATSecNum))
-               //      return NULL;
-
-               //fat = *((DWORD *) &SectorBuffer[ThisFATEntOffset]) & 0x0FFFFFFF;
-               //return fat;
-
-               // This code manages the fat32 fat table entry cache
-               // The cache is at address FILESYSADDR which is 128k in size
-               // The first two sectors will contain an array of DWORDs that
-               // Specify what fat sector is cached. The first two DWORDs
-               // should be zero.
-               FATOffset = (nCluster * 4);
-               ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector);
-               ThisFATEntOffset = (FATOffset % nBytesPerSector);
-
-               // Now we go through our cache and see if we already have the sector cached
-               bEntryFound = FALSE;
-               for (Idx=2; Idx<256; Idx++)
-               {
-                       if (((int*)pFat32FATCacheIndex)[Idx] == ThisFATSecNum)
-                       {
-                               bEntryFound = TRUE;
-                               break;
-                       }
-               }
-
-               if (bEntryFound)
-               {
-                       // Get the fat entry
-                       fat = (*((DWORD *) (pFat32FATCacheIndex +
-                               (Idx * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF;
-               }
-               else
-               {
-                       if (!ReadOneSector(ThisFATSecNum))
-                               return NULL;
-
-                       // Move each sector down in the cache to make room for new sector
-                       for (Idx=255; Idx>2; Idx--)
-                       {
-                               memcpy(pFat32FATCacheIndex + (Idx * nBytesPerSector), pFat32FATCacheIndex + ((Idx - 1) * nBytesPerSector), nBytesPerSector);
-                               ((int*)pFat32FATCacheIndex)[Idx] = ((int*)pFat32FATCacheIndex)[Idx - 1];
-                       }
-
-                       // Insert it into the cache
-                       memcpy(pFat32FATCacheIndex + (2 * nBytesPerSector), SectorBuffer, nBytesPerSector);
-                       ((int*)pFat32FATCacheIndex)[2] = ThisFATSecNum;
-
-                       // Get the fat entry
-                       fat = (*((DWORD *) (pFat32FATCacheIndex +
-                               (2 * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF;
-               }
-
-               return fat;
-               break;
-       }
-
-       return NULL;
-}
-
-/*
- * FATOpenFile()
- * Tries to open the file 'name' and returns true or false
- * for success and failure respectively
- */
-BOOL FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct)
-{
-       if(!FATLookupFile(szFileName, pFatStruct))
-               return FALSE;
-
-       /* Fill in file control information */
-       pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster;
-       pFatStruct->dwCurrentReadOffset = 0;
-
-       return TRUE;
-}
-
-/*
- * FATReadCluster()
- * Reads the specified cluster into memory
- * and returns the number of bytes read
- */
-int FATReadCluster(DWORD nCluster, char *cBuffer)
-{
-       int             nStartSector;
-
-       nStartSector = ((nCluster - 2) * nSectorsPerCluster) + nDataSectorStart;
-
-       ReadMultipleSectors(nStartSector, nSectorsPerCluster, cBuffer);
-
-       return (nSectorsPerCluster * nBytesPerSector);
-}
-
-/*
- * FATRead()
- * Reads nNumBytes from open file and
- * returns the number of bytes read
- */
-int FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer)
-{
-       int             nSectorWithinCluster;
-       int             nOffsetWithinSector;
-       int             nOffsetWithinCluster;
-       int             nNum;
-       int             nBytesRead = 0;
-
-       // If all the data is read return zero
-       if (pFatStruct->dwCurrentReadOffset >= pFatStruct->dwSize)
-               return 0;
-
-       // If they are trying to read more than there is to read
-       // then adjust the amount to read
-       if ((pFatStruct->dwCurrentReadOffset + nNumBytes) > pFatStruct->dwSize)
-               nNumBytes = pFatStruct->dwSize - pFatStruct->dwCurrentReadOffset;
-
-       while (nNumBytes)
-       {
-               // Check and see if the read offset is aligned to a cluster boundary
-               // if so great, if not then read the rest of the current cluster
-               if ((pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector)) != 0)
-               {
-                       nSectorWithinCluster = ((pFatStruct->dwCurrentReadOffset / nBytesPerSector) % nSectorsPerCluster);
-                       nOffsetWithinSector = (pFatStruct->dwCurrentReadOffset % nBytesPerSector);
-                       nOffsetWithinCluster = (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector));
-
-                       // Read the cluster into the scratch area
-                       FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF);
-
-                       nNum = (nSectorsPerCluster * nBytesPerSector) - (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector));
-                       if (nNumBytes >= nNum)
-                       {
-                               memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNum);
-                               nBytesRead += nNum;
-                               cBuffer += nNum;
-                               pFatStruct->dwCurrentReadOffset += nNum;
-                               pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster);
-                               nNumBytes -= nNum;
-                       }
-                       else
-                       {
-                               memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNumBytes);
-                               nBytesRead += nNumBytes;
-                               cBuffer += nNumBytes;
-                               pFatStruct->dwCurrentReadOffset += nNumBytes;
-                               nNumBytes -= nNumBytes;
-                       }
-               }
-               else
-               {
-                       // Read the cluster into the scratch area
-                       FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF);
-
-                       nNum = (nSectorsPerCluster * nBytesPerSector);
-                       if (nNumBytes >= nNum)
-                       {
-                               memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNum);
-                               nBytesRead += nNum;
-                               cBuffer += nNum;
-                               pFatStruct->dwCurrentReadOffset += nNum;
-                               pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster);
-                               nNumBytes -= nNum;
-                       }
-                       else
-                       {
-                               memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNumBytes);
-                               nBytesRead += nNumBytes;
-                               cBuffer += nNumBytes;
-                               pFatStruct->dwCurrentReadOffset += nNumBytes;
-                               nNumBytes -= nNumBytes;
-                       }
-               }
-       }
-
-       return nBytesRead;
-}
-
-int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset)
-{
-       DWORD           cluster;
-       int                     numclusters;
-
-       numclusters = offset / (nSectorsPerCluster * nBytesPerSector);
-       for (cluster=pFatStruct->dwStartCluster; numclusters > 0; numclusters--)
-               cluster = FATGetFATEntry(cluster);
-
-       pFatStruct->dwCurrentCluster = cluster;
-       pFatStruct->dwCurrentReadOffset = offset;
-
-       return 0;
-}
index 448d86d..6eedb47 100644 (file)
@@ -28,7 +28,7 @@
 
 void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line)
 {
-       FILE    file;
+       /*FILE  file;
        char    temp[260];
        char    bootsector[512];
        char    setup[2048];
@@ -97,5 +97,5 @@ void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line
        gotoxy(CursorXPos, CursorYPos);
 
        stop_floppy();
-       JumpToLinuxBootCode();
+       JumpToLinuxBootCode();*/
 }
index 6dfcb02..9f40d1d 100644 (file)
 #include "memory.h"
 #include "stdlib.h"
 #include "debug.h"
+#include "tui.h"
+
+
+//
+// Define this to 1 if you want the entire contents
+// of the memory allocation bitmap displayed
+// when a chunk is allocated or freed
+//
+#define DUMP_MEM_MAP_ON_VERIFY 0
 
 #define MEM_BLOCK_SIZE 256
 
@@ -39,6 +48,7 @@ PMEMBLOCK     HeapMemBlockArray = NULL;
 ULONG          AllocationCount = 0;
 
 VOID           VerifyHeap(VOID);
+VOID           DumpMemoryAllocMap(VOID);
 VOID           IncrementAllocationCount(VOID);
 VOID           DecrementAllocationCount(VOID);
 VOID           MemAllocTest(VOID);
@@ -66,7 +76,7 @@ VOID InitMemoryManager(PVOID BaseAddress, ULONG Length)
        ZeroMemory(HeapMemBlockArray, (HeapMemBlockCount * sizeof(MEMBLOCK)));
 
 #ifdef DEBUG
-       DebugPrint(DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount);
+       DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount));
        //MemAllocTest();
 #endif
 }
@@ -78,9 +88,11 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
        ULONG   NumFree;
        PVOID   MemPointer;
 
-#ifdef DEBUG
-       VerifyHeap();
-#endif DEBUG
+       if (NumberOfBytes == 0)
+       {
+               DbgPrint((DPRINT_MEMORY, "AllocateMemory() called for 0 bytes. Returning NULL.\n"));
+               return NULL;
+       }
 
        // Find out how many blocks it will take to
        // satisfy this allocation
@@ -116,6 +128,8 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
        // then return NULL
        if (NumFree < BlocksNeeded)
        {
+               DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", NumberOfBytes, AllocationCount));
+               MessageBox("Memory allocation failed: out of memory.");
                return NULL;
        }
 
@@ -135,7 +149,8 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
 
 #ifdef DEBUG
        IncrementAllocationCount();
-       DebugPrint(DPRINT_MEMORY, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocationCount: %d\n", NumberOfBytes, BlocksNeeded, Idx, AllocationCount);
+       DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocCount: %d\n", NumberOfBytes, BlocksNeeded, Idx, AllocationCount));
+       VerifyHeap();
 #endif DEBUG
 
        // Now return the pointer
@@ -149,12 +164,11 @@ VOID FreeMemory(PVOID MemBlock)
        ULONG   Idx;
 
 #ifdef DEBUG
-       VerifyHeap();
 
        // Make sure we didn't get a bogus pointer
        if ((MemBlock < HeapBaseAddress) || (MemBlock > (HeapBaseAddress + HeapLengthInBytes)))
        {
-               BugCheck1("Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock);
+               BugCheck((DPRINT_MEMORY, "Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock));
        }
 #endif DEBUG
 
@@ -167,7 +181,7 @@ VOID FreeMemory(PVOID MemBlock)
        // Make sure we didn't get a bogus pointer
        if ((BlockCount < 1) || (BlockCount > HeapMemBlockCount))
        {
-               BugCheck1("Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray[BlockNumber].BlocksAllocated);
+               BugCheck((DPRINT_MEMORY, "Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray[BlockNumber].BlocksAllocated));
        }
 #endif
 
@@ -181,7 +195,8 @@ VOID FreeMemory(PVOID MemBlock)
 
 #ifdef DEBUG
        DecrementAllocationCount();
-       DebugPrint(DPRINT_MEMORY, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount, BlockNumber, AllocationCount);
+       DbgPrint((DPRINT_MEMORY, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount, BlockNumber, AllocationCount));
+       VerifyHeap();
 #endif DEBUG
 }
 
@@ -192,6 +207,11 @@ VOID VerifyHeap(VOID)
        ULONG   Idx2;
        ULONG   Count;
 
+       if (DUMP_MEM_MAP_ON_VERIFY)
+       {
+               DumpMemoryAllocMap();
+       }
+
        // Loop through the array and verify that
        // everything is kosher
        for (Idx=0; Idx<HeapMemBlockCount; Idx++)
@@ -203,7 +223,7 @@ VOID VerifyHeap(VOID)
                        // had better have a length that is within range
                        if ((HeapMemBlockArray[Idx].BlocksAllocated < 1) || (HeapMemBlockArray[Idx].BlocksAllocated > (HeapMemBlockCount - Idx)))
                        {
-                               BugCheck1("Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray[Idx].BlocksAllocated);
+                               BugCheck((DPRINT_MEMORY, "Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray[Idx].BlocksAllocated));
                        }
 
                        // Now go through and verify that the rest of
@@ -216,30 +236,60 @@ VOID VerifyHeap(VOID)
                                // Make sure it's allocated
                                if (HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE)
                                {
-                                       BugCheck0("Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n");
+                                       BugCheck((DPRINT_MEMORY, "Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n"));
                                }
 
                                // Make sure the length is zero
                                if (HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0)
                                {
-                                       BugCheck0("Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n");
+                                       BugCheck((DPRINT_MEMORY, "Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n"));
                                }
                        }
 
                        // Move on to the next run
-                       Idx += Count;
+                       Idx += (Count - 1);
                }
                else
                {
                        // Nope, not allocated so make sure the length is zero
                        if (HeapMemBlockArray[Idx].BlocksAllocated != 0)
                        {
-                               BugCheck0("Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n");
+                               BugCheck((DPRINT_MEMORY, "Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n"));
                        }
                }
        }
 }
 
+VOID DumpMemoryAllocMap(VOID)
+{
+       ULONG   Idx;
+
+       DbgPrint((DPRINT_MEMORY, "----------- Memory Allocation Bitmap -----------\n"));
+
+       for (Idx=0; Idx<HeapMemBlockCount; Idx++)
+       {
+               if ((Idx % 32) == 0)
+               {
+                       DbgPrint((DPRINT_MEMORY, "\n%x:\t", (Idx * 256)));
+               }
+               else if ((Idx % 4) == 0)
+               {
+                       DbgPrint((DPRINT_MEMORY, " "));
+               }
+
+               if (HeapMemBlockArray[Idx].MemBlockAllocated)
+               {
+                       DbgPrint((DPRINT_MEMORY, "X"));
+               }
+               else
+               {
+                       DbgPrint((DPRINT_MEMORY, "*"));
+               }
+       }
+
+       DbgPrint((DPRINT_MEMORY, "\n"));
+}
+
 VOID IncrementAllocationCount(VOID)
 {
        AllocationCount++;
@@ -266,6 +316,8 @@ VOID MemAllocTest(VOID)
        getch();
        MemPtr3 = AllocateMemory(4096);
        printf("MemPtr3: 0x%x\n", (int)MemPtr3);
+       DumpMemoryAllocMap();
+       VerifyHeap();
        getch();
 
        FreeMemory(MemPtr2);
index 4b81045..cb97c57 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
 #include "tui.h"
 #include "menu.h"
 #include "options.h"
+#include "memory.h"
 
-static int nOSListBoxLeft;
-static int nOSListBoxRight;
-static int nOSListBoxTop;
-static int nOSListBoxBottom;
 
-static int nOSSelected = 0; // Currently selected OS (zero based)
-
-int RunMenu(void)
+typedef struct
 {
-       int             key;
-       int             second;
-       BOOL    bDone = FALSE;
+       PUCHAR *MenuItemList;
+       ULONG   MenuItemCount;
+       LONG    MenuTimeRemaining;
+       ULONG   SelectedMenuItem;
+
+       ULONG   Left;
+       ULONG   Top;
+       ULONG   Right;
+       ULONG   Bottom;
 
-       if (nTimeOut > 0)
-               nTimeOut++; // Increment the timeout since 0 doesn't count for a second
+} MENU_INFO, *PMENU_INFO;
 
-       // Initialise the menu
-       InitMenu();
+VOID   CalcMenuBoxSize(PMENU_INFO MenuInfo);
+VOID   DrawMenu(PMENU_INFO MenuInfo);
+VOID   DrawMenuBox(PMENU_INFO MenuInfo);
+VOID   DrawMenuItem(PMENU_INFO MenuInfo, ULONG MenuItemNumber);
+ULONG  ProcessMenuKeyboardEvent(PMENU_INFO MenuInfo);
 
-       // Update the menu
-       DrawMenu();
+extern ULONG   nScreenWidth;           // Screen Width
+extern ULONG   nScreenHeight;          // Screen Height
 
-       second = getsecond();
+extern CHAR    cStatusBarFgColor;                      // Status bar foreground color
+extern CHAR    cStatusBarBgColor;                      // Status bar background color
+extern CHAR    cBackdropFgColor;                       // Backdrop foreground color
+extern CHAR    cBackdropBgColor;                       // Backdrop background color
+extern CHAR    cBackdropFillStyle;                     // Backdrop fill style
+extern CHAR    cTitleBoxFgColor;                       // Title box foreground color
+extern CHAR    cTitleBoxBgColor;                       // Title box background color
+extern CHAR    cMessageBoxFgColor;                     // Message box foreground color
+extern CHAR    cMessageBoxBgColor;                     // Message box background color
+extern CHAR    cMenuFgColor;                   // Menu foreground color
+extern CHAR    cMenuBgColor;                   // Menu background color
+extern CHAR    cTextColor;                     // Normal text color
+extern CHAR    cSelectedTextColor;                     // Selected text color
+extern CHAR    cSelectedTextBgColor;                   // Selected text background color
 
-       // Loop
-       do
+BOOL DisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, PULONG SelectedMenuItem)
+{
+       PUCHAR          ScreenBuffer;
+       MENU_INFO       MenuInformation;
+       ULONG           CurrentClockSecond;
+
+       //
+       // The first thing we need to check is the timeout
+       // If it's zero then don't bother with anything,
+       // just return the default item
+       //
+       if (MenuTimeOut == 0)
        {
-               // Check for a keypress
-               if (kbhit())
+               if (SelectedMenuItem != NULL)
                {
-                       // Cancel the timeout
-                       if (nTimeOut != -1)
-                       {
-                               nTimeOut = -1;
-                               DrawMenu();
-                       }
+                       *SelectedMenuItem = DefaultMenuItem;
+               }
+
+               return TRUE;
+       }
+
+       //
+       // Allocate memory to hold screen contents before menu is drawn
+       //
+       ScreenBuffer = AllocateMemory(4000);
+       if (ScreenBuffer == NULL)
+       {
+               return FALSE;
+       }
 
-                       // Get the key
-                       key = getch();
+       //
+       // Save screen contents to our buffer
+       //
+       SaveScreen(ScreenBuffer);
 
-                       // Is it extended?
-                       if (key == 0)
-                               key = getch(); // Yes - so get the extended key
+       //
+       // Setup the MENU_INFO structure
+       //
+       MenuInformation.MenuItemList = MenuItemList;
+       MenuInformation.MenuItemCount = MenuItemCount;
+       MenuInformation.MenuTimeRemaining = MenuTimeOut;
+       MenuInformation.SelectedMenuItem = DefaultMenuItem;
 
-                       // Process the key
-                       switch (key)
-                       {
-                       case KEY_UP:
-                               if (nOSSelected)
-                               {
-                                       nOSSelected--;
-
-                                       // Update the menu
-                                       DrawMenu();
-                               }
-                               break;
-                       case KEY_DOWN:
-                               if (nOSSelected < (nNumOS-1))
-                               {
-                                       nOSSelected++;
-
-                                       // Update the menu
-                                       DrawMenu();
-                               }
-                               break;
-                       case KEY_ENTER:
-                               bDone = TRUE;
-                               break;
-                       case KEY_F8:
-                               DoOptionsMenu();
-                               DrawBackdrop();
-                               DrawMenu();
-                               break;
-                       }
+       //
+       // Calculate the size of the menu box
+       //
+       CalcMenuBoxSize(&MenuInformation);
+
+       //
+       // Draw the menu
+       //
+       DrawMenu(&MenuInformation);
+
+       //
+       // Get the current second of time
+       //
+       CurrentClockSecond = getsecond();
+
+       //
+       // Process keys
+       //
+       while (1)
+       {
+               //
+               // Process key presses
+               //
+               if (ProcessMenuKeyboardEvent(&MenuInformation) == KEY_ENTER)
+               {
+                       //
+                       // If they pressed enter then exit this loop
+                       //
+                       break;
                }
 
+               //
                // Update the date & time
+               //
                UpdateDateTime();
 
-               if (nTimeOut > 0)
+               if (MenuInformation.MenuTimeRemaining > 0)
                {
-                       if (getsecond() != second)
+                       if (getsecond() != CurrentClockSecond)
                        {
-                               second = getsecond();
-                               nTimeOut--;
+                               //
+                               // Update the time information
+                               //
+                               CurrentClockSecond = getsecond();
+                               MenuInformation.MenuTimeRemaining--;
 
+                               //
                                // Update the menu
-                               DrawMenu();
+                               //
+                               DrawMenuBox(&MenuInformation);
                        }
                }
-
-               if (nTimeOut == 0)
-                       bDone = TRUE;
+               else if (MenuInformation.MenuTimeRemaining == 0)
+               {
+                       //
+                       // A time out occurred, exit this loop and return default OS
+                       //
+                       break;
+               }
        }
-       while (!bDone);
 
-       return nOSSelected;
+       //
+       // Update the selected menu item information
+       //
+       if (SelectedMenuItem != NULL)
+       {
+               *SelectedMenuItem = MenuInformation.SelectedMenuItem;
+       }
+       
+       return TRUE;
 }
 
-void InitMenu(void)
+VOID CalcMenuBoxSize(PMENU_INFO MenuInfo)
 {
-       int             i;
-       int             height = 1; // Allow room for top & bottom borders
-       int             width = 0;
+       ULONG   Idx;
+       ULONG   Width;
+       ULONG   Height;
+       ULONG   Length;
 
-       for(i=0; i<nNumOS; i++)
+       //
+       // Height is the menu item count plus 2 (top border & bottom border)
+       //
+       Height = MenuInfo->MenuItemCount + 2;
+       Height -= 1; // Height is zero-based
+
+       //
+       // Find the length of the longest string in the menu
+       //
+       Width = 0;
+       for(Idx=0; Idx<MenuInfo->MenuItemCount; Idx++)
        {
-               height++;
-               if(strlen(OSList[i].name) > width)
-                       width = strlen(OSList[i].name);
+               Length = strlen(MenuInfo->MenuItemList[Idx]);
+
+               if (Length > Width)
+               {
+                       Width = Length;
+               }
        }
-       width += 18; // Allow room for left & right borders, plus 8 spaces on each side
 
-       // Calculate the OS list box area
-       nOSListBoxLeft = (nScreenWidth - width) / 2;
-       nOSListBoxRight = nOSListBoxLeft + width;
-       nOSListBoxTop = (nScreenHeight - height) / 2 + 1;
-       nOSListBoxBottom = nOSListBoxTop + height;
+       //
+       // Allow room for left & right borders, plus 8 spaces on each side
+       //
+       Width += 18;
 
-       nOSSelected = 0;
+       //
+       // Calculate the menu box area
+       //
+       MenuInfo->Left = (nScreenWidth - Width) / 2;
+       MenuInfo->Right = (MenuInfo->Left) + Width;
+       MenuInfo->Top = (( (nScreenHeight - TITLE_BOX_HEIGHT) - Height) / 2 + 1) + (TITLE_BOX_HEIGHT / 2);
+       MenuInfo->Bottom = (MenuInfo->Top) + Height;
 }
 
-void DrawMenu(void)
+VOID DrawMenu(PMENU_INFO MenuInfo)
 {
-       int             i, j;
-       char    text[260];
-       char    temp[260];
-       int             space, space_left, space_right;
+       ULONG   Idx;
+
+       //
+       // Draw the menu box
+       //
+       DrawMenuBox(MenuInfo);
 
+       //
+       // Draw each line of the menu
+       //
+       for (Idx=0; Idx<MenuInfo->MenuItemCount; Idx++)
+       {
+               DrawMenuItem(MenuInfo, Idx);
+       }
+}
+
+VOID DrawMenuBox(PMENU_INFO MenuInfo)
+{
+       UCHAR   MenuLineText[80];
+       UCHAR   TempString[80];
+
+       //
        // Update the status bar
-       DrawStatusText(" Use \x18\x19 to select, ENTER to boot. Press F8 for advanced options.");
+       //
+       DrawStatusText(" Use \x18\x19 to select, ENTER to boot.");
+
+       //
+       // Draw the menu box
+       //
+       DrawBox(MenuInfo->Left,
+               MenuInfo->Top,
+               MenuInfo->Right,
+               MenuInfo->Bottom,
+               D_VERT,
+               D_HORZ,
+               FALSE,          // Filled
+               TRUE,           // Shadow
+               ATTR(cMenuFgColor, cMenuBgColor));
+
+       //
+       // If there is a timeout draw the time remaining
+       //
+       if (MenuInfo->MenuTimeRemaining >= 0)
+       {
+               strcpy(MenuLineText, "[ Time Remaining: ");
+               itoa(MenuInfo->MenuTimeRemaining, TempString, 10);
+               strcat(MenuLineText, TempString);
+               strcat(MenuLineText, " ]");
 
-       DrawBox(nOSListBoxLeft, nOSListBoxTop, nOSListBoxRight, nOSListBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
+               DrawText(MenuInfo->Right - strlen(MenuLineText) - 1,
+                       MenuInfo->Bottom,
+                       MenuLineText,
+                       ATTR(cMenuFgColor, cMenuBgColor));
+       }
+}
+
+VOID DrawMenuItem(PMENU_INFO MenuInfo, ULONG MenuItemNumber)
+{
+       ULONG   Idx;
+       UCHAR   MenuLineText[80];
+       ULONG   SpaceTotal;
+       ULONG   SpaceLeft;
+       ULONG   SpaceRight;
+
+       //
+       // We will want the string centered so calculate
+       // how many spaces will be to the left and right
+       //
+       SpaceTotal = (MenuInfo->Right - MenuInfo->Left - 2) - strlen(MenuInfo->MenuItemList[MenuItemNumber]);
+       SpaceLeft = (SpaceTotal / 2) + 1;
+       SpaceRight = (SpaceTotal - SpaceLeft) + 1;
+
+       //
+       // Insert the spaces on the left
+       //
+       for (Idx=0; Idx<SpaceLeft; Idx++)
+       {
+               MenuLineText[Idx] = ' ';
+       }
+       MenuLineText[Idx] = '\0';
+
+       //
+       // Now append the text string
+       //
+       strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
+
+       //
+       // Now append the spaces on the right
+       //
+       for (Idx=0; Idx<SpaceRight; Idx++)
+       {
+               strcat(MenuLineText, " ");
+       }
+
+       //
+       // If this is the selected menu item then draw it as selected
+       // otherwise just draw it using the normal colors
+       //
+       if (MenuItemNumber == MenuInfo->SelectedMenuItem)
+       {
+               DrawText(MenuInfo->Left + 1,
+                       MenuInfo->Top + 1 + MenuItemNumber,
+                       MenuLineText,
+                       ATTR(cSelectedTextColor, cSelectedTextBgColor));
+       }
+       else
+       {
+               DrawText(MenuInfo->Left + 1,
+                       MenuInfo->Top + 1 + MenuItemNumber,
+                       MenuLineText,
+                       ATTR(cTextColor, cMenuBgColor));
+       }
+}
+
+ULONG ProcessMenuKeyboardEvent(PMENU_INFO MenuInfo)
+{
+       ULONG   KeyEvent = 0;
 
-       for(i=0; i<nNumOS; i++)
+       //
+       // Check for a keypress
+       //
+       if (kbhit())
        {
-               space = (nOSListBoxRight - nOSListBoxLeft - 2) - strlen(OSList[i].name);
-               space_left = (space / 2) + 1;
-               space_right = (space - space_left) + 1;
-
-               text[0] = '\0';
-               for(j=0; j<space_left; j++)
-                       strcat(text, " ");
-               strcat(text, OSList[i].name);
-               for(j=0; j<space_right; j++)
-                       strcat(text, " ");
-
-               if(i == nOSSelected)
+               //
+               // Cancel the timeout
+               //
+               if (MenuInfo->MenuTimeRemaining != -1)
                {
-                       DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
+                       MenuInfo->MenuTimeRemaining = -1;
+                       DrawMenuBox(MenuInfo);
                }
-               else
+
+               //
+               // Get the key
+               //
+               KeyEvent = getch();
+
+               //
+               // Is it extended?
+               //
+               if (KeyEvent == 0)
+                       KeyEvent = getch(); // Yes - so get the extended key
+
+               //
+               // Process the key
+               //
+               switch (KeyEvent)
                {
-                       DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
-               }
-       }
+               case KEY_UP:
+                       
+                       if (MenuInfo->SelectedMenuItem > 0)
+                       {
+                               MenuInfo->SelectedMenuItem--;
 
-       if (nTimeOut >= 0)
-       {
-               strcpy(text, "[ Time Remaining: ");
-               itoa(nTimeOut, temp, 10);
-               strcat(text, temp);
-               strcat(text, " ]");
+                               //
+                               // Update the menu
+                               //
+                               DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem + 1); // Deselect previous item
+                               DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem);             // Select new item
+                       }
+
+                       break;
 
-               DrawText(nOSListBoxRight - strlen(text) - 1, nOSListBoxBottom, text, ATTR(cMenuFgColor, cMenuBgColor));
+               case KEY_DOWN:
+
+                       if (MenuInfo->SelectedMenuItem < (MenuInfo->MenuItemCount - 1))
+                       {
+                               MenuInfo->SelectedMenuItem++;
+
+                               //
+                               // Update the menu
+                               //
+                               DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem - 1); // Deselect previous item
+                               DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem);             // Select new item
+                       }
+
+                       break;
+               }
        }
-}
\ No newline at end of file
+
+       return KeyEvent;
+}
index ebf085f..b30d0b6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  FreeLoader
- *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
  *
  *  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
@@ -20,8 +20,6 @@
 #ifndef __MENU_H
 #define __MENU_H
 
-int            RunMenu(void);
-void   InitMenu(void);
-void   DrawMenu(void);
+BOOL   DisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, PULONG SelectedMenuItem);
 
 #endif // #defined __MENU_H
\ No newline at end of file
index 43a76b7..c084cc7 100644 (file)
 
 void LoadAndBootBootSector(int nOSToBoot)
 {
-       FILE    file;
+       FILE*   FilePointer;
        char    name[260];
        char    value[260];
        char    szFileName[1024];
        int             i;
+       ULONG   BytesRead;
 
        // Find all the message box settings and run them
-       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       /*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
        {
                ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
                if (stricmp(name, "MessageBox") == 0)
@@ -69,7 +70,9 @@ void LoadAndBootBootSector(int nOSToBoot)
        }
 
        strcpy(szFileName, value);
-       if (!OpenFile(szFileName, &file))
+
+       FilePointer = OpenFile(szFileName);
+       if (FilePointer == NULL)
        {
                strcat(value, " not found.");
                MessageBox(value);
@@ -77,7 +80,7 @@ void LoadAndBootBootSector(int nOSToBoot)
        }
 
        // Read boot sector
-       if (ReadFile(&file, 512, (void*)0x7c00) != 512)
+       if (!ReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
        {
                MessageBox("Disk Read Error");
                return;
@@ -95,7 +98,7 @@ void LoadAndBootBootSector(int nOSToBoot)
        gotoxy(CursorXPos, CursorYPos);
 
        stop_floppy();
-       JumpToBootCode();
+       JumpToBootCode();*/
 }
 
 void LoadAndBootPartition(int nOSToBoot)
@@ -107,7 +110,7 @@ void LoadAndBootPartition(int nOSToBoot)
        int             i;
 
        // Find all the message box settings and run them
-       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       /*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
        {
                ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
                if (stricmp(name, "MessageBox") == 0)
@@ -132,14 +135,14 @@ void LoadAndBootPartition(int nOSToBoot)
 
        BootPartition = atoi(value);
 
-       if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
+       if (!BiosInt13Read(BootDrive, 0, 0, 1, 1, DISKREADBUFFER))
        {
                MessageBox("Disk Read Error");
                return;
        }
 
        // Check for validity
-       if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
+       if (*((WORD*)(DISKREADBUFFER + 0x1fe)) != 0xaa55)
        {
                MessageBox("Invalid partition table magic (0xaa55)");
                return;
@@ -181,7 +184,7 @@ void LoadAndBootPartition(int nOSToBoot)
        gotoxy(CursorXPos, CursorYPos);
 
        stop_floppy();
-       JumpToBootCode();
+       JumpToBootCode();*/
 }
 
 void LoadAndBootDrive(int nOSToBoot)
@@ -191,7 +194,7 @@ void LoadAndBootDrive(int nOSToBoot)
        int             i;
 
        // Find all the message box settings and run them
-       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       /*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
        {
                ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
                if (stricmp(name, "MessageBox") == 0)
@@ -226,5 +229,5 @@ void LoadAndBootDrive(int nOSToBoot)
        gotoxy(CursorXPos, CursorYPos);
 
        stop_floppy();
-       JumpToBootCode();
+       JumpToBootCode();*/
 }
index 8bac0bc..78b11a8 100644 (file)
@@ -36,12 +36,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
        DWORD                           dwFileLoadOffset;
        DWORD                           dwDataSize;
        DWORD                           dwBssSize;
+       ULONG                           BytesRead;
 
        /*
         * Load the first 8192 bytes of the kernel image
         * so we can search for the multiboot header
         */
-       ReadFile(KernelImage, 8192, ImageHeaders);
+       ReadFile(KernelImage, 8192, NULL, ImageHeaders);
 
        /*
         * Now find the multiboot header and copy it
@@ -95,13 +96,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
         * Get the file offset, this should be 0, and move the file pointer
         */
        dwFileLoadOffset = (Idx * sizeof(DWORD)) - (mb_header.header_addr - mb_header.load_addr);
-       fseek(KernelImage, dwFileLoadOffset);
+       SetFilePointer(KernelImage, dwFileLoadOffset);
        
        /*
         * Load the file image
         */
        dwDataSize = (mb_header.load_end_addr - mb_header.load_addr);
-       ReadFile(KernelImage, dwDataSize, (void*)mb_header.load_addr);
+       ReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr);
 
        /*
         * Initialize bss area
@@ -142,7 +143,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
        /*
         * Load the file image
         */
-       ReadFile(ModuleImage, dwModuleSize, (void*)next_module_load_base);
+       ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
 
        next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
        mb_info.mods_count++;
@@ -154,10 +155,14 @@ int GetBootPartition(char *OperatingSystemName)
 {
        int             BootPartitionNumber = -1;
        char    value[1024];
+       ULONG   SectionId;
 
-       if (ReadSectionSettingByName(OperatingSystemName, "BootPartition", value))
+       if (OpenSection(OperatingSystemName, &SectionId))
        {
-               BootPartitionNumber = atoi(value);
+               if (ReadSectionSettingByName(SectionId, "BootPartition", value, 1024))
+               {
+                       BootPartitionNumber = atoi(value);
+               }
        }
 
        return BootPartitionNumber;
index 3a0e92d..e779d0f 100644 (file)
@@ -23,7 +23,7 @@
 #include "options.h"
 #include "miscboot.h"
 
-
+#if 0
 void DoOptionsMenu(void)
 {
        int             OptionsMenuItemCount = 1; // Count is 1 because we don't show the "Set ReactOS Boot Flags" menu item yet
@@ -101,7 +101,7 @@ void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
        char    BootOptionsMenuItems[2][80] = { "Boot To ", "Pick A Boot Partition"     };
        int             BootOptionsMenuItemSelected = 0;
 
-       strcat(BootOptionsMenuItems[0], BootDriveText);
+       /*strcat(BootOptionsMenuItems[0], BootDriveText);
 
        while (BootOptionsMenuItemSelected != -1)
        {
@@ -144,7 +144,7 @@ void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
 
                        break;
                }
-       }
+       }*/
 }
 
 void DoBootPartitionOptionsMenu(int BootDriveNum)
@@ -164,7 +164,7 @@ void DoBootPartitionOptionsMenu(int BootDriveNum)
        char    temp[25];
 
 
-       BootDrive = BootDriveNum;
+       /*BootDrive = BootDriveNum;
 
        if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
        {
@@ -244,7 +244,7 @@ void DoBootPartitionOptionsMenu(int BootDriveNum)
                        stop_floppy();
                        JumpToBootCode();
                }
-       }
+       }*/
 }
 
 int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle)
@@ -345,7 +345,7 @@ int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nO
 
 void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount)
 {
-       int             height = OptionsMenuItemCount;
+       /*int           height = OptionsMenuItemCount;
        int             width = 20;
 
        height += 1; // Allow room for top & bottom borders
@@ -355,7 +355,7 @@ void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOp
        *nOptionsMenuBoxLeft = (nScreenWidth - width) / 2;
        *nOptionsMenuBoxRight = *nOptionsMenuBoxLeft + width;
        *nOptionsMenuBoxTop = (nScreenHeight - height) / 2 + 1;
-       *nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;
+       *nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;*/
 }
 
 void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom)
@@ -365,7 +365,7 @@ void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int
        int             space, space_left, space_right;
 
        // Update the status bar
-       DrawStatusText(" Use \x18\x19 to select, then press ENTER. Press ESC to go back.");
+       /*DrawStatusText(" Use \x18\x19 to select, then press ENTER. Press ESC to go back.");
 
        DrawBox(nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
        DrawText(nOptionsMenuBoxLeft + (((nOptionsMenuBoxRight - nOptionsMenuBoxLeft) - strlen(OptionsMenuTitle)) / 2) + 1, nOptionsMenuBoxTop, OptionsMenuTitle, ATTR(cMenuFgColor, cMenuBgColor));
@@ -391,5 +391,6 @@ void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int
                {
                        DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
                }
-       }
-}
\ No newline at end of file
+       }*/
+}
+#endif
\ No newline at end of file
diff --git a/freeldr/freeldr/oslist.c b/freeldr/freeldr/oslist.c
new file mode 100644 (file)
index 0000000..34d67df
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+       
+#include "freeldr.h"
+#include "parseini.h"
+#include "oslist.h"
+
+BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, PULONG OperatingSystemCountPointer)
+{
+       ULONG   Idx;
+       ULONG   CurrentOperatingSystemIndex;
+       UCHAR   SettingName[80];
+       UCHAR   SettingValue[80];
+       ULONG   OperatingSystemCount;
+       ULONG   SectionId;
+       ULONG   OperatingSystemSectionId;
+       ULONG   SectionSettingCount;
+       PUCHAR  *OperatingSystemSectionNames;
+       PUCHAR  *OperatingSystemDisplayNames;
+
+       //
+       // Open the [FreeLoader] section
+       //
+       if (!OpenSection("FreeLoader", &SectionId))
+       {
+               MessageBox("Section [FreeLoader] not found in freeldr.ini.");
+               return FALSE;
+       }
+
+       SectionSettingCount = GetNumSectionItems(SectionId);
+       OperatingSystemCount = CountOperatingSystems(SectionId);
+
+       //
+       // Allocate memory to hold operating system lists
+       //
+       if (!AllocateListMemory(&OperatingSystemSectionNames, &OperatingSystemDisplayNames, OperatingSystemCount))
+       {
+               return FALSE;
+       }
+
+       //
+       // Now loop through and read the operating system section names
+       //
+       CurrentOperatingSystemIndex = 0;
+       for (Idx=0; Idx<SectionSettingCount; Idx++)
+       {
+               ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
+
+               if (stricmp(SettingName, "OS") == 0)
+               {
+                       strcpy(OperatingSystemSectionNames[CurrentOperatingSystemIndex], SettingValue);
+
+                       CurrentOperatingSystemIndex++;
+               }
+       }
+       
+       //
+       // Now loop through and read the operating system display names
+       //
+       for (Idx=0; Idx<OperatingSystemCount; Idx++)
+       {
+               if (OpenSection(OperatingSystemSectionNames[Idx], &OperatingSystemSectionId))
+               {
+                       if (ReadSectionSettingByName(OperatingSystemSectionId, "Name", SettingValue, 80))
+                       {
+                               //
+                               // Remove any quotes around the string
+                               //
+                               RemoveQuotes(SettingValue);
+                               strcpy(OperatingSystemDisplayNames[Idx], SettingValue);
+                       }
+                       else
+                       {
+                               sprintf(SettingName, "Operating System '%s' has no Name= line in it's [section].", OperatingSystemSectionNames[Idx]);
+                               MessageBox(SettingName);
+                               strcpy(OperatingSystemDisplayNames[Idx], "");
+                       }
+               }
+       }
+
+       *OperatingSystemCountPointer = OperatingSystemCount;
+       *SectionNamesPointer = OperatingSystemSectionNames;
+       *DisplayNamesPointer = OperatingSystemDisplayNames;
+
+       return TRUE;
+}
+
+ULONG CountOperatingSystems(ULONG SectionId)
+{
+       ULONG   Idx;
+       UCHAR   SettingName[80];
+       UCHAR   SettingValue[80];
+       ULONG   OperatingSystemCount = 0;
+       ULONG   SectionSettingCount;
+       
+       //
+       // Loop through and count the operating systems
+       //
+       SectionSettingCount = GetNumSectionItems(SectionId);
+       for (Idx=0; Idx<SectionSettingCount; Idx++)
+       {
+               ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
+
+               if (stricmp(SettingName, "OS") == 0)
+               {
+                       if (OpenSection(SettingValue, NULL))
+                       {
+                               OperatingSystemCount++;
+                       }
+                       else
+                       {
+                               sprintf(SettingName, "Operating System '%s' is listed in freeldr.ini but doesn't have a [section].", SettingValue);
+                               MessageBox(SettingName);
+                       }
+               }
+       }
+
+       return OperatingSystemCount;
+}
+
+BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount)
+{
+       ULONG   Idx;
+       PUCHAR  *OperatingSystemSectionNames = NULL;
+       PUCHAR  *OperatingSystemDisplayNames = NULL;
+
+       //
+       // Allocate memory to hold operating system list arrays
+       //
+       OperatingSystemSectionNames = (PUCHAR*) AllocateMemory( sizeof(PUCHAR) * OperatingSystemCount);
+       OperatingSystemDisplayNames = (PUCHAR*) AllocateMemory( sizeof(PUCHAR) * OperatingSystemCount);
+       
+       //
+       // If either allocation failed then return FALSE
+       //
+       if ( (OperatingSystemSectionNames == NULL) || (OperatingSystemDisplayNames == NULL) )
+       {
+               if (OperatingSystemSectionNames != NULL)
+               {
+                       FreeMemory(OperatingSystemSectionNames);
+               }
+
+               if (OperatingSystemDisplayNames != NULL)
+               {
+                       FreeMemory(OperatingSystemDisplayNames);
+               }
+
+               return FALSE;
+       }
+
+       //
+       // Clear our newly allocated memory
+       //
+       memset(OperatingSystemSectionNames, 0, sizeof(PUCHAR) * OperatingSystemCount);
+       memset(OperatingSystemDisplayNames, 0, sizeof(PUCHAR) * OperatingSystemCount);
+
+       //
+       // Loop through each array element and allocate it's string memory
+       //
+       for (Idx=0; Idx<OperatingSystemCount; Idx++)
+       {
+               OperatingSystemSectionNames[Idx] = (PUCHAR) AllocateMemory(80);
+               OperatingSystemDisplayNames[Idx] = (PUCHAR) AllocateMemory(80);
+
+               //
+               // If it failed then jump to the cleanup code
+               //
+               if ( (OperatingSystemSectionNames[Idx] == NULL) || (OperatingSystemDisplayNames[Idx] == NULL))
+               {
+                       goto AllocateListMemoryFailed;
+               }
+       }
+
+       *SectionNamesPointer = OperatingSystemSectionNames;
+       *DisplayNamesPointer = OperatingSystemDisplayNames;
+
+       return TRUE;
+
+AllocateListMemoryFailed:
+
+       //
+       // Loop through each array element and free it's string memory
+       //
+       for (Idx=0; Idx<OperatingSystemCount; Idx++)
+       {
+               if (OperatingSystemSectionNames[Idx] != NULL)
+               {
+                       FreeMemory(OperatingSystemSectionNames[Idx]);
+               }
+
+               if (OperatingSystemDisplayNames[Idx] != NULL)
+               {
+                       FreeMemory(OperatingSystemDisplayNames[Idx]);
+               }
+       }
+
+       //
+       // Free operating system list arrays
+       //
+       FreeMemory(OperatingSystemSectionNames);
+       FreeMemory(OperatingSystemDisplayNames);
+
+       return FALSE;
+}
+
+BOOL RemoveQuotes(PUCHAR QuotedString)
+{
+       UCHAR   TempString[200];
+
+       //
+       // If this string is not quoted then return FALSE
+       //
+       if ((QuotedString[0] != '\"') && (QuotedString[strlen(QuotedString)-1] != '\"'))
+       {
+               return FALSE;
+       }
+
+       if (QuotedString[0] == '\"')
+       {
+               strcpy(TempString, (QuotedString + 1));
+       }
+       else
+       {
+               strcpy(TempString, QuotedString);
+       }
+
+       if (TempString[strlen(TempString)-1] == '\"')
+       {
+               TempString[strlen(TempString)-1] = '\0';
+       }
+
+       strcpy(QuotedString, TempString);
+
+       return TRUE;
+}
diff --git a/freeldr/freeldr/oslist.h b/freeldr/freeldr/oslist.h
new file mode 100644 (file)
index 0000000..3ce0e85
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 2001  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __OSLIST_H
+#define __OSLIST_H
+
+BOOL   InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, PULONG OperatingSystemCountPointer);
+ULONG  CountOperatingSystems(ULONG SectionId);
+BOOL   AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount);
+BOOL   RemoveQuotes(PUCHAR QuotedString);
+
+#endif // #defined __OSLIST_H
index 1bb2615..681c1eb 100644 (file)
 #include "fs.h"
 #include "stdlib.h"
 #include "memory.h"
+#include "debug.h"
 
 PUCHAR FreeLoaderIniFileData = NULL;
 ULONG  FreeLoaderIniFileSize = 0;
 
-BOOL ParseIniFile(void)
+BOOL ParseIniFile(VOID)
 {
-       int             i;
-       char    name[1024];
-       char    value[1024];
-       FILE    Freeldr_Ini;    // File handle for freeldr.ini
+       //int           i;
+       //char  name[1024];
+       //char  value[1024];
+       PFILE   Freeldr_Ini;    // File handle for freeldr.ini
 
        // Open the boot drive for file access
        if (!OpenDiskDrive(BootDrive, 0))
@@ -42,28 +43,31 @@ BOOL ParseIniFile(void)
        }
 
        // Try to open freeldr.ini or fail
-       if (!OpenFile("freeldr.ini", &Freeldr_Ini))
+       Freeldr_Ini = OpenFile("freeldr.ini");
+       if (Freeldr_Ini == NULL)
        {
                printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
                return FALSE;
        }
 
        // Get the file size & allocate enough memory for it
-       FreeLoaderIniFileSize = GetFileSize(&Freeldr_Ini);
+       FreeLoaderIniFileSize = GetFileSize(Freeldr_Ini);
        FreeLoaderIniFileData = AllocateMemory(FreeLoaderIniFileSize);
 
        // If we are out of memory then return FALSE
        if (FreeLoaderIniFileData == NULL)
        {
                printf("Out of memory while loading FREELDR.INI.\n");
+               CloseFile(Freeldr_Ini);
                return FALSE;
        }
 
        // Read freeldr.ini off the disk
-       ReadFile(&Freeldr_Ini, FreeLoaderIniFileSize, FreeLoaderIniFileData);
+       ReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData);
+       CloseFile(Freeldr_Ini);
 
        // Make sure the [FREELOADER] section exists
-       if (!GetNumSectionItems("FREELOADER"))
+       /*if (OpenSection("FREELOADER", NULL))
        {
                printf("Section [FREELOADER] not found in FREELDR.INI.\nYou need to re-install FreeLoader.\n");
                return FALSE;
@@ -81,7 +85,7 @@ BOOL ParseIniFile(void)
                }
                else
                        SetSetting(name, value);
-       }
+       }*/
 
        return TRUE;
 }
@@ -122,208 +126,202 @@ ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset
        return CurrentOffset;
 }
 
-ULONG GetOffsetOfFirstLineOfSection(PUCHAR SectionName)
+BOOL OpenSection(PUCHAR SectionName, PULONG SectionId)
 {
-       char    str[1024];
-       char    real_section[1024];
-       ULONG   freeldr_ini_offset;
+       UCHAR   TempString[80];
+       UCHAR   RealSectionName[80];
+       ULONG   FileOffset;
        BOOL    SectionFound = FALSE;
 
+       //
        // Get the real section name
-       strcpy(real_section, "[");
-       strcat(real_section, SectionName);
-       strcat(real_section, "]");
+       //
+       strcpy(RealSectionName, "[");
+       strcat(RealSectionName, SectionName);
+       strcat(RealSectionName, "]");
 
+       //
        // Get to the beginning of the file
-       freeldr_ini_offset = 0;
+       //
+       FileOffset = 0;
 
+       //
        // Find the section
-       while (freeldr_ini_offset < FreeLoaderIniFileSize)
+       //
+       while (FileOffset < FreeLoaderIniFileSize)
        {
+               //
                // Read a line
-               freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
-
-               // Skip comments
-               if (str[0] == '#')
-                       continue;
-
-               // Skip blank lines
-               if (!strlen(str))
-                       continue;
+               //
+               FileOffset = GetNextLineOfFileData(TempString, 80, FileOffset);
 
+               //
                // If it isn't a section header then continue on
-               if (str[0] != '[')
+               //
+               if (TempString[0] != '[')
                        continue;
 
+               //
                // Check and see if we found it
-               if (stricmp(str, real_section) == 0)
+               //
+               if (stricmp(TempString, RealSectionName) == 0)
                {
                        SectionFound = TRUE;
                        break;
                }
        }
 
-       // If we didn't find the section then we're outta here
-       if (!SectionFound)
-               return 0;
+       if (SectionId)
+       {
+               *SectionId = FileOffset;
+       }
 
-       return freeldr_ini_offset;
+       return SectionFound;
 }
 
-ULONG GetNumSectionItems(PUCHAR SectionName)
+ULONG GetNumSectionItems(ULONG SectionId)
 {
-       UCHAR   str[1024];
-       ULONG   num_items = 0;
-       ULONG   freeldr_ini_offset;
-
-       // Get to the beginning of the section
-       freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
-
-       // If the section wasn't found then exit
-       if (freeldr_ini_offset == 0)
-       {
-               return 0;
-       }
+       UCHAR   TempString[80];
+       ULONG   SectionItemCount = 0;
 
        // Now count how many settings are in this section
-       while (freeldr_ini_offset < FreeLoaderIniFileSize)
+       while (SectionId < FreeLoaderIniFileSize)
        {
                // Read a line
-               freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
+               SectionId = GetNextLineOfFileData(TempString, 80, SectionId);
+
+               // If we hit a new section then we're done
+               if (TempString[0] == '[')
+                       break;
 
                // Skip comments
-               if (str[0] == '#')
+               if (TempString[0] == '#')
                        continue;
 
                // Skip blank lines
-               if (!strlen(str))
+               if (!strlen(TempString))
                        continue;
 
-               // If we hit a new section then we're done
-               if (str[0] == '[')
-                       break;
-
-               num_items++;
+               SectionItemCount++;
        }
 
-       return num_items;
+       return SectionItemCount;
 }
 
-BOOL ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue)
+BOOL ReadSectionSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize)
 {
-       UCHAR   str[1024];
-       ULONG   num_items = 0;
-       ULONG   i;
-       ULONG   freeldr_ini_offset;
+       UCHAR   TempString[1024];
+       ULONG   SectionItemCount = 0;
+       ULONG   Idx;
+       ULONG   FileOffset;
 
+       //
        // Get to the beginning of the section
-       freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
-
-       // If the section wasn't found then exit
-       if (freeldr_ini_offset == 0)
-       {
-               return 0;
-       }
+       //
+       FileOffset = SectionId;
 
+       //
        // Now find the setting we are looking for
-       while (freeldr_ini_offset < FreeLoaderIniFileSize)
+       //
+       do
        {
                // Read a line
-               freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
+               FileOffset = GetNextLineOfFileData(TempString, 1024, FileOffset);
 
                // Skip comments
-               if (str[0] == '#')
+               if (TempString[0] == '#')
                        continue;
 
                // Skip blank lines
-               if (!strlen(str))
+               if (!strlen(TempString))
                        continue;
 
                // If we hit a new section then we're done
-               if (str[0] == '[')
+               if (TempString[0] == '[')
                        break;
 
-               // Increment setting number
-               num_items++;
-
                // Check and see if we found the setting
-               if (num_items == SettingNumber)
+               if (SectionItemCount == SettingNumber)
                {
-                       for (i=0; i<strlen(str); i++)
+                       for (Idx=0; Idx<strlen(TempString); Idx++)
                        {
                                // Check and see if this character is the separator
-                               if (str[i] == '=')
+                               if (TempString[Idx] == '=')
                                {
-                                       SettingName[i] = '\0';
+                                       SettingName[Idx] = '\0';
 
-                                       strcpy(SettingValue, str+i+1);
+                                       strncpy(SettingValue, TempString + Idx + 1, ValueSize);
 
                                        return TRUE;
                                }
-                               else
-                                       SettingName[i] = str[i];
+                               else if (Idx < NameSize)
+                               {
+                                       SettingName[Idx] = TempString[Idx];
+                               }
                        }
                }
+
+               // Increment setting number
+               SectionItemCount++;
        }
+       while (FileOffset < FreeLoaderIniFileSize);
 
        return FALSE;
 }
 
-BOOL ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue)
+BOOL ReadSectionSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize)
 {
-       UCHAR   str[1024];
-       UCHAR   temp[1024];
-       ULONG   i;
-       ULONG   freeldr_ini_offset;
+       UCHAR   TempString[1024];
+       UCHAR   TempBuffer[80];
+       ULONG   Idx;
+       ULONG   FileOffset;
 
+       //
        // Get to the beginning of the section
-       freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
-
-       // If the section wasn't found then exit
-       if (freeldr_ini_offset == 0)
-       {
-               return 0;
-       }
+       //
+       FileOffset = SectionId;
 
+       //
        // Now find the setting we are looking for
-       while (freeldr_ini_offset < FreeLoaderIniFileSize)
+       //
+       while (FileOffset < FreeLoaderIniFileSize)
        {
                // Read a line
-               freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
+               FileOffset = GetNextLineOfFileData(TempString, 1024, FileOffset);
 
                // Skip comments
-               if (str[0] == '#')
+               if (TempString[0] == '#')
                        continue;
 
                // Skip blank lines
-               if (!strlen(str))
+               if (!strlen(TempString))
                        continue;
 
                // If we hit a new section then we're done
-               if (str[0] == '[')
+               if (TempString[0] == '[')
                        break;
 
                // Extract the setting name
-               for (i=0; i<strlen(str); i++)
+               for (Idx=0; Idx<strlen(TempString); Idx++)
                {
-                       if (str[i] != '=')
-                               temp[i] = str[i];
+                       if (TempString[Idx] != '=')
+                               TempBuffer[Idx] = TempString[Idx];
                        else
                        {
-                               temp[i] = '\0';
+                               TempBuffer[Idx] = '\0';
                                break;
                        }
                }
 
                // Check and see if we found the setting
-               if (stricmp(temp, SettingName) == 0)
+               if (stricmp(TempBuffer, SettingName) == 0)
                {
-                       for (i=0; i<strlen(str); i++)
+                       for (Idx=0; Idx<strlen(TempString); Idx++)
                        {
                                // Check and see if this character is the separator
-                               if (str[i] == '=')
+                               if (TempString[Idx] == '=')
                                {
-                                       strcpy(SettingValue, str+i+1);
+                                       strcpy(Buffer, TempString + Idx + 1);
 
                                        return TRUE;
                                }
@@ -434,7 +432,7 @@ BOOL IsValidSetting(char *setting, char *value)
        return FALSE;
 }
 
-void SetSetting(char *setting, char *value)
+/*void SetSetting(char *setting, char *value)
 {
        char    v[260];
 
@@ -519,4 +517,4 @@ void SetSetting(char *setting, char *value)
        }
        else if(stricmp(setting, "TimeOut") == 0)
                nTimeOut = atoi(value);
-}
+}*/
index f123a51..32a29b6 100644 (file)
 #ifndef __PARSEINI_H
 #define __PARSEINI_H
 
-BOOL   ParseIniFile(void);
+/*BOOL ParseIniFile(void);
 ULONG  GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset); // Gets the next line of text (up to BufferSize) after CurrentOffset and returns the offset of the next line
 ULONG  GetOffsetOfFirstLineOfSection(PUCHAR SectionName); // Returns the offset of the first line in the section or zero if the section wasn't found
 ULONG  GetNumSectionItems(PUCHAR SectionName); // returns the number of items in a particular section (i.e. [FREELOADER])
 BOOL   ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue); // Reads the num'th value from section
 BOOL   ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue); // Reads the value named name from section
 BOOL   IsValidSetting(char *setting, char *value);
+void   SetSetting(char *setting, char *value);*/
+
+BOOL   ParseIniFile(VOID);
+ULONG  GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset);
+BOOL   OpenSection(PUCHAR SectionName, PULONG SectionId);
+ULONG  GetNumSectionItems(ULONG SectionId);
+BOOL   ReadSectionSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize);
+BOOL   ReadSectionSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize);
+BOOL   IsValidSetting(char *setting, char *value);
 void   SetSetting(char *setting, char *value);
 
 
index 7fca575..4341c46 100644 (file)
@@ -34,7 +34,7 @@ BOOL  LoadReactOSDrivers(PUCHAR OperatingSystemName);
 
 void LoadAndBootReactOS(PUCHAR OperatingSystemName)
 {
-       FILE            file;
+       PFILE           FilePointer;
        char            name[1024];
        char            value[1024];
        char            szFileName[1024];
@@ -43,6 +43,18 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
        int                     nNumDriverFiles=0;
        int                     nNumFilesLoaded=0;
        char            MsgBuffer[256];
+       ULONG           SectionId;
+
+       //
+       // Open the operating system section
+       // specified in the .ini file
+       //
+       if (!OpenSection(OperatingSystemName, &SectionId))
+       {
+               sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
+               MessageBox(MsgBuffer);
+               return;
+       }
 
        /*
         * Setup multiboot information structure
@@ -73,7 +85,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
        /*
         * Make sure the system path is set in the .ini file
         */
-       if (!ReadSectionSettingByName(OperatingSystemName, "SystemPath", value))
+       if (!ReadSectionSettingByName(SectionId, "SystemPath", value, 1024))
        {
                MessageBox("System path not specified for selected operating system.");
                return;
@@ -99,7 +111,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
        /*
         * Read the optional kernel parameters (if any)
         */
-       if (ReadSectionSettingByName(OperatingSystemName, "Options", value))
+       if (ReadSectionSettingByName(SectionId, "Options", value, 1024))
        {
                strcat(multiboot_kernel_cmdline, " ");
                strcat(multiboot_kernel_cmdline, value);
@@ -113,7 +125,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
        /*
         * Find the kernel image name
         */
-       if(!ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
+       if(!ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
        {
                MessageBox("Kernel image file not specified for selected operating system.");
                return;
@@ -136,12 +148,12 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
        /*
         * Parse the ini file and count the kernel and drivers
         */
-       for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
+       for (i=1; i<=GetNumSectionItems(SectionId); i++)
        {
                /*
                 * Read the setting and check if it's a driver
                 */
-               ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
+               ReadSectionSettingByNumber(SectionId, i, name, 1024, value, 1024);
                if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
                        nNumDriverFiles++;
        }
@@ -150,14 +162,17 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
         * Find the kernel image name
         * and try to load the kernel off the disk
         */
-       if(ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
+       if(ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
        {
                /*
                 * Set the name and try to open the PE image
                 */
-               strcpy(szFileName, szBootPath);
-               strcat(szFileName, value);
-               if (!OpenFile(szFileName, &file))
+               //strcpy(szFileName, szBootPath);
+               //strcat(szFileName, value);
+               strcpy(szFileName, value);
+
+               FilePointer = OpenFile(szFileName);
+               if (FilePointer == NULL)
                {
                        strcat(value, " not found.");
                        MessageBox(value);
@@ -176,7 +191,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
                /*
                 * Load the kernel image
                 */
-               MultiBootLoadKernel(&file);
+               MultiBootLoadKernel(FilePointer);
                
                nNumFilesLoaded++;
                DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
@@ -186,20 +201,23 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
         * Parse the ini file and load the kernel and
         * load all the drivers specified
         */
-       for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
+       for (i=1; i<=GetNumSectionItems(SectionId); i++)
        {
                /*
                 * Read the setting and check if it's a driver
                 */
-               ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
+               ReadSectionSettingByNumber(SectionId, i, name, 1024, value, 1024);
                if (stricmp(name, "Driver") == 0)
                {
                        /*
                         * Set the name and try to open the PE image
                         */
-                       strcpy(szFileName, szBootPath);
-                       strcat(szFileName, value);
-                       if (!OpenFile(szFileName, &file))
+                       //strcpy(szFileName, szBootPath);
+                       //strcat(szFileName, value);
+                       strcpy(szFileName, value);
+
+                       FilePointer = OpenFile(szFileName);
+                       if (FilePointer == NULL)
                        {
                                strcat(value, " not found.");
                                MessageBox(value);
@@ -218,7 +236,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
                        /*
                         * Load the driver
                         */
-                       MultiBootLoadModule(&file, szFileName);
+                       MultiBootLoadModule(FilePointer, szFileName);
 
 
                        nNumFilesLoaded++;
index 6f6c345..be80b2d 100644 (file)
@@ -253,6 +253,17 @@ char *strcpy(char *dest, char *src)
        return ret;
 }
 
+char *strncpy(char *dest, char *src, size_t count)
+{
+       char    *ret = dest;
+
+       while((*src) && (count--))
+               *dest++ = *src++;
+       *dest = 0;
+
+       return ret;
+}
+
 char *strcat(char *dest, char *src)
 {
        char    *ret = dest;
@@ -324,19 +335,19 @@ int _strnicmp(const char *string1, const char *string2, size_t length)
        return 0;
 }
 
-char *fgets(char *string, int n, FILE *stream)
+char *fgets(char *string, int n, PFILE stream)
 {
        int     i;
 
        for(i=0; i<(n-1); i++)
        {
-               if(feof(stream))
+               if(IsEndOfFile(stream))
                {
                        i++;
                        break;
                }
 
-               ReadFile(stream, 1, string+i);
+               ReadFile(stream, 1, NULL, string+i);
 
                if(string[i] == '\n')
                {
index 13a5ebf..7bde1c9 100644 (file)
@@ -40,6 +40,7 @@ int           wherey(void);                   // Implemented in asmcode.S
 
 int    strlen(char *str);
 char   *strcpy(char *dest, char *src);
+char   *strncpy(char *dest, char *src, size_t count);
 char   *strcat(char *dest, char *src);
 char   *strchr(const char *s, int c);
 int    strcmp(const char *string1, const char *string2);
@@ -51,7 +52,7 @@ int   tolower(int c);
 int    memcmp(const void *buf1, const void *buf2, size_t count);
 void   *memcpy(void *dest, const void *src, size_t count);
 void   *memset(void *dest, int c, size_t count);
-char   *fgets(char *string, int n, FILE *stream);
+char   *fgets(char *string, int n, PFILE stream);
 int    atoi(char *string);
 
 #define ZeroMemory(Destination, Length) memset(Destination, 0, Length)
@@ -64,18 +65,15 @@ void        sprintf(char *buffer, char *format, ...);
 char *convert_to_ascii(char *buf, int c, ...);
 
 int    biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
+
+BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer); // Implemented in asmcode.S
+BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer); // Implemented in asmcode.S
+BOOL BiosInt13ExtensionsSupported(ULONG Drive);
+
 void   stop_floppy(void);              // Implemented in asmcode.S
 int    get_heads(int drive);           // Implemented in asmcode.S
 int    get_cylinders(int drive);       // Implemented in asmcode.S
 int    get_sectors(int drive);         // Implemented in asmcode.S
 
-/* Values for biosdisk() */
-#define _DISK_RESET            0       // Unimplemented
-#define _DISK_STATUS   1       // Unimplemented
-#define _DISK_READ             2       // Reads a sector into memory
-#define _DISK_WRITE            3       // Unimplemented
-#define _DISK_VERIFY   4       // Unimplemented
-#define _DISK_FORMAT   5       // Unimplemented
-
 
 #endif  // defined __STDLIB_H
\ No newline at end of file
index 4ccf5b1..f3cf79c 100644 (file)
 #include "freeldr.h"
 #include "stdlib.h"
 #include "tui.h"
+#include "memory.h"
+#include "debug.h"
+#include "parseini.h"
+
+ULONG  nScreenWidth = 80;              // Screen Width
+ULONG  nScreenHeight = 25;             // Screen Height
+
+CHAR   cStatusBarFgColor                       = COLOR_BLACK;                  // Status bar foreground color
+CHAR   cStatusBarBgColor                       = COLOR_CYAN;                   // Status bar background color
+CHAR   cBackdropFgColor                        = COLOR_WHITE;                  // Backdrop foreground color
+CHAR   cBackdropBgColor                        = COLOR_BLUE;                   // Backdrop background color
+CHAR   cBackdropFillStyle                      = MEDIUM_FILL;                  // Backdrop fill style
+CHAR   cTitleBoxFgColor                        = COLOR_WHITE;                  // Title box foreground color
+CHAR   cTitleBoxBgColor                        = COLOR_RED;                    // Title box background color
+CHAR   cMessageBoxFgColor                      = COLOR_WHITE;                  // Message box foreground color
+CHAR   cMessageBoxBgColor                      = COLOR_BLUE;                   // Message box background color
+CHAR   cMenuFgColor                            = COLOR_WHITE;                  // Menu foreground color
+CHAR   cMenuBgColor                            = COLOR_BLUE;                   // Menu background color
+CHAR   cTextColor                                      = COLOR_YELLOW;                 // Normal text color
+CHAR   cSelectedTextColor                      = COLOR_BLACK;                  // Selected text color
+CHAR   cSelectedTextBgColor            = COLOR_GRAY;                   // Selected text background color
+CHAR   szTitleBoxTitleText[260]        = "Boot Menu";                  // Title box's title text
+
+PUCHAR szMessageBoxLineText            = NULL;
+
+BOOL   UserInterfaceUp                         = FALSE;                                // Tells us if the user interface is displayed
+
+
+BOOL InitUserInterface(VOID)
+{
+       ULONG   SectionId;
+       UCHAR   SettingText[260];
+
+       DbgPrint((DPRINT_UI, "Initializing User Interface.\n"));
+       
+       szMessageBoxLineText = AllocateMemory(4096);
+       
+       if (szMessageBoxLineText == NULL)
+       {
+               return FALSE;
+       }
+
+       DbgPrint((DPRINT_UI, "Reading in UI settings from [Display] section.\n"));
+
+       if (OpenSection("Display", &SectionId))
+       {
+               if (ReadSectionSettingByName(SectionId, "TitleText", SettingText, 260))
+               {
+                       strcpy(szTitleBoxTitleText, SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "StatusBarColor", SettingText, 260))
+               {
+                       cStatusBarBgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "StatusBarTextColor", SettingText, 260))
+               {
+                       cStatusBarFgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "BackdropTextColor", SettingText, 260))
+               {
+                       cBackdropFgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "BackdropColor", SettingText, 260))
+               {
+                       cBackdropBgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "BackdropFillStyle", SettingText, 260))
+               {
+                       cBackdropFillStyle = TextToFillStyle(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "TitleBoxTextColor", SettingText, 260))
+               {
+                       cTitleBoxFgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "TitleBoxColor", SettingText, 260))
+               {
+                       cTitleBoxBgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "MessageBoxTextColor", SettingText, 260))
+               {
+                       cMessageBoxFgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "MessageBoxColor", SettingText, 260))
+               {
+                       cMessageBoxBgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "MenuTextColor", SettingText, 260))
+               {
+                       cMenuFgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "MenuColor", SettingText, 260))
+               {
+                       cMenuBgColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "TextColor", SettingText, 260))
+               {
+                       cTextColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "SelectedTextColor", SettingText, 260))
+               {
+                       cSelectedTextColor = TextToColor(SettingText);
+               }
+               if (ReadSectionSettingByName(SectionId, "SelectedColor", SettingText, 260))
+               {
+                       cSelectedTextBgColor = TextToColor(SettingText);
+               }
+       }
+
+       clrscr();
+       hidecursor();
+
+       // Draw the backdrop and title box
+       DrawBackdrop();
+       
+       UserInterfaceUp = TRUE;
 
-int            nScreenWidth = 80;              // Screen Width
-int            nScreenHeight = 25;             // Screen Height
-
-char   cStatusBarFgColor = COLOR_BLACK;                // Status bar foreground color
-char   cStatusBarBgColor = COLOR_CYAN;                 // Status bar background color
-char   cBackdropFgColor = COLOR_WHITE;                 // Backdrop foreground color
-char   cBackdropBgColor = COLOR_BLUE;                  // Backdrop background color
-char   cBackdropFillStyle = MEDIUM_FILL;               // Backdrop fill style
-char   cTitleBoxFgColor = COLOR_WHITE;                 // Title box foreground color
-char   cTitleBoxBgColor = COLOR_RED;                   // Title box background color
-char   cMessageBoxFgColor = COLOR_WHITE;               // Message box foreground color
-char   cMessageBoxBgColor = COLOR_BLUE;                // Message box background color
-char   cMenuFgColor = COLOR_WHITE;                             // Menu foreground color
-char   cMenuBgColor = COLOR_BLUE;                              // Menu background color
-char   cTextColor = COLOR_YELLOW;                              // Normal text color
-char   cSelectedTextColor = COLOR_BLACK;               // Selected text color
-char   cSelectedTextBgColor = COLOR_GRAY;              // Selected text background color
-char   szTitleBoxTitleText[260] = "Boot Menu"; // Title box's title text
-
-char   szMessageBoxLineText[4000] = "";
+       DbgPrint((DPRINT_UI, "InitUserInterface() returning TRUE.\n"));
+
+       return TRUE;
+}
 
 void DrawBackdrop(void)
 {
-       // Fill in the backdrop
-       FillArea(0, 0, nScreenWidth-1, nScreenHeight-1, cBackdropFillStyle, ATTR(cBackdropFgColor, cBackdropBgColor));
-
+       //
+       // Fill in the background (excluding title box & status bar)
+       //
+       FillArea(0,
+                       TITLE_BOX_HEIGHT,
+                       nScreenWidth - 1,
+                       nScreenHeight - 1,
+                       cBackdropFillStyle,
+                       ATTR(cBackdropFgColor, cBackdropBgColor));
+
+       //
        // Draw the title box
-       DrawBox(1, 1, nScreenWidth, 5, D_VERT, D_HORZ, TRUE, FALSE, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
-
-       // Draw version
-       DrawText(3, 2, VERSION, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+       //
+       DrawBox(1,
+                       1,
+                       nScreenWidth,
+                       5,
+                       D_VERT,
+                       D_HORZ,
+                       TRUE,
+                       FALSE,
+                       ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+
+       //
+       // Draw version text
+       //
+       DrawText(3,
+                       2,
+                       VERSION,
+                       ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+
+       //
        // Draw copyright
-       DrawText(3, 3, "by Brian Palmer", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
-       DrawText(3, 4, "<brianp@sginet.com>", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
-
+       //
+       DrawText(3,
+                       3,
+                       "by Brian Palmer",
+                       ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+       DrawText(3,
+                       4,
+                       "<brianp@sginet.com>",
+                       ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+
+       //
        // Draw help text
+       //
        //DrawText(nScreenWidth-15, 4, /*"F1 for Help"*/"F8 for Options", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
 
-       // Draw title
-       DrawText((nScreenWidth/2)-(strlen(szTitleBoxTitleText)/2), 3, szTitleBoxTitleText, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
-
-       // Draw date
-       DrawText(nScreenWidth-9, 2, "01/02/03", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
-       // Draw time
-       DrawText(nScreenWidth-9, 3, "10:12:34", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
+       //
+       // Draw title text
+       //
+       DrawText( (nScreenWidth / 2) - (strlen(szTitleBoxTitleText)/2),
+                       3,
+                       szTitleBoxTitleText,
+                       ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
 
+       //
        // Draw status bar
+       //
        DrawStatusText("");
 
+       //
        // Update the date & time
+       //
        UpdateDateTime();
 }
 
@@ -234,8 +370,8 @@ void DrawStatusText(char *text)
 
 void UpdateDateTime(void)
 {
-       char    date[260];
-       char    time[260];
+       char    date[40];
+       char    time[40];
        char    temp[20];
        int             hour, minute, second, bPM=FALSE;
 
@@ -353,10 +489,19 @@ void MessageBox(char *text)
        int             curline = 0;
        int             i , j, k;
        int             x1, x2, y1, y2;
-       char    savebuffer[8000];
+       PVOID   savebuffer;
        char    temp[260];
        char    key;
 
+       if (!UserInterfaceUp)
+       {
+               printf("%s", text);
+               printf("Press any key.\n");
+               getch();
+               return;
+       }
+
+       savebuffer = AllocateMemory(8000);
        SaveScreen(savebuffer);
        strcat(szMessageBoxLineText, text);
 
@@ -428,6 +573,7 @@ void MessageBox(char *text)
        }
 
        RestoreScreen(savebuffer);
+       FreeMemory(savebuffer);
        UpdateDateTime();
        strcpy(szMessageBoxLineText, "");
 }
index 8dc6cf0..072ac5c 100644 (file)
 #ifndef __TUI_H
 #define __TUI_H
 
-#define        SCREEN_MEM      0xB8000
-
-extern int             nScreenWidth;           // Screen Width
-extern int             nScreenHeight;          // Screen Height
-
-extern char    cStatusBarFgColor;                      // Status bar foreground color
-extern char    cStatusBarBgColor;                      // Status bar background color
-extern char    cBackdropFgColor;                       // Backdrop foreground color
-extern char    cBackdropBgColor;                       // Backdrop background color
-extern char    cBackdropFillStyle;                     // Backdrop fill style
-extern char    cTitleBoxFgColor;                       // Title box foreground color
-extern char    cTitleBoxBgColor;                       // Title box background color
-extern char    cMessageBoxFgColor;                     // Message box foreground color
-extern char    cMessageBoxBgColor;                     // Message box background color
-extern char    cMenuFgColor;                           // Menu foreground color
-extern char    cMenuBgColor;                           // Menu background color
-extern char    cTextColor;                                     // Normal text color
-extern char    cSelectedTextColor;                     // Selected text color
-extern char    cSelectedTextBgColor;           // Selected text background color
-extern char    szTitleBoxTitleText[260];       // Title box's title text
+#define        SCREEN_MEM                              0xB8000
+#define TITLE_BOX_HEIGHT               5
 
+// Initialize Textual-User-Interface
+BOOL   InitUserInterface(VOID);
 // Fills the entire screen with a backdrop
 void   DrawBackdrop(void);
 // Fills the area specified with cFillChar and cAttr
index 8dcc68e..489ee79 100644 (file)
@@ -4,8 +4,9 @@ To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit c
 FreeLoader does not currently work with extended partitions.
 Linux booting support needs to be added.
 ext2 filesystem support needs to be added.
+The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails.
 
-Current memory layout:
+Old memory layout:
 
 0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
 0000:1000 - 0000:6FFF: Real mode stack area
@@ -16,3 +17,27 @@ xxxx:xxxx - 6000:0000: Protected mode stack area & heap
 7000:0000 - 7000:FFFF: scratch area for any function's use (ie sector buffer for biosdisk()) - can be overwritten by any function
 8000:0000 - 9000:FFFF: fat table entry buffer
 A000:0000 - FFFF:FFFF: reserved
+
+
+New memory layout:
+
+0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
+0000:1000 - 0000:6FFF: Real mode stack area
+0000:7000 - 0000:7FFF: Unused
+0000:8000 - xxxx:xxxx: FreeLoader program & data area
+xxxx:xxxx - 8000:FFFF: Random memory allocation heap
+9000:0000 - 9000:7FFF: Disk read buffer for BIOS Int 13h
+9000:8000 - 9000:8FFF: Screen save buffer passed in from boot sector
+9000:9000 - 9000:FFFF: Protected mode stack area
+A000:0000 - FFFF:FFFF: reserved
+
+
+FreeLoader Boot Process
+
+Boot Sector
+
+       The BIOS loads the boot sector at 0000:7C00. The FAT32 boot sector relocates itself higher in memory at 9000:0000 and loads it's extra sector at 9000:0200 and then looks for freeldr.sys on the file system. Once found it loads freeldr.sys to 0000:7E00 and then jumps to it's entry point at 0000:8000. The FAT12/16 boot sector does no relocation, it just searches for the freeldr.sys and loads the first 512 bytes to 0000:7E00. This extra code enables it to fully navigate the file allocation table. Then it loads freeldr.sys to 0000:7E00 and jumps to it's entry point at 0000:8000. Before FreeLoader gets control the boot sector saves the screen contents to a buffer at 9000:8000 and the cursor x & y position to bytes at 9000:8FA0 & 9000:8FA1 respectively.
+
+FreeLoader Initialization
+
+       When FreeLoader gets control it saves the boot drive, passed to it in the DL register, and sets up the stack, enables protected mode, and calls BootMain().
\ No newline at end of file