Initial revision
authorBrian Palmer <brianp@sginet.com>
Tue, 15 May 2001 03:50:25 +0000 (03:50 +0000)
committerBrian Palmer <brianp@sginet.com>
Tue, 15 May 2001 03:50:25 +0000 (03:50 +0000)
svn path=/trunk/; revision=1904

40 files changed:
freeldr/COPYING [new file with mode: 0644]
freeldr/FREELDR.INI [new file with mode: 0644]
freeldr/bootsect/BOOTSECT.ASM [new file with mode: 0644]
freeldr/bootsect/BTSECT32.ASM [new file with mode: 0644]
freeldr/bootsect/MAKE.BAT [new file with mode: 0644]
freeldr/bootsect/bootsect.h [new file with mode: 0644]
freeldr/bootsect/btsect32.h [new file with mode: 0644]
freeldr/bootsect/c_data.c [new file with mode: 0644]
freeldr/bootsect/install.bat [new file with mode: 0644]
freeldr/bootsect/install.src [new file with mode: 0644]
freeldr/bootsect/win2k-12.asm [new file with mode: 0644]
freeldr/bootsect/win2k.asm [new file with mode: 0644]
freeldr/build.bat [new file with mode: 0644]
freeldr/freeldr/Makefile [new file with mode: 0644]
freeldr/freeldr/asmcode.S [new file with mode: 0644]
freeldr/freeldr/asmcode.h [new file with mode: 0644]
freeldr/freeldr/boot.S [new file with mode: 0644]
freeldr/freeldr/freeldr.c [new file with mode: 0644]
freeldr/freeldr/freeldr.h [new file with mode: 0644]
freeldr/freeldr/fs.c [new file with mode: 0644]
freeldr/freeldr/fs.h [new file with mode: 0644]
freeldr/freeldr/fs_fat.c [new file with mode: 0644]
freeldr/freeldr/linux.c [new file with mode: 0644]
freeldr/freeldr/linux.h [new file with mode: 0644]
freeldr/freeldr/menu.c [new file with mode: 0644]
freeldr/freeldr/menu.h [new file with mode: 0644]
freeldr/freeldr/miscboot.c [new file with mode: 0644]
freeldr/freeldr/miscboot.h [new file with mode: 0644]
freeldr/freeldr/options.c [new file with mode: 0644]
freeldr/freeldr/options.h [new file with mode: 0644]
freeldr/freeldr/pe.h [new file with mode: 0644]
freeldr/freeldr/ros.S [new file with mode: 0644]
freeldr/freeldr/rosboot.c [new file with mode: 0644]
freeldr/freeldr/rosboot.h [new file with mode: 0644]
freeldr/freeldr/stdlib.c [new file with mode: 0644]
freeldr/freeldr/stdlib.h [new file with mode: 0644]
freeldr/freeldr/tui.c [new file with mode: 0644]
freeldr/freeldr/tui.h [new file with mode: 0644]
freeldr/install.bat [new file with mode: 0644]
freeldr/notes.txt [new file with mode: 0644]

diff --git a/freeldr/COPYING b/freeldr/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/freeldr/FREELDR.INI b/freeldr/FREELDR.INI
new file mode 100644 (file)
index 0000000..2a48ce1
--- /dev/null
@@ -0,0 +1,130 @@
+# FreeLoader by Brian Palmer
+# FREELDR.INI - FreeLoader Initialization file
+#
+# Each line must be less than 1024 characters long
+# and must be either a section heading (i.e. [section_name])
+# or a setting (i.e. name=value) or a blank line.
+# Comments start with a '#' character.
+
+# Background colors can be any one of the following:
+# Black
+# Blue
+# Green
+# Cyan
+# Red
+# Magenta
+# Brown
+# Gray
+
+# Text colors can be any one of the background
+# colors and any of the following:
+# DarkGray
+# LightBlue
+# LightGreen
+# LightCyan
+# LightRed
+# LightMagenta
+# Yellow
+# White
+
+# [FREELOADER] Section Commands:
+#
+# MessageBox           - displays the specified text in a message box upon bootup
+# MessageLine          - adds a new line of text to a message box (must come before MessageBox command)
+# TitleText            - text that is displayed in the title box
+# StatusBarColor       - color of status bar's background
+# StatusBarTextColor   - color of status bar's text
+# BackdropTextColor    - color of the backdrop's fill
+# BackdropColor                - color of the backdrop's background
+# BackdropFillStyle    - backdrop fill style - can be Light, Medium, or Dark
+# TitleBoxTextColor    - title box text color
+# TitleBoxColor                - title box background color
+# MessageBoxTextColor  - message box text color
+# MessageBoxColor      - message box background color
+# MenuTextColor                - menu text color
+# MenuColor            - menu color
+# TextColor            - normal text color
+# SelectedTextColor    - selected text color
+# SelectedColor                - selected text background color
+# TimeOut              - sets the timeout (in seconds) before the first OS listed gets booted automagically
+
+# [OS-General] Section Commands:
+#
+# BootType             - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive
+# BootDrive            - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk
+# BootPartition                - sets the boot partition
+
+# [BootSector OSType] Section Commands:
+#
+# BootSector           - sets the filename of the bootsector to be loaded
+
+# [ReactOS OSType] Section Commands:
+#
+# Options              - sets the command line options for the kernel being booted
+# Kernel               - sets the kernel filename
+# Driver               - sets the name of one or more drivers to be loaded (one entry per driver)
+
+
+
+[FREELOADER]
+MessageLine=Welcome to FreeLoader!
+MessageLine=Copyright (c) 2000 by Brian Palmer <brianp@sginet.com>
+MessageLine=
+MessageBox=Edit your FREELDR.INI file to change your boot settings.
+TitleText=Boot Menu
+StatusBarColor=Cyan
+StatusBarTextColor=Black
+BackdropTextColor=White
+BackdropColor=Blue
+BackdropFillStyle=Medium
+TitleBoxTextColor=White
+TitleBoxColor=Red
+MessageBoxTextColor=White
+MessageBoxColor=Blue
+MenuTextColor=White
+MenuColor=Blue
+TextColor=Yellow
+SelectedTextColor=Black
+SelectedColor=Gray
+#OS=ReactOS
+#OS=ReactOS (Debug)
+#OS=Linux
+OS=3« Floppy (A:)
+OS=Microsoft Windows (C:)
+OS=Drive D:
+#TimeOut=0
+
+#[ReactOS]
+#BootType=ReactOS
+#BootDrive=0
+#Options=/DEBUGPORT=SCREEN
+#Kernel=\NTOSKRNL.EXE
+#Driver=\DRIVERS\IDE.SYS
+#Driver=\DRIVERS\VFATFS.SYS
+
+#[ReactOS (Debug)]
+#BootType=ReactOS
+#BootDrive=0
+#Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200
+#Kernel=\NTOSKRNL.EXE
+#Driver=\DRIVERS\IDE.SYS
+#Driver=\DRIVERS\VFATFS.SYS
+
+#[Linux]
+# Linux boot type not implemented yet
+#BootType=Partition
+#BootDrive=0x80
+#BootPartition=2
+
+[3« Floppy (A:)]
+BootType=Drive
+BootDrive=0
+
+[Microsoft Windows (C:)]
+BootType=Drive
+BootDrive=0x80
+
+[Drive D:]
+BootType=Partition
+BootDrive=0x81
+BootPartition=1
diff --git a/freeldr/bootsect/BOOTSECT.ASM b/freeldr/bootsect/BOOTSECT.ASM
new file mode 100644 (file)
index 0000000..2478e4f
--- /dev/null
@@ -0,0 +1,256 @@
+; BOOTSECT.ASM
+; FAT12/16 Boot Sector
+; Copyright (c) 1998 Brian Palmer
+
+org 7c00h
+
+segment .text
+
+bits 16
+
+start:
+        jmp short main
+        nop
+
+OEMName         db 'FreeLDR!'
+BytesPerSector  dw 512
+SectsPerCluster db 1
+ReservedSectors dw 1
+NumberOfFats    db 2
+MaxRootEntries  dw 512
+TotalSectors    dw 2880
+MediaDescriptor db 0f0h
+SectorsPerFat   dw 9
+SectorsPerTrack dw 18
+NumberOfHeads   dw 2
+HiddenSectors   dd 0
+TotalSectorsBig dd 0
+BootDrive       db 0
+Reserved        db 0
+ExtendSig       db 29h
+SerialNumber    dd 00000000h
+VolumeLabel     db 'FreeLoader!'
+FileSystem      db 'FAT12   '
+
+main:
+        cli
+        cld
+        xor ax,ax
+        mov ss,ax
+        mov sp,7c00h            ; Setup a stack
+        mov ax,cs               ; Setup segment registers
+        mov ds,ax               ; Make DS correct
+        mov es,ax               ; Make ES correct
+
+
+        sti                     ; Enable ints now
+        mov [BootDrive],dl      ; Save the boot drive
+        xor ax,ax               ; Zero out AX
+
+        ; Reset disk controller
+        int 13h         
+        jnc Continue1           
+        jmp BadBoot             ; Reset failed...
+
+Continue1:
+        ; Now we must find our way to the first sector of the root directory
+        xor ax,ax
+        xor cx,cx
+        mov al,[NumberOfFats]    ; Number of fats
+        mul WORD [SectorsPerFat] ; Times sectors per fat
+        add ax,WORD [HiddenSectors] 
+        adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors 
+        add ax,[ReservedSectors]     ; Add the number of reserved sectors
+        adc dx,cx               ; Add carry bit
+        push ax                 ; Store it on the stack
+        push dx                 ; Save 32-bit logical start sector
+        push ax
+        push dx                 ; Save it for later use also
+        ; DX:AX now has the number of the starting sector of the root directory
+
+        ; Now calculate the size of the root directory
+        mov ax,0020h            ; Size of dir entry
+        mul WORD [MaxRootEntries] ; Times the number of entries
+        mov bx,[BytesPerSector]
+        add ax,bx
+        dec ax
+        div bx                  ; Divided by the size of a sector
+        ; AX now has the number of root directory sectors
+
+        xchg ax,cx              ; Now CX has number of sectors
+        pop  dx
+        pop  ax                 ; Restore logical sector start
+        push cx                 ; Save for later use
+        mov  bx,7c0h            ; We will load the root directory 
+        add  bx,20h             ; Right after the boot sector in memory
+        mov  es,bx
+        xor  bx,bx              ; We will load it to [0000:7e00h]
+        call ReadSectors        ; Read the sectors
+        jnc  Continue2          ; BadBoot on error
+        jmp  BadBoot
+Continue2:
+
+
+        ; Now we have to find our way through the root directory to
+        ; The OSLOADER.SYS file
+        mov  bx,[MaxRootEntries]; Search entire root directory
+        mov  ax,7e0h            ; We loaded at 07e0:0000
+        mov  es,ax
+        xor  di,di
+        mov  si,filename
+        mov  cx,11
+        rep  cmpsb              ; Compare filenames
+        jz   FoundFile          ; If same we found it
+        dec  bx
+        jnz  FindFile
+        jmp  ErrBoot
+
+FindFile:
+        mov  ax,es              ; We didn't find it in the previous dir entry
+        add  ax,2               ; So lets move to the next one
+        mov  es,ax              ; And search again
+        xor  di,di
+        mov  si,filename        
+        mov  cx,11
+        rep  cmpsb              ; Compare filenames
+        jz   FoundFile          ; If same we found it
+        dec  bx                 ; Keep searching till we run out of dir entries
+        jnz  FindFile           ; Last entry?
+        jmp  ErrBoot
+
+FoundFile:
+        xor  di,di              ; ES:DI has dir entry
+        xor  dx,dx
+        mov  ax,WORD [es:di+1ah]        ; Get start cluster
+        dec  ax
+        dec  ax
+        xor  ch,ch
+        mov  cl,BYTE [SectsPerCluster] ; Times sectors per cluster
+        mul  cx
+        pop  cx                 ; Get number of sectors for root dir
+        add  ax,cx
+        adc  dx,0
+        pop  cx                 ; Get logical start sector of
+        pop  bx                 ; Root directory
+        add  ax,bx              ; Now we have DX:AX with the logical start
+        adc  dx,cx              ; Sector of OSLOADER.SYS
+        push ax
+        push dx
+        mov  ax,WORD [es:di+1ch]
+        mov  dx,WORD [es:di+1eh]
+        mov  bx,[BytesPerSector]
+        dec  bx
+        add  ax,bx
+        adc  dx,0
+        div  WORD [BytesPerSector]
+        xchg ax,cx              ; Now CX has number of sectors of OSLOADER.SYS
+        pop  dx
+        pop  ax
+        mov  bx,800h
+        mov  es,bx
+        xor  bx,bx              ; Load ROSLDR at 0000:8000h
+        call ReadSectors        ; Load it
+        jc   BadBoot
+        mov  dl,[BootDrive]
+        xor  ax,ax
+        push ax
+        mov  ax,8000h
+        push ax                 ; We will do a far return to 0000:8000h
+        retf                    ; Transfer control to ROSLDR
+
+
+
+; Reads logical sectors into [ES:BX]
+; DX:AX has logical sector number to read
+; CX has number of sectors to read
+; CarryFlag set on error
+ReadSectors:
+        push ax
+        push dx
+        push cx
+        xchg ax,cx
+        xchg ax,dx
+        xor  dx,dx
+        div  WORD [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,513
+        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
+        pop  cx
+        pop  dx
+        pop  ax
+        jc   ReadFail
+        inc  ax       ;Increment Sector to Read
+        jnz  NoCarry
+        inc  dx
+
+
+NoCarry:
+        push bx
+        mov  bx,es
+        add  bx,20h
+        mov  es,bx
+        pop  bx
+                                        ; Increment read buffer for next sector
+        loop ReadSectors                ; Read next sector
+
+
+ReadFail:
+        ret   
+
+
+
+; Displays a bad boot message
+; And reboots
+BadBoot:
+        mov  si,msgDiskError    ; Bad boot disk message
+        call PutChars           ; Display it
+        mov  si,msgAnyKey       ; Press any key message
+        call PutChars           ; Display it
+
+               jmp  Reboot
+
+; Displays an error message
+; And reboots
+ErrBoot:
+        mov  si,msgFreeLdr      ; 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
+
+PutChars:
+        lodsb
+        or al,al
+        jz short Done
+        mov ah,0eh
+        mov bx,07h
+        int 10h
+        jmp short 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'
+
+        times 510-($-$$) db 0   ; Pad to 510 bytes
+        dw 0aa55h       ; BootSector signature
+        
diff --git a/freeldr/bootsect/BTSECT32.ASM b/freeldr/bootsect/BTSECT32.ASM
new file mode 100644 (file)
index 0000000..092769e
--- /dev/null
@@ -0,0 +1,351 @@
+; BTSECT32.ASM
+; FAT32 Boot Sector
+; Copyright (c) 1998, 2000 Brian Palmer
+
+org 7c00h
+
+segment .text
+
+bits 16
+
+start:
+        jmp short main
+        nop
+
+OEMName                                db 'FreeLDR!'
+BytesPerSector         dw 512
+SectsPerCluster                db 1
+ReservedSectors                dw 1
+NumberOfFats           db 2
+MaxRootEntries         dw 0                    ;512 - Always zero for FAT32 volumes
+TotalSectors           dw 0                    ;2880 - Always zero for FAT32 volumes
+MediaDescriptor                db 0f8h
+SectorsPerFat          dw 0                    ;9 - Always zero for FAT32 volumes
+SectorsPerTrack                dw 18
+NumberOfHeads          dw 2
+HiddenSectors          dd 0
+TotalSectorsBig                dd 0
+; FAT32 Inserted Info
+SectorsPerFatBig       dd      0
+ExtendedFlags          dw      0
+FSVersion                      dw      0
+RootDirStartCluster    dd      0
+FSInfoSector           dw      0
+BackupBootSector       dw      6
+Reserved1                      times 12 db 0
+; End FAT32 Inserted Info
+BootDrive                      db 0
+Reserved                       db 0
+ExtendSig                      db 29h
+SerialNumber           dd 00000000h
+VolumeLabel                    db 'FreeLoader!'
+FileSystem                     db 'FAT32   '
+
+main:
+        cli
+        cld
+        xor ax,ax
+        mov ss,ax
+        mov sp,7c00h            ; Setup a stack
+        mov ax,cs               ; Setup segment registers
+        mov ds,ax               ; Make DS correct
+        mov es,ax               ; Make ES correct
+
+
+        sti                     ; Enable ints now
+        mov [BootDrive],dl      ; Save the boot drive
+        xor ax,ax               ; Zero out AX
+
+        ; Reset disk controller
+        int 13h         
+        jnc Continue
+        jmp BadBoot             ; Reset failed...
+
+Continue:
+               ; 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 
+               mov  cx,1
+        mov  bx,7e0h
+        mov  es,bx                             ; Read sector to [0000:7e00h]
+               xor  bx,bx
+               call ReadSectors
+               jnc  Continue1
+               jmp  BadBoot
+
+
+Continue1:
+        ; Now we must get the first cluster of the root directory
+               mov  eax,DWORD [RootDirStartCluster]
+               cmp  eax,0ffffff8h              ; Check to see if this is the last cluster in the chain
+               jb       Continue2                      ; If not continue, if so BadBoot
+               jmp  ErrBoot
+Continue2:
+        mov  bx,800h
+        mov  es,bx                             ; Read cluster to [0000:8000h]
+        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]
+               shl  bx,4                               ; BX = BX * 512 / 32
+        mov  ax,800h            ; We loaded at 0800:0000
+        mov  es,ax
+        xor  di,di
+        mov  si,filename
+        mov  cx,11
+        rep  cmpsb              ; Compare filenames
+        jz   FoundFile          ; If same we found it
+        dec  bx
+        jnz  FindFile
+        jmp  ErrBoot
+
+FindFile:
+        mov  ax,es              ; We didn't find it in the previous dir entry
+        add  ax,2               ; So lets move to the next one
+        mov  es,ax              ; And search again
+        xor  di,di
+        mov  si,filename        
+        mov  cx,11
+        rep  cmpsb              ; Compare filenames
+        jz   FoundFile          ; If same we found it
+        dec  bx                 ; Keep searching till we run out of dir entries
+        jnz  FindFile           ; Last entry?
+
+               ; Get the next root dir cluster and try again until we run out of clusters
+               mov  eax,DWORD [RootDirStartCluster]
+               call GetFatEntry
+               mov  [RootDirStartCluster],eax
+        jmp  Continue1
+
+FoundFile:
+        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
+        mov  es,bx
+
+FoundFile2:
+               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
+               push eax
+        xor  bx,bx              ; Load ROSLDR starting at 0000:8000h
+               push es
+               call ReadCluster
+               pop  es
+
+               xor  bx,bx
+        mov  bl,[SectsPerCluster]
+               shl  bx,5                               ; BX = BX * 512 / 16
+               mov  ax,es                              ; Increment the load address by
+               add  ax,bx                              ; The size of a cluster
+               mov  es,ax
+
+               pop  eax
+               push es
+               call GetFatEntry                ; Get the next entry
+               pop  es
+
+        jmp  FoundFile2                        ; 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
+        retf                    ; Transfer control to ROSLDR
+
+
+
+; Reads logical sectors into [ES:BX]
+; DX:AX has logical sector number to read
+; CX has number of sectors to read
+; CarryFlag set on error
+ReadSectors:
+        push ax
+        push dx
+        push cx
+        xchg ax,cx
+        xchg ax,dx
+        xor  dx,dx
+        div  WORD [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,513
+        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
+        pop  cx
+        pop  dx
+        pop  ax
+        jc   ReadFail
+        inc  ax       ;Increment Sector to Read
+        jnz  NoCarry
+        inc  dx
+
+
+NoCarry:
+        push bx
+        mov  bx,es
+        add  bx,20h
+        mov  es,bx
+        pop  bx
+                                        ; Increment read buffer for next sector
+        loop ReadSectors                ; Read next sector
+
+
+ReadFail:
+        ret
+
+
+
+
+; Displays a bad boot message
+; And reboots
+BadBoot:
+        mov  si,msgDiskError    ; Bad boot disk message
+        call PutChars           ; Display it
+        mov  si,msgAnyKey       ; Press any key message
+        call PutChars           ; Display it
+
+               jmp  Reboot
+
+; Displays an error message
+; And reboots
+ErrBoot:
+        mov  si,msgFreeLdr      ; 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
+
+PutChars:
+        lodsb
+        or al,al
+        jz short Done
+        mov ah,0eh
+        mov bx,07h
+        int 10h
+        jmp short 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'
+
+        times 510-($-$$) db 0   ; Pad to 510 bytes
+        dw 0aa55h       ; BootSector signature
+        
+
+; End of bootsector
+;
+; Now starts the extra boot code that we will store
+; at sector 14 on a FAT32 volume
+;
+; To remain multi-boot compatible with other operating
+; systems we must not overwrite anything other than
+; the bootsector which means we will have to use
+; a different sector like 14 to store our extra boot code
+;
+; Note: Win2k uses sector 12 for this purpose
+
+
+; Returns the FAT entry for a given cluster number
+; On entry EAX has cluster number
+; On return EAX has FAT entry for that cluster
+GetFatEntry:
+
+               shl   eax,2                                             ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
+               mov   ecx,eax                                   ; Save this for later in ECX
+               xor   edx,edx
+               movzx ebx,WORD [BytesPerSector]
+               push  ebx
+               div   ebx                                               ; FAT Sector Number = EAX / BytesPerSector
+               movzx ebx,WORD [ReservedSectors]
+               add   eax,ebx                                   ; FAT Sector Number += ReservedSectors
+               movzx ebx,WORD [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
+               push  ecx
+               ror   eax,16
+               mov   dx,ax
+               ror   eax,16
+               ; DX:AX holds logical FAT sector number
+        mov  bx,7000h
+        mov  es,bx
+        xor  bx,bx              ; We will load it to [7000:0000h]
+               mov  cx,1
+               call ReadSectors
+               jnc  GetFatEntry1
+               jmp  BadBoot
+GetFatEntry1:
+        mov  bx,7000h
+        mov  es,bx
+               pop  ecx
+               mov  eax,DWORD [es:ecx]         ; Get FAT entry
+               and  eax,0fffffffh                      ; Mask off reserved bits
+
+               ret
+
+
+; Reads cluster number in EAX into [ES:0000]
+ReadCluster:
+               ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
+
+               dec   eax
+               dec   eax
+               xor   edx,edx
+               movzx ebx,BYTE [SectsPerCluster]
+               mul   ebx
+               push  eax
+               xor   edx,edx
+               movzx eax,BYTE [NumberOfFats]
+               mul   DWORD [SectorsPerFatBig]
+               movzx ebx,WORD [ReservedSectors]
+               add   eax,ebx
+               add   eax,DWORD [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]
+               call  ReadSectors
+               jnc   ReadCluster1
+               jmp   BadBoot
+
+ReadCluster1:
+               ret
+
+        times 1022-($-$$) db 0   ; Pad to 1022 bytes
+        dw 0aa55h       ; BootSector signature
diff --git a/freeldr/bootsect/MAKE.BAT b/freeldr/bootsect/MAKE.BAT
new file mode 100644 (file)
index 0000000..35efa95
--- /dev/null
@@ -0,0 +1,2 @@
+nasm -o bootsect.bin -f bin bootsect.asm
+nasm -o btsect32.bin -f bin btsect32.asm
\ No newline at end of file
diff --git a/freeldr/bootsect/bootsect.h b/freeldr/bootsect/bootsect.h
new file mode 100644 (file)
index 0000000..ef020f3
--- /dev/null
@@ -0,0 +1,35 @@
+unsigned char data[] = {
+
+0xeb, 0x3c, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00, 
+0x02, 0x00, 0x02, 0x40, 0x0b, 0xf0, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c, 
+0x6f, 0x61, 0x64, 0x65, 0x72, 0x21, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc, 
+0x31, 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16, 
+0x24, 0x7c, 0x31, 0xc0, 0xcd, 0x13, 0x73, 0x03, 0xe9, 0x0b, 0x01, 0x31, 0xc0, 0x31, 0xc9, 0xa0, 
+0x10, 0x7c, 0xf7, 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13, 0x16, 0x1e, 0x7c, 0x03, 0x06, 
+0x0e, 0x7c, 0x11, 0xca, 0x50, 0x52, 0x50, 0x52, 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b, 
+0x1e, 0x0b, 0x7c, 0x01, 0xd8, 0x48, 0xf7, 0xf3, 0x91, 0x5a, 0x58, 0x51, 0xbb, 0xc0, 0x07, 0x81, 
+0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x8c, 0x00, 0x73, 0x03, 0xe9, 0xc7, 0x00, 0x8b, 
+0x1e, 0x11, 0x7c, 0xb8, 0xe0, 0x07, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00, 
+0xf3, 0xa6, 0x74, 0x1f, 0x4b, 0x75, 0x03, 0xe9, 0xbb, 0x00, 0x8c, 0xc0, 0x05, 0x02, 0x00, 0x8e, 
+0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x06, 0x4b, 0x75, 0xea, 
+0xe9, 0xa2, 0x00, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x1a, 0x48, 0x48, 0x30, 0xed, 0x8a, 
+0x0e, 0x0d, 0x7c, 0xf7, 0xe1, 0x59, 0x01, 0xc8, 0x81, 0xd2, 0x00, 0x00, 0x59, 0x5b, 0x01, 0xd8, 
+0x11, 0xca, 0x50, 0x52, 0x26, 0x8b, 0x45, 0x1c, 0x26, 0x8b, 0x55, 0x1e, 0x8b, 0x1e, 0x0b, 0x7c, 
+0x4b, 0x01, 0xd8, 0x81, 0xd2, 0x00, 0x00, 0xf7, 0x36, 0x0b, 0x7c, 0x91, 0x5a, 0x58, 0xbb, 0x00, 
+0x08, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x0e, 0x00, 0x72, 0x4c, 0x8a, 0x16, 0x24, 0x7c, 0x31, 0xc0, 
+0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91, 0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18, 
+0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7, 0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a, 
+0x16, 0x24, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08, 0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13, 
+0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53, 0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00, 
+0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0x96, 0x7d, 0xe8, 0x1b, 0x00, 0xbe, 0xbb, 0x7d, 0xe8, 
+0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xa3, 0x7d, 0xe8, 0x0c, 0x00, 0xbe, 0xbb, 0x7d, 0xe8, 0x06, 
+0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0, 0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 
+0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 
+0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e, 
+0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 
+0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 
+0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x20, 
+0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
\ No newline at end of file
diff --git a/freeldr/bootsect/btsect32.h b/freeldr/bootsect/btsect32.h
new file mode 100644 (file)
index 0000000..57dc647
--- /dev/null
@@ -0,0 +1,67 @@
+unsigned char data[] = {
+
+0xeb, 0x58, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00, 
+0x02, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x65, 
+0x72, 0x21, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xd0, 
+0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16, 0x40, 0x7c, 0x31, 0xc0, 
+0xcd, 0x13, 0x73, 0x03, 0xe9, 0x05, 0x01, 0x31, 0xd2, 0xb8, 0x0e, 0x00, 0x03, 0x06, 0x1c, 0x7c, 
+0x13, 0x16, 0x1e, 0x7c, 0xb9, 0x01, 0x00, 0xbb, 0xe0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0xab, 
+0x00, 0x73, 0x03, 0xe9, 0xe6, 0x00, 0x66, 0xa1, 0x2c, 0x7c, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f, 
+0x72, 0x03, 0xe9, 0xe6, 0x00, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0xe8, 0xb2, 0x01, 0x31, 0xdb, 0x8a, 
+0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x04, 0xb8, 0x00, 0x08, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d, 
+0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x2a, 0x4b, 0x75, 0x03, 0xe9, 0xbe, 0x00, 0x8c, 0xc0, 0x05, 
+0x02, 0x00, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x11, 
+0x4b, 0x75, 0xea, 0x66, 0xa1, 0x2c, 0x7c, 0xe8, 0x16, 0x01, 0x66, 0xa3, 0x2c, 0x7c, 0xe9, 0xa5, 
+0xff, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x14, 0x66, 0xc1, 0xe0, 0x10, 0x26, 0x8b, 0x45, 
+0x1a, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f, 0x73, 0x22, 0x66, 0x50, 
+0x31, 0xdb, 0x06, 0xe8, 0x49, 0x01, 0x07, 0x31, 0xdb, 0x8a, 0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x05, 
+0x8c, 0xc0, 0x01, 0xd8, 0x8e, 0xc0, 0x66, 0x58, 0x06, 0xe8, 0xd4, 0x00, 0x07, 0xe9, 0xd6, 0xff, 
+0x8a, 0x16, 0x40, 0x7c, 0x31, 0xc0, 0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91, 
+0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7, 
+0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a, 0x16, 0x40, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08, 
+0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53, 
+0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0xac, 0x7d, 0xe8, 
+0x1b, 0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xb9, 0x7d, 0xe8, 0x0c, 
+0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x06, 0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0, 
+0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b, 
+0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 
+0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 
+0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 
+0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52, 
+0x45, 0x45, 0x4c, 0x44, 0x52, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 
+0x66, 0xc1, 0xe0, 0x02, 0x66, 0x89, 0xc1, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb7, 0x1e, 0x0b, 0x7c, 
+0x66, 0x53, 0x66, 0xf7, 0xf3, 0x66, 0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x0f, 
+0xb7, 0x1e, 0x1c, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x5b, 0x66, 0x4b, 0x66, 0x21, 0xd9, 0x66, 0x51, 
+0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 
+0xdb, 0xb9, 0x01, 0x00, 0xe8, 0xf5, 0xfe, 0x73, 0x03, 0xe9, 0x30, 0xff, 0xbb, 0x00, 0x70, 0x8e, 
+0xc3, 0x66, 0x59, 0x26, 0x66, 0x67, 0x8b, 0x01, 0x66, 0x25, 0xff, 0xff, 0xff, 0x0f, 0xc3, 0x66, 
+0x48, 0x66, 0x48, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x1e, 0x0d, 0x7c, 0x66, 0xf7, 0xe3, 0x66, 
+0x50, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x06, 0x10, 0x7c, 0x66, 0xf7, 0x26, 0x24, 0x7c, 0x66, 
+0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x03, 0x06, 0x1c, 0x7c, 0x66, 0x5b, 0x66, 
+0x01, 0xd8, 0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0x31, 0xdb, 0x0f, 0xb6, 
+0x0e, 0x0d, 0x7c, 0xe8, 0x96, 0xfe, 0x73, 0x03, 0xe9, 0xd1, 0xfe, 0xc3, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
\ No newline at end of file
diff --git a/freeldr/bootsect/c_data.c b/freeldr/bootsect/c_data.c
new file mode 100644 (file)
index 0000000..963df42
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdio.h>
+
+char   in_filename[260];
+char   out_filename[260];
+FILE   *in;
+FILE   *out;
+
+int main(void)
+{
+       unsigned char   ch;
+       int                             cnt = 0;
+
+       printf("Enter data filename: ");
+       scanf("%s", in_filename);
+       printf("Enter output filename: ");
+       scanf("%s", out_filename);
+
+       if ((in = fopen(in_filename, "rb")) == NULL)
+       {
+               printf("Couldn't open data file.\n");
+               return 0;
+       }
+       if ((out = fopen(out_filename, "wb")) == NULL)
+       {
+               printf("Couldn't open output file.\n");
+               return 0;
+       }
+
+       fprintf(out, "unsigned char data[] = {\n");
+
+       ch = fgetc(in);
+       while (!feof(in))
+       {
+               if (cnt != 0)
+                       fprintf(out, ", ");
+               if (!(cnt % 16))
+                       fprintf(out, "\n");
+               fprintf(out, "0x%02x", (int)ch);
+               cnt++;
+               ch = fgetc(in);
+       }
+
+       fprintf(out, "\n};");
+
+       fclose(in);
+       fclose(out);
+
+       return 0;
+}
\ No newline at end of file
diff --git a/freeldr/bootsect/install.bat b/freeldr/bootsect/install.bat
new file mode 100644 (file)
index 0000000..32e2f3c
--- /dev/null
@@ -0,0 +1 @@
+debug bootsect.bin < install.src
diff --git a/freeldr/bootsect/install.src b/freeldr/bootsect/install.src
new file mode 100644 (file)
index 0000000..8667502
--- /dev/null
@@ -0,0 +1,2 @@
+w 100 0 0 1
+q
diff --git a/freeldr/bootsect/win2k-12.asm b/freeldr/bootsect/win2k-12.asm
new file mode 100644 (file)
index 0000000..d68a6fb
--- /dev/null
@@ -0,0 +1,197 @@
+00008000  660FB64610        movzx eax,byte [bp+NumberOfFats]
+00008005  668B4E24          mov ecx,[bp+SectorsPerFatBig]
+00008009  66F7E1            mul ecx
+0000800C  6603461C          add eax,[bp+HiddenSectors]
+00008010  660FB7560E        movzx edx,word [bp+ReservedSectors]
+00008015  6603C2            add eax,edx
+00008018  668946FC          mov [bp-0x4],eax
+0000801C  66C746F4FFFFFFFF  mov dword [bp-0xc],0xffffffff
+00008024  668B462C          mov eax,[bp+RootDirStartCluster]
+00008028  6683F802          cmp eax,byte +0x2
+0000802C  0F82A6FC          jc near 0x7cd6
+00008030  663DF8FFFF0F      cmp eax,0xffffff8
+00008036  0F839CFC          jnc near 0x7cd6
+0000803A  6650              push eax
+0000803C  6683E802          sub eax,byte +0x2
+00008040  660FB65E0D        movzx ebx,byte [bp+SectsPerCluster]
+00008045  8BF3              mov si,bx
+00008047  66F7E3            mul ebx
+0000804A  660346FC          add eax,[bp-0x4]
+0000804E  BB0082            mov bx,0x8200
+00008051  8BFB              mov di,bx
+00008053  B90100            mov cx,0x1
+00008056  E887FC            call 0x7ce0
+00008059  382D              cmp [di],ch
+0000805B  741E              jz 0x807b
+0000805D  B10B              mov cl,0xb
+0000805F  56                push si
+00008060  BE707D            mov si,0x7d70
+00008063  F3A6              repe cmpsb
+00008065  5E                pop si
+00008066  741B              jz 0x8083
+00008068  03F9              add di,cx
+0000806A  83C715            add di,byte +0x15
+0000806D  3BFB              cmp di,bx
+0000806F  72E8              jc 0x8059
+00008071  4E                dec si
+00008072  75DA              jnz 0x804e
+00008074  6658              pop eax
+00008076  E86500            call 0x80de
+00008079  72BF              jc 0x803a
+0000807B  83C404            add sp,byte +0x4
+0000807E  E955FC            jmp 0x7cd6
+00008081  0020              add [bx+si],ah
+00008083  83C404            add sp,byte +0x4
+00008086  8B7509            mov si,[di+0x9]
+00008089  8B7D0F            mov di,[di+0xf]
+0000808C  8BC6              mov ax,si
+0000808E  66C1E010          shl eax,0x10
+00008092  8BC7              mov ax,di
+00008094  6683F802          cmp eax,byte +0x2
+00008098  0F823AFC          jc near 0x7cd6
+0000809C  663DF8FFFF0F      cmp eax,0xffffff8
+000080A2  0F8330FC          jnc near 0x7cd6
+000080A6  6650              push eax
+000080A8  6683E802          sub eax,byte +0x2
+000080AC  660FB64E0D        movzx ecx,byte [bp+0xd]
+000080B1  66F7E1            mul ecx
+000080B4  660346FC          add eax,[bp-0x4]
+000080B8  BB0000            mov bx,0x0
+000080BB  06                push es
+000080BC  8E068180          mov es,[0x8081]
+000080C0  E81DFC            call 0x7ce0
+000080C3  07                pop es
+000080C4  6658              pop eax
+000080C6  C1EB04            shr bx,0x4
+000080C9  011E8180          add [0x8081],bx
+000080CD  E80E00            call 0x80de
+000080D0  0F830200          jnc near 0x80d6
+000080D4  72D0              jc 0x80a6
+000080D6  8A5640            mov dl,[bp+0x40]
+000080D9  EA00000020        jmp 0x2000:0x0
+000080DE  66C1E002          shl eax,0x2
+000080E2  E81100            call 0x80f6
+000080E5  26668B01          mov eax,[es:bx+di]
+000080E9  6625FFFFFF0F      and eax,0xfffffff
+000080EF  663DF8FFFF0F      cmp eax,0xffffff8
+000080F5  C3                ret
+000080F6  BF007E            mov di,0x7e00
+000080F9  660FB74E0B        movzx ecx,word [bp+0xb]
+000080FE  6633D2            xor edx,edx
+00008101  66F7F1            div ecx
+00008104  663B46F4          cmp eax,[bp-0xc]
+00008108  743A              jz 0x8144
+0000810A  668946F4          mov [bp-0xc],eax
+0000810E  6603461C          add eax,[bp+0x1c]
+00008112  660FB74E0E        movzx ecx,word [bp+0xe]
+00008117  6603C1            add eax,ecx
+0000811A  660FB75E28        movzx ebx,word [bp+0x28]
+0000811F  83E30F            and bx,byte +0xf
+00008122  7416              jz 0x813a
+00008124  3A5E10            cmp bl,[bp+0x10]
+00008127  0F83ABFB          jnc near 0x7cd6
+0000812B  52                push dx
+0000812C  668BC8            mov ecx,eax
+0000812F  668B4624          mov eax,[bp+0x24]
+00008133  66F7E3            mul ebx
+00008136  6603C1            add eax,ecx
+00008139  5A                pop dx
+0000813A  52                push dx
+0000813B  8BDF              mov bx,di
+0000813D  B90100            mov cx,0x1
+00008140  E89DFB            call 0x7ce0
+00008143  5A                pop dx
+00008144  8BDA              mov bx,dx
+00008146  C3                ret
+00008147  0000              add [bx+si],al
+00008149  0000              add [bx+si],al
+0000814B  0000              add [bx+si],al
+0000814D  0000              add [bx+si],al
+0000814F  0000              add [bx+si],al
+00008151  0000              add [bx+si],al
+00008153  0000              add [bx+si],al
+00008155  0000              add [bx+si],al
+00008157  0000              add [bx+si],al
+00008159  0000              add [bx+si],al
+0000815B  0000              add [bx+si],al
+0000815D  0000              add [bx+si],al
+0000815F  0000              add [bx+si],al
+00008161  0000              add [bx+si],al
+00008163  0000              add [bx+si],al
+00008165  0000              add [bx+si],al
+00008167  0000              add [bx+si],al
+00008169  0000              add [bx+si],al
+0000816B  0000              add [bx+si],al
+0000816D  0000              add [bx+si],al
+0000816F  0000              add [bx+si],al
+00008171  0000              add [bx+si],al
+00008173  0000              add [bx+si],al
+00008175  0000              add [bx+si],al
+00008177  0000              add [bx+si],al
+00008179  0000              add [bx+si],al
+0000817B  0000              add [bx+si],al
+0000817D  0000              add [bx+si],al
+0000817F  0000              add [bx+si],al
+00008181  0000              add [bx+si],al
+00008183  0000              add [bx+si],al
+00008185  0000              add [bx+si],al
+00008187  0000              add [bx+si],al
+00008189  0000              add [bx+si],al
+0000818B  0000              add [bx+si],al
+0000818D  0000              add [bx+si],al
+0000818F  0000              add [bx+si],al
+00008191  0000              add [bx+si],al
+00008193  0000              add [bx+si],al
+00008195  0000              add [bx+si],al
+00008197  0000              add [bx+si],al
+00008199  0000              add [bx+si],al
+0000819B  0000              add [bx+si],al
+0000819D  0000              add [bx+si],al
+0000819F  0000              add [bx+si],al
+000081A1  0000              add [bx+si],al
+000081A3  0000              add [bx+si],al
+000081A5  0000              add [bx+si],al
+000081A7  0000              add [bx+si],al
+000081A9  0000              add [bx+si],al
+000081AB  0000              add [bx+si],al
+000081AD  0000              add [bx+si],al
+000081AF  0000              add [bx+si],al
+000081B1  0000              add [bx+si],al
+000081B3  0000              add [bx+si],al
+000081B5  0000              add [bx+si],al
+000081B7  0000              add [bx+si],al
+000081B9  0000              add [bx+si],al
+000081BB  0000              add [bx+si],al
+000081BD  0000              add [bx+si],al
+000081BF  0000              add [bx+si],al
+000081C1  0000              add [bx+si],al
+000081C3  0000              add [bx+si],al
+000081C5  0000              add [bx+si],al
+000081C7  0000              add [bx+si],al
+000081C9  0000              add [bx+si],al
+000081CB  0000              add [bx+si],al
+000081CD  0000              add [bx+si],al
+000081CF  0000              add [bx+si],al
+000081D1  0000              add [bx+si],al
+000081D3  0000              add [bx+si],al
+000081D5  0000              add [bx+si],al
+000081D7  0000              add [bx+si],al
+000081D9  0000              add [bx+si],al
+000081DB  0000              add [bx+si],al
+000081DD  0000              add [bx+si],al
+000081DF  0000              add [bx+si],al
+000081E1  0000              add [bx+si],al
+000081E3  0000              add [bx+si],al
+000081E5  0000              add [bx+si],al
+000081E7  0000              add [bx+si],al
+000081E9  0000              add [bx+si],al
+000081EB  0000              add [bx+si],al
+000081ED  0000              add [bx+si],al
+000081EF  0000              add [bx+si],al
+000081F1  0000              add [bx+si],al
+000081F3  0000              add [bx+si],al
+000081F5  0000              add [bx+si],al
+000081F7  0000              add [bx+si],al
+000081F9  0000              add [bx+si],al
+000081FB  0000              add [bx+si],al
+000081FD  0055AA            add [di-0x56],dl
diff --git a/freeldr/bootsect/win2k.asm b/freeldr/bootsect/win2k.asm
new file mode 100644 (file)
index 0000000..466ad7e
--- /dev/null
@@ -0,0 +1,174 @@
+segment .text
+
+bits 16
+
+start:
+        jmp short main
+        nop
+
+OEMName                                db 'FreeLDR!'
+BytesPerSector         dw 512
+SectsPerCluster                db 1
+ReservedSectors                dw 1
+NumberOfFats           db 2
+MaxRootEntries         dw 0                    ;512 - Always zero for FAT32 volumes
+TotalSectors           dw 0                    ;2880 - Always zero for FAT32 volumes
+MediaDescriptor                db 0f8h
+SectorsPerFat          dw 0                    ;9 - Always zero for FAT32 volumes
+SectorsPerTrack                dw 18
+NumberOfHeads          dw 2
+HiddenSectors          dd 0
+TotalSectorsBig                dd 0
+; FAT32 Inserted Info
+SectorsPerFatBig       dd      0
+ExtendedFlags          dw      0
+FSVersion                      dw      0
+RootDirStartCluster    dd      0
+FSInfoSector           dw      0
+BackupBootSector       dw      6
+Reserved1                      times 12 db 0
+; End FAT32 Inserted Info
+BootDrive                      db 0
+Reserved                       db 0
+ExtendSig                      db 29h
+SerialNumber           dd 00000000h
+VolumeLabel                    db 'FreeLoader!'
+FileSystem                     db 'FAT12   '
+
+main:
+00007C5A  33C9              xor                cx,cx
+00007C5C  8ED1              mov                ss,cx
+00007C5E  BCF47B            mov                sp,0x7bf4
+00007C61  8EC1              mov                es,cx
+00007C63  8ED9              mov                ds,cx
+00007C65  BD007C            mov                bp,0x7c00
+00007C68  884E02            mov                [bp+0x2],cl
+00007C6B  8A5640            mov                dl,[bp+BootDrive]
+00007C6E  B408              mov                ah,0x8
+00007C70  CD13              int                0x13                    ; Int 13, func 8 - Get Drive Parameters
+00007C72  7305              jnc                0x7c79                  ; If no error jmp
+
+00007C74  B9FFFF            mov                cx,0xffff
+00007C77  8AF1              mov                dh,cl
+
+00007C79  660FB6C6          movzx      eax,dh
+00007C7D  40                inc                ax
+00007C7E  660FB6D1          movzx      edx,cl
+00007C82  80E23F            and                dl,0x3f
+00007C85  F7E2              mul                dx
+00007C87  86CD              xchg       cl,ch
+00007C89  C0ED06            shr                ch,0x6
+00007C8C  41                inc                cx
+00007C8D  660FB7C9          movzx      ecx,cx
+00007C91  66F7E1            mul                ecx
+00007C94  668946F8          mov                [bp-0x8],eax
+00007C98  837E1600          cmp                word [bp+TotalSectors],byte +0x0
+00007C9C  7538              jnz                print_ntldr_error_message
+
+00007C9E  837E2A00          cmp                word [bp+FSVersion],byte +0x0
+00007CA2  7732              ja         print_ntldr_error_message
+
+00007CA4  668B461C          mov                eax,[bp+0x1c]
+00007CA8  6683C00C          add                eax,byte +0xc
+00007CAC  BB0080            mov                bx,0x8000
+00007CAF  B90100            mov                cx,0x1
+00007CB2  E82B00            call       read_sectors
+00007CB5  E94803            jmp                0x8000
+
+print_disk_error_message:
+00007CB8  A0FA7D            mov                al,[DISK_ERR_offset_from_0x7d00]
+putchars:
+00007CBB  B47D              mov                ah,0x7d
+00007CBD  8BF0              mov                si,ax
+get_another_char:
+00007CBF  AC                lodsb
+00007CC0  84C0              test       al,al
+00007CC2  7417              jz         reboot
+00007CC4  3CFF              cmp                al,0xff
+00007CC6  7409              jz         print_reboot_message
+00007CC8  B40E              mov                ah,0xe
+00007CCA  BB0700            mov                bx,0x7
+00007CCD  CD10              int                0x10
+00007CCF  EBEE              jmp                short get_another_char
+print_reboot_message:
+00007CD1  A0FB7D            mov                al,[RESTART_ERR_offset_from_0x7d00]
+00007CD4  EBE5              jmp                short putchars
+print_ntldr_error_message:
+00007CD6  A0F97D            mov                al,[NTLDR_ERR_offset_from_0x7d00]
+00007CD9  EBE0              jmp                short putchars
+reboot:
+00007CDB  98                cbw
+00007CDC  CD16              int                0x16
+00007CDE  CD19              int                0x19
+
+read_sectors:
+00007CE0  6660              pushad
+00007CE2  663B46F8          cmp                eax,[bp-0x8]
+00007CE6  0F824A00          jc         near 0x7d34
+00007CEA  666A00            o32                push byte +0x0
+00007CED  6650              push       eax
+00007CEF  06                push       es
+00007CF0  53                push       bx
+00007CF1  666810000100      push       dword 0x10010
+00007CF7  807E0200          cmp                byte [bp+0x2],0x0
+00007CFB  0F852000          jnz                near 0x7d1f
+00007CFF  B441              mov                ah,0x41
+00007D01  BBAA55            mov                bx,0x55aa
+00007D04  8A5640            mov                dl,[bp+BootDrive]
+00007D07  CD13              int                0x13
+00007D09  0F821C00          jc         near 0x7d29
+00007D0D  81FB55AA          cmp                bx,0xaa55
+00007D11  0F851400          jnz                near 0x7d29
+00007D15  F6C101            test       cl,0x1
+00007D18  0F840D00          jz         near 0x7d29
+00007D1C  FE4602            inc                byte [bp+0x2]
+00007D1F  B442              mov                ah,0x42
+00007D21  8A5640            mov                dl,[bp+BootDrive]
+00007D24  8BF4              mov                si,sp
+00007D26  CD13              int                0x13
+00007D28  B0F9              mov                al,0xf9
+00007D2A  6658              pop                eax
+00007D2C  6658              pop                eax
+00007D2E  6658              pop                eax
+00007D30  6658              pop                eax
+00007D32  EB2A              jmp                short 0x7d5e
+00007D34  6633D2            xor                edx,edx
+00007D37  660FB74E18        movzx      ecx,word [bp+SectorsPerTrack]
+00007D3C  66F7F1            div                ecx
+00007D3F  FEC2              inc                dl
+00007D41  8ACA              mov                cl,dl
+00007D43  668BD0            mov                edx,eax
+00007D46  66C1EA10          shr                edx,0x10
+00007D4A  F7761A            div                word [bp+NumberOfHeads]
+00007D4D  86D6              xchg       dl,dh
+00007D4F  8A5640            mov                dl,[bp+BootDrive]
+00007D52  8AE8              mov                ch,al
+00007D54  C0E406            shl                ah,0x6
+00007D57  0ACC              or         cl,ah
+00007D59  B80102            mov                ax,0x201
+00007D5C  CD13              int                0x13
+00007D5E  6661              popad
+00007D60  0F8254FF          jc         near print_disk_error_message
+00007D64  81C30002          add                bx,0x200
+00007D68  6640              inc                eax
+00007D6A  49                dec                cx
+00007D6B  0F8571FF          jnz                near read_sectors
+00007D6F  C3                ret
+
+NTLDR          db 'NTLDR      '
+
+filler         times 49        db 0
+
+NTLDR_ERR      db 0dh,0ah,'NTLDR is missing',0ffh
+DISK_ERR       db 0dh,0ah,'Disk error',0ffh
+RESTART_ERR    db 0dh,0ah,'Press any key to restart',0dh,0ah
+
+more_filler    times 16        db 0
+
+NTLDR_offset_from_0x7d00                                               db 0
+NTLDR_ERR_offset_from_0x7d00                                   db 0ach
+DISK_ERR_offset_from_0x7d00                                            db 0bfh
+RESTART_ERR_offset_from_0x7d00                                 db 0cch
+
+                                               dw 0
+                                               dw 0aa55h
\ No newline at end of file
diff --git a/freeldr/build.bat b/freeldr/build.bat
new file mode 100644 (file)
index 0000000..d845e83
--- /dev/null
@@ -0,0 +1,7 @@
+cd bootsect
+call make.bat
+cd..
+cd freeldr
+make
+copy freeldr.sys ..
+cd ..
diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile
new file mode 100644 (file)
index 0000000..e281738
--- /dev/null
@@ -0,0 +1,89 @@
+#
+#  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.
+#
+       
+
+export CC = gcc
+export LD = ld
+export AR = ar
+export RM = cmd /C del
+export CP = cmd /C copy
+
+FLAGS = -Wall -nostdinc -fno-builtin
+
+# asmcode.o has to be first in the link line because it contains the startup code
+OBJS = asmcode.a asmcode.o ros.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
+       rosboot.o tui.o menu.o miscboot.o options.o linux.o
+ASM_OBJS = asmcode.o ros.o boot.o
+C_OBJS = freeldr.o stdlib.o fs.a rosboot.o tui.o menu.o miscboot.o options.o linux.o
+
+all:   freeldr.sys
+
+freeldr.sys:   asmcode.a c_code.a
+       $(LD) -N -Ttext=0x8000 --oformat=binary -o freeldr.sys asmcode.a c_code.a
+
+asmcode.a:     $(ASM_OBJS)
+       $(LD) -r -o asmcode.a $(ASM_OBJS)
+
+c_code.a:      $(C_OBJS)
+       $(LD) -r -o c_code.a $(C_OBJS)
+
+asmcode.o:     asmcode.S asmcode.h Makefile
+       $(CC) $(FLAGS) -o asmcode.o -c asmcode.S
+
+freeldr.o:     freeldr.c freeldr.h stdlib.h fs.h rosboot.h tui.h asmcode.h menu.h miscboot.h Makefile
+       $(CC) $(FLAGS) -o freeldr.o -c freeldr.c
+
+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.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
+
+rosboot.o:     rosboot.c freeldr.h rosboot.h stdlib.h fs.h tui.h Makefile
+       $(CC) $(FLAGS) -o rosboot.o -c rosboot.c
+
+ros.o: ros.S asmcode.h Makefile
+       $(CC) $(FLAGS) -o ros.o -c ros.S
+
+tui.o: tui.c freeldr.h stdlib.h tui.h Makefile
+       $(CC) $(FLAGS) -o tui.o -c tui.c
+
+menu.o:        menu.c freeldr.h stdlib.h tui.h menu.h Makefile
+       $(CC) $(FLAGS) -o menu.o -c menu.c
+
+boot.o:        boot.S asmcode.h Makefile
+       $(CC) $(FLAGS) -o boot.o -c boot.S
+
+miscboot.o:    miscboot.c freeldr.h asmcode.h stdlib.h fs.h tui.h miscboot.h Makefile
+       $(CC) $(FLAGS) -o miscboot.o -c miscboot.c
+
+options.o:     options.c freeldr.h stdlib.h tui.h options.h Makefile
+       $(CC) $(FLAGS) -o options.o -c options.c
+
+linux.o:       linux.c freeldr.h stdlib.h tui.h linux.h Makefile
+       $(CC) $(FLAGS) -o linux.o -c linux.c
+
+clean:
+       $(RM) $(OBJS)
diff --git a/freeldr/freeldr/asmcode.S b/freeldr/freeldr/asmcode.S
new file mode 100644 (file)
index 0000000..ae91d6e
--- /dev/null
@@ -0,0 +1,1177 @@
+/*
+ *  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.
+ */
+
+       .text
+       .code16
+
+#include "asmcode.h"
+
+
+EXTERN(start)
+
+       cli
+
+       /* Setup segment registers */
+       xorw    %ax,%ax
+       movw    %ax,%ds
+       movw    %ax,%es
+       movw    %ax,%fs
+       movw    %ax,%gs
+       movw    %ax,%ss
+       /* Setup a stack */
+       movw    stack16,%sp
+
+       sti
+
+       /* Init pmode */
+       call    switch_to_prot
+
+       .code32
+
+       /* Store the boot drive */
+       movb    %dl,(_BootDrive)
+
+       /* GO! */
+       call    _BootMain
+
+       call    switch_to_real
+       .code16
+
+       int             $0x19
+
+       /* We should never get here */
+stop:
+       jmp             stop
+
+
+/*
+ * Switches the processor to protected mode
+ * it destroys eax
+ */
+EXTERN(switch_to_prot)
+
+       .code16
+
+       cli             /* None of these */
+
+       /* Get the return address off the stack */
+       popw    (code32ret)
+
+       /* Save 16-bit stack pointer */
+       movw    %sp,stack16
+
+       /* Load the GDT */
+       lgdt    gdtptr
+
+       /* Enable Protected Mode */
+       mov             %cr0,%eax
+       orl             $CR0_PE_SET,%eax
+       mov             %eax,%cr0
+
+       /* Clear prefetch queue & correct CS */
+       ljmp    $PMODE_CS, $inpmode
+
+
+       .code32
+
+inpmode:
+       /* Setup segment selectors */
+       movw    $PMODE_DS,%ax
+       movw    %ax,%ds
+       movw    %ax,%es
+       movw    %ax,%fs
+       movw    %ax,%gs
+       movw    %ax,%ss
+       movl    stack32,%esp
+
+       /* Put the return address back onto the stack */
+       pushl   (code32ret)
+
+       /* Now return in p-mode! */
+       ret
+
+/*
+ * Switches the processor back to real mode
+ * it destroys eax
+ */
+EXTERN(switch_to_real)
+
+       .code32
+
+       /* Get the return address off the stack */
+       popl    (code16ret)
+
+       /* Save 32-bit stack pointer */
+       movl    %esp,stack32
+
+       /* jmp to 16-bit segment to set the limit correctly */
+       ljmp    $RMODE_CS, $switch_to_real16
+
+switch_to_real16:
+       .code16
+
+       /* Restore segment registers to correct limit */
+       movw    $RMODE_DS,%ax
+       movw    %ax,%ds
+       movw    %ax,%es
+       movw    %ax,%fs
+       movw    %ax,%gs
+       movw    %ax,%ss
+
+       /* Disable Protected Mode */
+       mov             %cr0,%eax
+       andl    $CR0_PE_CLR,%eax
+       mov             %eax,%cr0
+
+       /* Clear prefetch queue & correct CS */
+       ljmp    $0, $inrmode
+
+inrmode:
+       movw    %cs,%ax
+       movw    %ax,%ds
+       movw    %ax,%es
+       movw    %ax,%fs
+       movw    %ax,%gs
+       movw    %ax,%ss
+       movw    stack16,%sp
+
+       /* Put the return address back onto the stack */
+       pushw   (code16ret)
+
+       sti             /* These are ok now */
+
+       /* Now return in r-mode! */
+       ret
+
+
+/*
+ * void putchar(int ch);
+ */
+EXTERN(_putchar)
+       .code32
+
+       push    %eax
+       push    %ebx
+       push    %ebp
+
+       /* Get character to display */
+       movb    0x10(%esp),%bl
+
+       /* If we are displaying a CR '\n' then do a LF also */
+       cmpb    $0x0a,%bl
+       jnz             putchar_1
+
+       /* Display the LF */
+       pushl   $0x0d
+       call    _putchar
+       popl    %eax
+
+putchar_1:
+       /* If we are displaying a TAB '\t' then display 8 spaces ' ' */
+       cmpb    $0x09,%bl
+       jnz             putchar_2
+
+       /* Display the 8 spaces ' ' */
+       pushl   $0x20
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       call    _putchar
+       popl    %eax
+       pop             %ebp
+       pop             %ebx
+       pop             %eax
+       ret
+
+putchar_2:
+       call    switch_to_real
+
+       .code16
+
+       /* Display the character via BIOS int 0x10 function 0x0e */
+       movb    $0x0e,%ah
+       movb    %bl,%al
+       movw    $1,%bx
+       int             $0x10
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %ebp
+       pop             %ebx
+       pop             %eax
+       ret
+
+/*
+ * void clrscr(void);
+ */
+EXTERN(_clrscr)
+       .code32
+
+       push    %eax
+       push    %ebp
+
+       call    switch_to_real
+
+       .code16
+
+       /* Int 0x10, AH = 0x0F - Get Current Video Mode */
+       movb    $0x0f,%ah
+       int             $0x10
+
+       /* Int 0x10, AH = 0x00 - Set Current Video Mode, also clears the screen */
+       movb    $0x00,%ah
+       int             $0x10
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %ebp
+       pop             %eax
+       ret
+
+/*
+ * int kbhit(void);
+ */
+EXTERN(_kbhit)
+       .code32
+
+       push    %ebp
+       push    %ebx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Int 0x16, AH = 0x01 - Get Keyboard Status */
+       movb    $0x01,%ah
+       int             $0x16
+       jz              kbhit_1 // ZF=0 if no key is available
+
+       /* Return value is non-zero if a key is available */
+       movl    $1,%ebx
+       jmp             kbhit_done
+
+kbhit_1:
+       /* Return value is zero if no key is available */
+       movl    $0,%ebx
+
+kbhit_done:
+       
+       call    switch_to_prot
+
+       .code32
+
+       /* Get return value from ebx */
+       movl    %ebx,%eax
+
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int getch(void);
+ */
+extended_scancode:
+       .byte   0
+EXTERN(_getch)
+       .code32
+
+       push    %ebp
+       push    %ebx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Check and see if we have an extended scancode to return */
+       movb    extended_scancode,%al
+       movb    $0,extended_scancode
+       movzbl  %al,%ebx
+       cmpb    $0,%al
+       jnz             getch_done
+
+       /* Int 0x16, AH = 0x00 - Wait for keypress */
+       movb    $0,%ah
+       int             $0x16
+
+       /* If al is zero then it is an extended key */
+       cmp             $0,%al
+       jnz             getch_1
+
+       /* Save the scan code to be returned on the next call to getch() */
+       movb    %ah,extended_scancode
+
+getch_1:
+       /* Store character in ebx */
+       movzbl  %al,%ebx
+
+getch_done:
+       call    switch_to_prot
+
+       .code32
+
+       /* Get return value from ebx */
+       movl    %ebx,%eax
+
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * void gotoxy(int x, int y);
+ */
+EXTERN(_gotoxy)
+       .code32
+
+       push    %ebp
+       push    %eax
+       push    %ebx
+       push    %edx
+
+       /* Get cursor positions */
+       movb    0x14(%esp),%dl
+       movb    0x18(%esp),%dh
+
+       call    switch_to_real
+
+       .code16
+
+       /* Update the cursor position */
+       movb    $2,%ah
+       movb    $0,%bh
+       int             $0x10
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %edx
+       pop             %ebx
+       pop             %eax
+       pop             %ebp
+       ret
+
+/*
+ * int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer);
+ */
+_biosdisk_cmd:
+       .long   0
+_biosdisk_drive:
+       .long   0
+_biosdisk_head:
+       .long   0
+_biosdisk_track:
+       .long   0
+_biosdisk_sector:
+       .long   0
+_biosdisk_nsects:
+       .long   0
+_biosdisk_buffer:
+       .long   0
+_biosdisk_retval:
+       .long   0
+_biosdisk_retrycount:
+       .byte   0
+EXTERN(_biosdisk)
+       .code32
+
+       push    %ebp
+       push    %esi
+       push    %edi
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       /* Get parameters */
+       movl    0x1c(%esp),%eax
+       movl    %eax,_biosdisk_cmd
+       movl    0x20(%esp),%eax
+       movl    %eax,_biosdisk_drive
+       movl    0x24(%esp),%eax
+       movl    %eax,_biosdisk_head
+       movl    0x28(%esp),%eax
+       movl    %eax,_biosdisk_track
+       movl    0x2c(%esp),%eax
+       movl    %eax,_biosdisk_sector
+       movl    0x30(%esp),%eax
+       movl    %eax,_biosdisk_nsects
+       movl    0x34(%esp),%eax
+       movl    %eax,_biosdisk_buffer
+
+       call    switch_to_real
+
+       .code16
+       pushw   %es                                             // Save this just in case
+       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
+       movb    _biosdisk_sector,%cl    // Get the sector in CL
+    movw       _biosdisk_track,%ax             // Cylinder in AX
+       movb    %al,%ch                                 // Now put it in CH
+       rorb    $1,%ah                                  // Low 8 bits of cylinder in CH, high 2 bits
+       rorb    $1,%ah                                  //  in CL shifted to bits 6 & 7
+       andb    $0xc0,%ah                               // Clear out low six bits
+       orb             %ah,%cl                                 // Or with sector number
+       movb    _biosdisk_head,%dh              // Get the head
+       movb    _biosdisk_drive,%dl             // Get the drive
+       movb    $2,%ah                                  // BIOS int 0x13, function 2 - Read Disk Sectors
+       movb    _biosdisk_nsects,%al    // Number of sectors to read
+       int             $0x13                                   // Read a sector
+
+       // I have recently learned that not all bioses return
+       // the sector read count in the AL register (at least mine doesn't)
+       // even if the sectors were read correctly. So instead
+       // of checking the sector read count we will rely solely
+       // on the carry flag being set on error
+
+       //jmp           _biosdisk_done
+       //cmpb  _biosdisk_nsects,%al    // See how many sectors we actually read
+       //jne           _biosdisk_error                 // Jump if no error
+
+       movb    $1,%al                                  // Set the return value to be one (will be set to zero later if needed)
+       jc              _biosdisk_error                 // Jump if error (CF = 1 on error)
+       jmp             _biosdisk_done
+
+
+_biosdisk_error:
+       cmpb    $0x11,%ah                               // Check and see if it was a corrected ECC error
+       je              _biosdisk_done                  // If so then the data is still good, if not fail
+
+       movb    _biosdisk_retrycount,%al// Get the current retry count
+       decb    %al                                             // Decrement it
+       movb    %al,_biosdisk_retrycount// Save it
+       cmpb    $0,%al                                  // Is it zero?
+       jz              _biosdisk_zero                  // Yes, return zero
+
+       movb    $0,%ah                                  // BIOS int 0x13, function 0 - Reset Disk System
+       movb    _biosdisk_drive,%dl             // Get the drive
+       int             $0x13                                   // Reset the disk system
+       jmp             _biosdisk_read                  // Try reading again
+
+_biosdisk_zero:
+       movb    $0,%al                                  // We will return zero
+
+_biosdisk_done:
+       movzbl  %al,%eax                                // Put the number of sectors read into EAX
+       movl    %eax,_biosdisk_retval   // Save it as the return value
+
+       popw    %es                                             // Restore ES
+       call    switch_to_prot
+
+       .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
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %edi
+       pop             %esi
+       pop             %ebp
+       ret
+
+/*
+ * int getyear(void);
+ */
+EXTERN(_getyear)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the date */
+       movb    $4,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %ch,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %ch,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+       movb    %dl,%dh
+
+       movb    %cl,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %cl,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+
+       movb    %dl,%cl
+
+       movzbl  %dh,%eax
+       movl    $100,%ebx
+       mull    %ebx
+       movl    %eax,%edx
+       addb    %cl,%dl
+
+       /* Save return value */
+       movl    %edx,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int getday(void);
+ */
+EXTERN(_getday)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the date */
+       movb    $4,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %dl,%al
+       andb    $0x0f,%al
+       movb    %al,%cl
+       movb    %dl,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%cl
+
+       /* Save return value */
+       movzbl  %cl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int getmonth(void);
+ */
+EXTERN(_getmonth)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the date */
+       movb    $4,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %dh,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %dh,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+
+       /* Save return value */
+       movzbl  %dl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int gethour(void);
+ */
+EXTERN(_gethour)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the time */
+       movb    $2,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %ch,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %ch,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+
+       /* Save return value */
+       movzbl  %dl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int getminute(void);
+ */
+EXTERN(_getminute)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the time */
+       movb    $2,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %cl,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %cl,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+
+       /* Save return value */
+       movzbl  %dl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int getsecond(void);
+ */
+EXTERN(_getsecond)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the time */
+       movb    $2,%ah
+       int             $0x1a
+
+       /* Convert from BCD to normal */
+       movb    %dh,%al
+       andb    $0x0f,%al
+       movb    %al,%dl
+       movb    %dh,%al
+       shrb    $0x04,%al
+       andb    $0x0f,%al
+       movb    $0x0a,%bl
+       mulb    %bl
+       addb    %al,%dl
+
+       /* Save return value */
+       movzbl  %dl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * void hidecursor(void);
+ */
+EXTERN(_hidecursor)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Hide the cursor */
+       movb    $1,%ah
+       movw    $0x2000,%cx
+       int             $0x10
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * void showcursor(void);
+ */
+EXTERN(_showcursor)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Show the cursor */
+       movb    $1,%ah
+       movb    $0x0d,%ch
+       movb    $0x0e,%cl
+       int             $0x10
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int wherex(void);
+ */
+EXTERN(_wherex)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the cursor position */
+       movb    $3,%ah
+       movb    $0,%bh
+       int             $0x10
+
+       /* Save return value */
+       movzbl  %dl,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * int wherey(void);
+ */
+EXTERN(_wherey)
+       .code32
+
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       /* Get the cursor position */
+       movb    $3,%ah
+       movb    $0,%bh
+       int             $0x10
+
+       /* Save return value */
+       movzbl  %dh,%edx
+
+       call    switch_to_prot
+
+       .code32
+
+       /* Restore return value */
+       movl    %edx,%eax
+
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+       pop             %ebp
+       ret
+
+/*
+ * void stop_floppy(void);
+ *
+ * Stops the floppy drive from spinning, so that other software is
+ * jumped to with a known state.
+ */
+EXTERN(_stop_floppy)
+       .code32
+
+       push    %eax
+       push    %edx
+
+       call    switch_to_real
+
+       .code16
+
+       movw    $0x3F2, %dx
+       xorb    %al, %al
+       outb    %al, %dx
+
+       call    switch_to_prot
+
+       .code32
+
+       pop             %edx
+       pop             %eax
+       ret
+
+/*
+ * int get_heads(int drive);
+ */
+EXTERN(_get_heads)
+       .code32
+
+       push    %ebx
+       push    %ecx
+       push    %edx
+       push    %edi
+       push    %es
+
+       /* Get drive */
+       movl    0x18(%esp),%eax
+       movl    %eax,_biosdisk_drive
+
+       call    switch_to_real
+
+       .code16
+
+       movb    $0x08,%ah
+       movb    _biosdisk_drive,%dl
+       int             $0x13
+       jc              _get_heads_error
+
+       incb    %dh
+       movzbl  %dh,%edx
+       movl    %edx,_biosdisk_retval
+       jmp             _get_heads_done
+
+_get_heads_error:
+       movl    $0x0e,_biosdisk_retval
+
+_get_heads_done:
+
+       call    switch_to_prot
+
+       .code32
+
+       movl    _biosdisk_retval,%eax   // Get return value
+
+       pop             %es
+       pop             %edi
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+
+       ret
+
+/*
+ * int get_cylinders(int drive);
+ */
+EXTERN(_get_cylinders)
+       .code32
+
+       push    %ebx
+       push    %ecx
+       push    %edx
+       push    %edi
+       push    %es
+
+       /* Get drive */
+       movl    0x18(%esp),%eax
+       movl    %eax,_biosdisk_drive
+
+       call    switch_to_real
+
+       .code16
+
+       movb    $0x08,%ah
+       movb    _biosdisk_drive,%dl
+       int             $0x13
+       jc              _get_cylinders_error
+
+       xorl    %edx,%edx
+       andb    $0xc0,%cl
+       shrb    $0x06,%cl
+       movb    %cl,%dh
+       movb    %ch,%dl
+       incl    %edx
+       movl    %edx,_biosdisk_retval
+       jmp             _get_cylinders_done
+
+_get_cylinders_error:
+       movl    $0x00,_biosdisk_retval
+
+_get_cylinders_done:
+
+       call    switch_to_prot
+
+       .code32
+
+       movl    _biosdisk_retval,%eax   // Get return value
+
+       pop             %es
+       pop             %edi
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+
+       ret
+
+/*
+ * int get_sectors(int drive);
+ */
+EXTERN(_get_sectors)
+       .code32
+
+       push    %ebx
+       push    %ecx
+       push    %edx
+       push    %edi
+       push    %es
+
+       /* Get drive */
+       movl    0x18(%esp),%eax
+       movl    %eax,_biosdisk_drive
+
+       call    switch_to_real
+
+       .code16
+
+       movb    $0x08,%ah
+       movb    _biosdisk_drive,%dl
+       int             $0x13
+       jc              _get_sectors_error
+
+       andb    $0x3f,%cl
+       movzbl  %cl,%ecx
+       movl    %ecx,_biosdisk_retval
+       jmp             _get_sectors_done
+
+_get_sectors_error:
+       movl    $0x00,_biosdisk_retval
+
+_get_sectors_done:
+
+       call    switch_to_prot
+
+       .code32
+
+       movl    _biosdisk_retval,%eax   // Get return value
+
+       pop             %es
+       pop             %edi
+       pop             %edx
+       pop             %ecx
+       pop             %ebx
+
+       ret
+
+
+
+
+
+       /* 16-bit stack pointer */
+stack16:
+       .word   STACK16ADDR
+
+       /* 32-bit stack pointer */
+stack32:
+       .long   STACK32ADDR
+
+       /* 16-bit return address */
+code16ret:
+       .long   0
+
+       /* 32-bit return address */
+code32ret:
+       .long   0
+
+
+       .p2align        2       /* force 4-byte alignment */
+gdt:
+       /* NULL Descriptor */
+       .word   0x0000
+       .word   0x0000
+       .word   0x0000
+       .word   0x0000
+
+       /* 32-bit flat CS */
+       .word   0xFFFF
+       .word   0x0000
+       .word   0x9A00
+       .word   0x00CF
+
+       /* 32-bit flat DS */
+       .word   0xFFFF
+       .word   0x0000
+       .word   0x9200
+       .word   0x00CF
+
+       /* 16-bit real mode CS */
+       .word   0xFFFF
+       .word   0x0000
+       .word   0x9E00
+       .word   0x0000
+
+       /* 16-bit real mode DS */
+       .word   0xFFFF
+       .word   0x0000
+       .word   0x9200
+       .word   0x0000
+
+/* GDT table pointer */
+gdtptr:
+       .word   0x27            /* Limit */
+       .long   gdt                     /* Base Address */
+
+EXTERN(_BootDrive)
+       .long   0
diff --git a/freeldr/freeldr/asmcode.h b/freeldr/freeldr/asmcode.h
new file mode 100644 (file)
index 0000000..5ab2b72
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  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.
+ */
+       
+
+/* Defines needed for switching between real and protected mode */
+#define NULL_DESC      0x00    /* NULL descriptor */
+#define PMODE_CS       0x08    /* PMode code selector, base 0 limit 4g */
+#define PMODE_DS       0x10    /* PMode data selector, base 0 limit 4g */
+#define RMODE_CS       0x18    /* RMode code selector, base 0 limit 64k */
+#define RMODE_DS       0x20    /* RMode data selector, base 0 limit 64k */
+
+#define        KERNEL_BASE     0xC0000000
+//#define      USER_CS         0x08
+//#define      USER_DS         0x10
+//#define      KERNEL_CS       0x20
+//#define      KERNEL_DS       0x28
+#define        KERNEL_CS       0x08
+#define        KERNEL_DS       0x10
+
+#define CR0_PE_SET     0x00000001      /* OR this value with CR0 to enable pmode */
+#define CR0_PE_CLR     0xFFFFFFFE      /* AND this value with CR0 to disable pmode */
+
+#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 FILESYSADDR    0x80000 /* The filesystem data address will be at 8000:0000, or 0x80000 */
+
+#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 */
+
+/* Makes "x" a global variable or label */
+#define EXTERN(x)      .global x; x:
+
diff --git a/freeldr/freeldr/boot.S b/freeldr/freeldr/boot.S
new file mode 100644 (file)
index 0000000..c8f5124
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  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.
+ */
+
+       .text
+       .code16
+
+#include "asmcode.h"
+
+
+       .code32
+EXTERN(_JumpToBootCode)
+       call    switch_to_real
+       .code16
+
+       /* Set the boot drive */
+       movb    (_BootDrive),%dl
+
+       ljmpl   $0x0000,$0x7C00
+
+
+       .code32
+EXTERN(_JumpToLinuxBootCode)
+       call    switch_to_real
+       .code16
+
+       /* Set the boot drive */
+       movb    (_BootDrive),%dl
+
+       ljmpl   $0x0200,$0x9000
diff --git a/freeldr/freeldr/freeldr.c b/freeldr/freeldr/freeldr.c
new file mode 100644 (file)
index 0000000..b38d189
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ *  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 "stdlib.h"
+#include "fs.h"
+#include "rosboot.h"
+#include "tui.h"
+#include "asmcode.h"
+#include "menu.h"
+#include "miscboot.h"
+#include "linux.h"
+
+// Variable BootDrive moved to asmcode.S
+//unsigned int BootDrive = 0;          // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
+unsigned int   BootPartition = 0;      // Boot Partition, 1-4
+BOOL                   bTUILoaded = FALSE; // Tells us if the user interface is loaded
+
+char                   *pFreeldrIni = (char *)(FREELDRINIADDR); // Load address for freeldr.ini
+char                   *pScreenBuffer = (char *)(SCREENBUFFER); // Save address for screen contents
+int                            nCursorXPos = 0;        // Cursor's X Position
+int                            nCursorYPos = 0;        // Cursor's Y Position
+
+OSTYPE                 OSList[16];
+int                            nNumOS = 0;
+
+int                            nTimeOut = -1;          // Time to wait for the user before booting
+
+void BootMain(void)
+{
+       int             i;
+       char    name[1024];
+       char    value[1024];
+       int             nOSToBoot;
+
+       enable_a20();
+
+       SaveScreen(pScreenBuffer);
+       nCursorXPos = wherex();
+       nCursorYPos = wherey();
+
+       printf("Loading FreeLoader...\n");
+
+       if (!ParseIniFile())
+       {
+               printf("Press any key to reboot.\n");
+               getch();
+               return;
+       }
+
+       clrscr();
+       hidecursor();
+       // Draw the backdrop and title box
+       DrawBackdrop();
+       bTUILoaded = TRUE;
+
+       if (nNumOS == 0)
+       {
+               DrawStatusText(" Press ENTER to reboot");
+               MessageBox("Error: there were no operating systems listed to boot.\nPress ENTER to reboot.");
+               clrscr();
+               showcursor();
+               RestoreScreen(pScreenBuffer);
+               return;
+       }
+       
+
+       DrawStatusText(" Press ENTER to continue");
+       // Find all the message box settings and run them
+       for (i=1; i<=GetNumSectionItems("FREELOADER"); i++)
+       {
+               ReadSectionSettingByNumber("FREELOADER", i, name, value);
+               if (stricmp(name, "MessageBox") == 0)
+                       MessageBox(value);
+               if (stricmp(name, "MessageLine") == 0)
+                       MessageLine(value);
+       }
+
+       for (;;)
+       {
+               nOSToBoot = RunMenu();
+
+               LoadAndBootLinux(0x80, 0, "vmlinuz", "");
+               switch (OSList[nOSToBoot].nOSType)
+               {
+               case OSTYPE_REACTOS:
+                       LoadAndBootReactOS(nOSToBoot);
+                       break;
+               case OSTYPE_LINUX:
+                       MessageBox("Cannot boot this OS type yet!");
+                       break;
+               case OSTYPE_BOOTSECTOR:
+                       LoadAndBootBootSector(nOSToBoot);
+                       break;
+               case OSTYPE_PARTITION:
+                       LoadAndBootPartition(nOSToBoot);
+                       break;
+               case OSTYPE_DRIVE:
+                       LoadAndBootDrive(nOSToBoot);
+                       break;
+               }
+       }
+
+       MessageBox("Press any key to reboot.");
+       RestoreScreen(pScreenBuffer);
+       showcursor();
+       gotoxy(nCursorXPos, nCursorYPos);
+}
+
+BOOL ParseIniFile(void)
+{
+       int             i;
+       char    name[1024];
+       char    value[1024];
+       FILE    Freeldr_Ini;    // File handle for freeldr.ini
+
+       // Open the boot drive for file access
+       if(!OpenDiskDrive(BootDrive, 0))
+       {
+               printf("Error opening boot drive for file access.\n");
+               return FALSE;
+       }
+
+       // Try to open freeldr.ini or fail
+       if(!OpenFile("freeldr.ini", &Freeldr_Ini))
+       {
+               printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
+               return FALSE;
+       }
+
+       // Check and see if freeldr.ini is too big
+       // if so display a warning
+       if(GetFileSize(&Freeldr_Ini) > 0x4000)
+       {
+               printf("Warning: FREELDR.INI is bigger than 16k.\n");
+               printf("Only 16k of it will be loaded off the disk.\n");
+               printf("Press any key to continue.\n");
+               getch();
+       }
+
+       // Read freeldr.ini off the disk
+       ReadFile(&Freeldr_Ini, 0x4000, pFreeldrIni);
+
+       // Make sure the [FREELOADER] section exists
+       if(!GetNumSectionItems("FREELOADER"))
+       {
+               printf("Section [FREELOADER] not found in FREELDR.INI.\nYou need to re-install FreeLoader.\n");
+               return FALSE;
+       }
+
+       // Validate the settings in the [FREELOADER] section
+       for(i=1; i<=GetNumSectionItems("FREELOADER"); i++)
+       {
+               ReadSectionSettingByNumber("FREELOADER", i, name, value);
+               if(!IsValidSetting(name, value))
+               {
+                       printf("Invalid setting in freeldr.ini.\nName: \"%s\", Value: \"%s\"\n", name, value);
+                       printf("Press any key to continue.\n");
+                       getch();
+               }
+               else
+                       SetSetting(name, value);
+       }
+
+       return TRUE;
+}
+
+int GetNumSectionItems(char *section)
+{
+       int             i;
+       char    str[1024];
+       char    real_section[1024];
+       int             num_items = 0;
+       int             freeldr_ini_offset;
+       BOOL    bFoundSection = FALSE;
+
+       // Get the real section name
+       strcpy(real_section, "[");
+       strcat(real_section, section);
+       strcat(real_section, "]");
+
+       // Get to the beginning of the file
+       freeldr_ini_offset = 0;
+
+       // Find the section
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If it isn't a section header then continue on
+               if(str[0] != '[')
+                       continue;
+
+               // Check and see if we found it
+               if(stricmp(str, real_section) == 0)
+               {
+                       bFoundSection = TRUE;
+                       break;
+               }
+       }
+
+       // If we didn't find the section then we're outta here
+       if(!bFoundSection)
+               return 0;
+
+       // Now count how many settings are in this section
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If we hit a new section then we're done
+               if(str[0] == '[')
+                       break;
+
+               num_items++;
+       }
+
+       return num_items;
+}
+
+BOOL ReadSectionSettingByNumber(char *section, int num, char *name, char *value)
+{
+       char    str[1024];
+       char    real_section[1024];
+       int             num_items = 0;
+       int             i;
+       int             freeldr_ini_offset;
+       BOOL    bFoundSection = FALSE;
+
+       // Get the real section name
+       strcpy(real_section, "[");
+       strcat(real_section, section);
+       strcat(real_section, "]");
+
+       // Get to the beginning of the file
+       freeldr_ini_offset = 0;
+
+       // Find the section
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If it isn't a section header then continue on
+               if(str[0] != '[')
+                       continue;
+
+               // Check and see if we found it
+               if(stricmp(str, real_section) == 0)
+               {
+                       bFoundSection = TRUE;
+                       break;
+               }
+       }
+
+       // If we didn't find the section then we're outta here
+       if(!bFoundSection)
+               return FALSE;
+
+       // Now find the setting we are looking for
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If we hit a new section then we're done
+               if(str[0] == '[')
+                       break;
+
+               // Increment setting number
+               num_items++;
+
+               // Check and see if we found the setting
+               if(num_items == num)
+               {
+                       for(i=0; i<strlen(str); i++)
+                       {
+                               // Check and see if this character is the separator
+                               if(str[i] == '=')
+                               {
+                                       name[i] = '\0';
+
+                                       strcpy(value, str+i+1);
+
+                                       return TRUE;
+                               }
+                               else
+                                       name[i] = str[i];
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+BOOL ReadSectionSettingByName(char *section, char *valuename, char *name, char *value)
+{
+       char    str[1024];
+       char    real_section[1024];
+       char    temp[1024];
+       int             i;
+       int             freeldr_ini_offset;
+       BOOL    bFoundSection = FALSE;
+
+       // Get the real section name
+       strcpy(real_section, "[");
+       strcat(real_section, section);
+       strcat(real_section, "]");
+
+       // Get to the beginning of the file
+       freeldr_ini_offset = 0;
+
+       // Find the section
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If it isn't a section header then continue on
+               if(str[0] != '[')
+                       continue;
+
+               // Check and see if we found it
+               if(stricmp(str, real_section) == 0)
+               {
+                       bFoundSection = TRUE;
+                       break;
+               }
+       }
+
+       // If we didn't find the section then we're outta here
+       if(!bFoundSection)
+               return FALSE;
+
+       // Now find the setting we are looking for
+       while(freeldr_ini_offset < 0x4000)
+       {
+               // Read a line 
+               for(i=0; i<1024; i++,freeldr_ini_offset++)
+               {
+                       if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
+                               str[i] = pFreeldrIni[freeldr_ini_offset];
+                       else
+                       {
+                               freeldr_ini_offset++;
+                               break;
+                       }
+               }
+               str[i] = '\0';
+               //fgets(str, 1024, &Freeldr_Ini);
+
+               // Get rid of newline & linefeed characters (if any)
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+               if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
+                       str[strlen(str)-1] = '\0';
+
+               // Skip comments
+               if(str[0] == '#')
+                       continue;
+
+               // Skip blank lines
+               if(!strlen(str))
+                       continue;
+
+               // If we hit a new section then we're done
+               if(str[0] == '[')
+                       break;
+
+               // Extract the setting name
+               for(i=0; i<strlen(str); i++)
+               {
+                       if(str[i] != '=')
+                               temp[i] = str[i];
+                       else
+                       {
+                               temp[i] = '\0';
+                               break;
+                       }
+               }
+
+               // Check and see if we found the setting
+               if(stricmp(temp, valuename) == 0)
+               {
+                       for(i=0; i<strlen(str); i++)
+                       {
+                               // Check and see if this character is the separator
+                               if(str[i] == '=')
+                               {
+                                       name[i] = '\0';
+
+                                       strcpy(value, str+i+1);
+
+                                       return TRUE;
+                               }
+                               else
+                                       name[i] = str[i];
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+BOOL IsValidSetting(char *setting, char *value)
+{
+       if(stricmp(setting, "MessageBox") == 0)
+               return TRUE;
+       else if(stricmp(setting, "MessageLine") == 0)
+               return TRUE;
+       else if(stricmp(setting, "TitleText") == 0)
+               return TRUE;
+       else if(stricmp(setting, "StatusBarColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "StatusBarTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "BackdropTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "BackdropColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "BackdropFillStyle") == 0)
+       {
+               if(IsValidFillStyle(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "TitleBoxTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "TitleBoxColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "MessageBoxTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "MessageBoxColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "MenuTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "MenuColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "TextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "SelectedTextColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "SelectedColor") == 0)
+       {
+               if(IsValidColor(value))
+                       return TRUE;
+       }
+       else if(stricmp(setting, "OS") == 0)
+               return TRUE;
+       else if(stricmp(setting, "TimeOut") == 0)
+               return TRUE;
+       /*else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;
+       else if(stricmp(setting, "") == 0)
+               return TRUE;*/
+
+       return FALSE;
+}
+
+void SetSetting(char *setting, char *value)
+{
+       char    name[260];
+       char    v[260];
+
+       if(stricmp(setting, "TitleText") == 0)
+               strcpy(szTitleBoxTitleText, value);
+       else if(stricmp(setting, "StatusBarColor") == 0)
+               cStatusBarBgColor = TextToColor(value);
+       else if(stricmp(setting, "StatusBarTextColor") == 0)
+               cStatusBarFgColor = TextToColor(value);
+       else if(stricmp(setting, "BackdropTextColor") == 0)
+               cBackdropFgColor = TextToColor(value);
+       else if(stricmp(setting, "BackdropColor") == 0)
+               cBackdropBgColor = TextToColor(value);
+       else if(stricmp(setting, "BackdropFillStyle") == 0)
+               cBackdropFillStyle = TextToFillStyle(value);
+       else if(stricmp(setting, "TitleBoxTextColor") == 0)
+               cTitleBoxFgColor = TextToColor(value);
+       else if(stricmp(setting, "TitleBoxColor") == 0)
+               cTitleBoxBgColor = TextToColor(value);
+       else if(stricmp(setting, "MessageBoxTextColor") == 0)
+               cMessageBoxFgColor = TextToColor(value);
+       else if(stricmp(setting, "MessageBoxColor") == 0)
+               cMessageBoxBgColor = TextToColor(value);
+       else if(stricmp(setting, "MenuTextColor") == 0)
+               cMenuFgColor = TextToColor(value);
+       else if(stricmp(setting, "MenuColor") == 0)
+               cMenuBgColor = TextToColor(value);
+       else if(stricmp(setting, "TextColor") == 0)
+               cTextColor = TextToColor(value);
+       else if(stricmp(setting, "SelectedTextColor") == 0)
+               cSelectedTextColor = TextToColor(value);
+       else if(stricmp(setting, "SelectedColor") == 0)
+               cSelectedTextBgColor = TextToColor(value);
+       else if(stricmp(setting, "OS") == 0)
+       {
+               if(nNumOS >= 16)
+               {
+                       printf("Error: you can only boot to at most 16 different operating systems.\n");
+                       printf("Press any key to continue\n");
+                       getch();
+                       return;
+               }
+
+               if(!GetNumSectionItems(value))
+               {
+                       printf("Error: OS \"%s\" listed.\n", value);
+                       printf("It does not have it's own [section], or it is empty.\n");
+                       printf("Press any key to continue\n");
+                       getch();
+                       return;
+               }
+
+               strcpy(OSList[nNumOS].name, value);
+
+               if (!ReadSectionSettingByName(value, "BootType", name, v))
+               {
+                       printf("Unknown BootType for OS \"%s\"\n", value);
+                       printf("Press any key to continue\n");
+                       getch();
+                       return;
+               }
+
+               if (stricmp(v, "ReactOS") == 0)
+                       OSList[nNumOS].nOSType = OSTYPE_REACTOS;
+               else if (stricmp(v, "Linux") == 0)
+                       OSList[nNumOS].nOSType = OSTYPE_LINUX;
+               else if (stricmp(v, "BootSector") == 0)
+                       OSList[nNumOS].nOSType = OSTYPE_BOOTSECTOR;
+               else if (stricmp(v, "Partition") == 0)
+                       OSList[nNumOS].nOSType = OSTYPE_PARTITION;
+               else if (stricmp(v, "Drive") == 0)
+                       OSList[nNumOS].nOSType = OSTYPE_DRIVE;
+               else
+               {
+                       printf("Unknown BootType for OS \"%s\"\n", value);
+                       printf("Press any key to continue\n");
+                       getch();
+                       return;
+               }
+
+               nNumOS++;
+       }
+       else if(stricmp(setting, "TimeOut") == 0)
+               nTimeOut = atoi(value);
+}
diff --git a/freeldr/freeldr/freeldr.h b/freeldr/freeldr/freeldr.h
new file mode 100644 (file)
index 0000000..d8e3fd1
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  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.
+ */
+
+#ifndef __FREELDR_H
+#define __FREELDR_H
+
+
+/* just some stuff */
+#define VERSION                "FreeLoader v0.8"
+#define COPYRIGHT      "Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>"
+
+#define ROSLDR_MAJOR_VERSION   0
+#define ROSLDR_MINOR_VERSION   8
+#define ROSLDR_PATCH_VERSION   0
+
+#define        size_t  unsigned int
+#define BOOL   int
+#define        NULL    0
+#define        TRUE    1
+#define FALSE  0
+#define BYTE   unsigned char
+#define WORD   unsigned short
+#define DWORD  unsigned long
+#define CHAR   char
+#define WCHAR  unsigned short
+#define LONG   long
+#define ULONG  unsigned long
+#define PULONG unsigned long *
+#define PDWORD DWORD *
+#define PWORD  WORD *
+
+#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;
+
+extern unsigned int    BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
+extern unsigned int    BootPartition;  // Boot Partition, 1-4
+extern BOOL                    bTUILoaded; // Tells us if the user interface is loaded
+
+extern char                    *pFreeldrIni; // Load address for freeldr.ini
+extern char                    *pScreenBuffer; // Save address for screen contents
+extern int                     nCursorXPos;    // Cursor's X Position
+extern int                     nCursorYPos;    // 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
+
+void   BootMain(void);
+BOOL   ParseIniFile(void);
+int            GetNumSectionItems(char *section); // returns the number of items in a particular section (i.e. [FREELOADER])
+BOOL   ReadSectionSettingByNumber(char *section, int num, char *name, char *value); // Reads the num'th value from section
+BOOL   ReadSectionSettingByName(char *section, char *valuename, char *name, char *value); // Reads the value named name from section
+BOOL   IsValidSetting(char *setting, char *value);
+void   SetSetting(char *setting, char *value);
+
+#endif  // defined __FREELDR_H
\ No newline at end of file
diff --git a/freeldr/freeldr/fs.c b/freeldr/freeldr/fs.c
new file mode 100644 (file)
index 0000000..03419dd
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ *  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"
+
+#define        FS_DO_ERROR(s)  \
+       { \
+               if (bTUILoaded) \
+                       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
+
+int            FSType = NULL;                  // 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
+
+BOOL OpenDiskDrive(int nDrive, int nPartition)
+{
+       int             num_bootable_partitions = 0;
+       int             boot_partition = 0;
+       int             partition_type = 0;
+       int             head, sector, cylinder;
+       int             offset;
+
+       // Check and see if it is a floppy drive
+       if (nDrive < 0x80)
+       {
+               // 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;
+               }
+       }
+       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);
+
+               partition_type = SectorBuffer[offset + 4];
+
+               // Check for valid partition
+               if (partition_type == 0)
+               {
+                       FS_DO_ERROR("Invalid boot partition");
+                       return FALSE;
+               }
+
+               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;
+
+               // Read partition boot sector
+               if (!biosdisk(_DISK_READ, nDrive, head, cylinder, sector, 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;
+               }
+       }
+
+
+       // 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; 
+
+       nRootDirSectorStart = (nNumberOfFATs * nSectorsPerFAT) + nReservedSectors;
+       nRootDirSectors = ((nRootDirEntries * 32) + (nBytesPerSector - 1)) / nBytesPerSector;
+       nDataSectorStart = nReservedSectors + (nNumberOfFATs * nSectorsPerFAT) + nRootDirSectors;
+       nNumberOfClusters = (nTotalSectors - nDataSectorStart) / nSectorsPerCluster;
+
+       // Determine FAT type
+       if (nNumberOfClusters < 4085)
+       {
+               /* Volume is FAT12 */
+               nFATType = FAT12;
+       }
+       else if (nNumberOfClusters < 65525)
+       {
+               /* Volume is FAT16 */
+               nFATType = FAT16;
+       }
+       else
+       {
+               /* Volume is FAT32 */
+               nFATType = FAT32;
+
+               // Check version
+               // we only work with version 0
+               if (*((WORD*)(SectorBuffer + BPB_FILESYSTEMVERSION32)) != 0)
+               {
+                       FS_DO_ERROR("Error: FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
+                       return FALSE;
+               }
+       }
+
+       FSType = FS_FAT;
+
+       // 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))
+       {
+               if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData))
+                       return FALSE;
+       }
+       else if ((FSType == FS_FAT) && (nFATType == FAT32))
+       {
+               // 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;
+       }
+
+       return TRUE;
+}
+
+BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
+{
+       BOOL    bRetVal;
+       int             PhysicalSector;
+       int             PhysicalHead;
+       int             PhysicalTrack;
+       int             nNum;
+
+       nSect += nHiddenSectors;
+
+       while (nNumberOfSectors)
+       {
+               PhysicalSector = 1 + (nSect % nSectorsPerTrack);
+               PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
+               PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
+
+               if (PhysicalSector > 1)
+               {
+                       if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1)))
+                               nNum = (nSectorsPerTrack - (PhysicalSector - 1));
+                       else
+                               nNum = nNumberOfSectors;
+               }
+               else
+               {
+                       if (nNumberOfSectors >= nSectorsPerTrack)
+                               nNum = nSectorsPerTrack;
+                       else
+                               nNum = nNumberOfSectors;
+               }
+
+               bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
+
+               if (!bRetVal)
+               {
+                       FS_DO_ERROR("Disk Error");
+                       return FALSE;
+               }
+
+               pBuffer += (nNum * 512);
+               nNumberOfSectors -= nNum;
+               nSect += nNum;
+       }
+
+       return TRUE;
+}
+
+BOOL ReadOneSector(int nSect)
+{
+       BOOL    bRetVal;
+       int             PhysicalSector;
+       int             PhysicalHead;
+       int             PhysicalTrack;
+
+       nSectorBuffered = nSect;
+
+       nSect += nHiddenSectors;
+       PhysicalSector = 1 + (nSect % nSectorsPerTrack);
+       PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
+       PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
+
+
+       bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, 1, SectorBuffer);
+
+       if (!bRetVal)
+       {
+               FS_DO_ERROR("Disk Error");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+BOOL OpenFile(char *filename, FILE *pFile)
+{
+       switch(FSType)
+       {
+       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;
+       }
+
+       return TRUE;
+}
+
+/*
+ * ReadFile()
+ * returns number of bytes read or EOF
+ */
+int ReadFile(FILE *pFile, int count, void *buffer)
+{
+       switch(FSType)
+       {
+       case FS_FAT:
+               return FATRead(&(pFile->fat), count, buffer);
+       default:
+               FS_DO_ERROR("Error: Unknown filesystem.");
+               return EOF;
+       }
+
+       return 0;
+}
+
+DWORD GetFileSize(FILE *pFile)
+{
+       return pFile->filesize;
+}
+
+DWORD Rewind(FILE *pFile)
+{
+       switch (FSType)
+       {
+       case FS_FAT:
+               pFile->fat.dwCurrentCluster = pFile->fat.dwStartCluster;
+               pFile->fat.dwCurrentReadOffset = 0;
+               break;
+       default:
+               FS_DO_ERROR("Error: Unknown filesystem.");
+               break;
+       }
+
+       return pFile->filesize;
+}
+
+int feof(FILE *pFile)
+{
+       switch (FSType)
+       {
+       case FS_FAT:
+               if (pFile->fat.dwCurrentReadOffset >= pFile->fat.dwSize)
+                       return TRUE;
+               else
+                       return FALSE;
+               break;
+       default:
+               FS_DO_ERROR("Error: Unknown filesystem.");
+               return TRUE;
+               break;
+       }
+
+       return TRUE;
+}
+
+int fseek(FILE *pFile, DWORD offset)
+{
+       switch (FSType)
+       {
+       case FS_FAT:
+               return FATfseek(&(pFile->fat), offset);
+               break;
+       default:
+               FS_DO_ERROR("Error: Unknown filesystem.");
+               break;
+       }
+
+       return -1;
+}
diff --git a/freeldr/freeldr/fs.h b/freeldr/freeldr/fs.h
new file mode 100644 (file)
index 0000000..e80dadb
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  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.
+ */
+
+#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
+
+/*
+ * Structure of MSDOS directory entry
+ */
+typedef struct //_DIRENTRY
+{
+       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
+{
+       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
+{
+       //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);
+
+
+#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        FS_FAT                  1
+#define        FS_NTFS                 2
+#define        FS_EXT2                 3
+
+#define        FAT12                   1
+#define        FAT16                   2
+#define        FAT32                   3
+
+#endif // #defined __FS_FAT_H
\ No newline at end of file
diff --git a/freeldr/freeldr/fs_fat.c b/freeldr/freeldr/fs_fat.c
new file mode 100644 (file)
index 0000000..828d1dc
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ *  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;
+}
diff --git a/freeldr/freeldr/linux.c b/freeldr/freeldr/linux.c
new file mode 100644 (file)
index 0000000..0033897
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  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 "asmcode.h"
+#include "miscboot.h"
+#include "stdlib.h"
+#include "fs.h"
+#include "tui.h"
+#include "linux.h"
+
+void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line)
+{
+       FILE    file;
+       char    temp[260];
+       char    bootsector[512];
+       char    setup[2048];
+       int             len;
+
+       BootDrive = DriveNum;
+       BootPartition = Partition;
+
+       if (!OpenDiskDrive(BootDrive, BootPartition))
+       {
+               MessageBox("Failed to open boot drive.");
+               return;
+       }
+
+       if (!OpenFile(vmlinuz, &file))
+       {
+               strcpy(temp, vmlinuz);
+               strcat(temp, " not found.");
+               MessageBox(temp);
+               return;
+       }
+
+       // Read boot sector
+       if (ReadFile(&file, 512, bootsector) != 512)
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+       MessageBox("bootsector loaded");
+
+       // Read setup code
+       if (ReadFile(&file, 2048, setup) != 2048)
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+       MessageBox("setup loaded");
+
+       // Read kernel code
+       len = GetFileSize(&file) - (2048 + 512);
+       //len = 0x200;
+       if (ReadFile(&file, len, (void*)0x100000) != len)
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+       MessageBox("kernel loaded");
+
+       // Check for validity
+       if (*((WORD*)(bootsector + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid boot sector magic (0xaa55)");
+               return;
+       }
+       if (*((DWORD*)(setup + 2)) != 0x53726448)
+       {
+               MessageBox("Invalid setup magic (\"HdrS\")");
+               return;
+       }
+
+       memcpy((void*)0x90000, bootsector, 512);
+       memcpy((void*)0x90200, setup, 2048);
+
+       RestoreScreen(pScreenBuffer);
+       showcursor();
+       gotoxy(nCursorXPos, nCursorYPos);
+
+       stop_floppy();
+       JumpToLinuxBootCode();
+}
diff --git a/freeldr/freeldr/linux.h b/freeldr/freeldr/linux.h
new file mode 100644 (file)
index 0000000..3f6eb03
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+#ifndef __LINUX_H
+#define __LINUX_H
+
+void   JumpToLinuxBootCode(void);      // Implemented in boot.S
+
+void   LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line);
+
+#endif // defined __LINUX_H
\ No newline at end of file
diff --git a/freeldr/freeldr/menu.c b/freeldr/freeldr/menu.c
new file mode 100644 (file)
index 0000000..90846db
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  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 "stdlib.h"
+#include "tui.h"
+#include "menu.h"
+#include "options.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)
+{
+       int             key;
+       int             second;
+       BOOL    bDone = FALSE;
+
+       if (nTimeOut > 0)
+               nTimeOut++; // Increment the timeout since 0 doesn't count for a second
+
+       // Initialise the menu
+       InitMenu();
+
+       // Update the menu
+       DrawMenu();
+
+       second = getsecond();
+
+       // Loop
+       do
+       {
+               // Check for a keypress
+               if (kbhit())
+               {
+                       // Cancel the timeout
+                       if (nTimeOut != -1)
+                       {
+                               nTimeOut = -1;
+                               DrawMenu();
+                       }
+
+                       // Get the key
+                       key = getch();
+
+                       // Is it extended?
+                       if (key == 0)
+                               key = getch(); // Yes - so get the extended key
+
+                       // 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;
+                       }
+               }
+
+               // Update the date & time
+               UpdateDateTime();
+
+               if (nTimeOut > 0)
+               {
+                       if (getsecond() != second)
+                       {
+                               second = getsecond();
+                               nTimeOut--;
+
+                               // Update the menu
+                               DrawMenu();
+                       }
+               }
+
+               if (nTimeOut == 0)
+                       bDone = TRUE;
+       }
+       while (!bDone);
+
+       return nOSSelected;
+}
+
+void InitMenu(void)
+{
+       int             i;
+       int             height = 1; // Allow room for top & bottom borders
+       int             width = 0;
+
+       for(i=0; i<nNumOS; i++)
+       {
+               height++;
+               if(strlen(OSList[i].name) > width)
+                       width = strlen(OSList[i].name);
+       }
+       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;
+}
+
+void DrawMenu(void)
+{
+       int             i, j;
+       char    text[260];
+       char    temp[260];
+       int             space, space_left, space_right;
+
+       // Update the status bar
+       DrawStatusText(" Use \x18\x19 to select, ENTER to boot. Press F8 for advanced options.");
+
+       DrawBox(nOSListBoxLeft, nOSListBoxTop, nOSListBoxRight, nOSListBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
+
+       for(i=0; i<nNumOS; i++)
+       {
+               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)
+               {
+                       DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
+               }
+               else
+               {
+                       DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
+               }
+       }
+
+       if (nTimeOut >= 0)
+       {
+               strcpy(text, "[ Time Remaining: ");
+               itoa(nTimeOut, temp, 10);
+               strcat(text, temp);
+               strcat(text, " ]");
+
+               DrawText(nOSListBoxRight - strlen(text) - 1, nOSListBoxBottom, text, ATTR(cMenuFgColor, cMenuBgColor));
+       }
+}
\ No newline at end of file
diff --git a/freeldr/freeldr/menu.h b/freeldr/freeldr/menu.h
new file mode 100644 (file)
index 0000000..ebf085f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+#ifndef __MENU_H
+#define __MENU_H
+
+int            RunMenu(void);
+void   InitMenu(void);
+void   DrawMenu(void);
+
+#endif // #defined __MENU_H
\ No newline at end of file
diff --git a/freeldr/freeldr/miscboot.c b/freeldr/freeldr/miscboot.c
new file mode 100644 (file)
index 0000000..8b6026a
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  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 "asmcode.h"
+#include "miscboot.h"
+#include "stdlib.h"
+#include "fs.h"
+#include "tui.h"
+
+void LoadAndBootBootSector(int nOSToBoot)
+{
+       FILE    file;
+       char    name[260];
+       char    value[260];
+       char    szFileName[1024];
+       int             i;
+
+       // Find all the message box settings and run them
+       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       {
+               ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
+               if (stricmp(name, "MessageBox") == 0)
+                       MessageBox(value);
+               if (stricmp(name, "MessageLine") == 0)
+                       MessageLine(value);
+       }
+
+       if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
+       {
+               MessageBox("Boot drive not specified for selected OS!");
+               return;
+       }
+
+       BootDrive = atoi(value);
+
+       BootPartition = 0;
+       if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
+               BootPartition = atoi(value);
+
+       if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootSector", name, value))
+       {
+               MessageBox("Boot sector file not specified for selected OS!");
+               return;
+       }
+
+       if (!OpenDiskDrive(BootDrive, BootPartition))
+       {
+               MessageBox("Failed to open boot drive.");
+               return;
+       }
+
+       strcpy(szFileName, value);
+       if (!OpenFile(szFileName, &file))
+       {
+               strcat(value, " not found.");
+               MessageBox(value);
+               return;
+       }
+
+       // Read boot sector
+       if (ReadFile(&file, 512, (void*)0x7c00) != 512)
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+
+       // Check for validity
+       if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid boot sector magic (0xaa55)");
+               return;
+       }
+
+       RestoreScreen(pScreenBuffer);
+       showcursor();
+       gotoxy(nCursorXPos, nCursorYPos);
+
+       stop_floppy();
+       JumpToBootCode();
+}
+
+void LoadAndBootPartition(int nOSToBoot)
+{
+       char    name[260];
+       char    value[260];
+       int             head, sector, cylinder;
+       int             offset;
+       int             i;
+
+       // Find all the message box settings and run them
+       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       {
+               ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
+               if (stricmp(name, "MessageBox") == 0)
+                       MessageBox(value);
+               if (stricmp(name, "MessageLine") == 0)
+                       MessageLine(value);
+       }
+
+       if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
+       {
+               MessageBox("Boot drive not specified for selected OS!");
+               return;
+       }
+
+       BootDrive = atoi(value);
+
+       if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
+       {
+               MessageBox("Boot partition not specified for selected OS!");
+               return;
+       }
+
+       BootPartition = atoi(value);
+
+       if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+
+       // Check for validity
+       if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid partition table magic (0xaa55)");
+               return;
+       }
+
+       offset = 0x1BE + ((BootPartition-1) * 0x10);
+
+       // Check for valid partition
+       if (SectorBuffer[offset + 4] == 0)
+       {
+               MessageBox("Invalid boot partition");
+               return;
+       }
+
+       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;
+
+       // Read partition boot sector
+       if (!biosdisk(_DISK_READ, BootDrive, head, cylinder, sector, 1, (void*)0x7c00))
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+
+       // Check for validity
+       if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid boot sector magic (0xaa55)");
+               return;
+       }
+
+       RestoreScreen(pScreenBuffer);
+       showcursor();
+       gotoxy(nCursorXPos, nCursorYPos);
+
+       stop_floppy();
+       JumpToBootCode();
+}
+
+void LoadAndBootDrive(int nOSToBoot)
+{
+       char    name[260];
+       char    value[260];
+       int             i;
+
+       // Find all the message box settings and run them
+       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       {
+               ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
+               if (stricmp(name, "MessageBox") == 0)
+                       MessageBox(value);
+               if (stricmp(name, "MessageLine") == 0)
+                       MessageLine(value);
+       }
+
+       if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
+       {
+               MessageBox("Boot drive not specified for selected OS!");
+               return;
+       }
+
+       BootDrive = atoi(value);
+
+       if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, (void*)0x7c00))
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+
+       // Check for validity
+       if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid boot sector magic (0xaa55)");
+               return;
+       }
+
+       RestoreScreen(pScreenBuffer);
+       showcursor();
+       gotoxy(nCursorXPos, nCursorYPos);
+
+       stop_floppy();
+       JumpToBootCode();
+}
diff --git a/freeldr/freeldr/miscboot.h b/freeldr/freeldr/miscboot.h
new file mode 100644 (file)
index 0000000..d6b6ef2
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ */
+
+#ifndef __BOOT_H
+#define __BOOT_H
+
+void   JumpToBootCode(void);   // Implemented in boot.S
+
+void   LoadAndBootBootSector(int nOSToBoot);
+void   LoadAndBootPartition(int nOSToBoot);
+void   LoadAndBootDrive(int nOSToBoot);
+
+#endif // defined __BOOT_H
\ No newline at end of file
diff --git a/freeldr/freeldr/options.c b/freeldr/freeldr/options.c
new file mode 100644 (file)
index 0000000..8550e24
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ *  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 "stdlib.h"
+#include "tui.h"
+#include "options.h"
+#include "miscboot.h"
+
+
+void DoOptionsMenu(void)
+{
+       int             OptionsMenuItemCount = 1; // Count is 1 because we don't show the "Set ReactOS Boot Flags" menu item yet
+       char    OptionsMenuItems[2][80] = {     "Boot Wizard", "Set ReactOS Boot Flags" /* i.e. Safe Mode, Last Known Good Configuration */     };
+       int             OptionsMenuItemSelected = 0;
+
+       while (OptionsMenuItemSelected != -1)
+       {
+               OptionsMenuItemSelected = RunOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, OptionsMenuItemSelected, "[Advanced Options]");
+
+               switch (OptionsMenuItemSelected)
+               {
+               case 0:
+                       DoDiskOptionsMenu();
+                       break;
+               }
+       }
+}
+
+void DoDiskOptionsMenu(void)
+{
+       char    DiskMenuItems[25][80];
+       int             DiskMenuItemCount = 0;
+       int             FloppyDiskMenuItemCount = 0;
+       int             HardDiskMenuItemCount = 0;
+       int             DiskMenuItemSelected = 0;
+
+       char    temp[255];
+       int             i;
+
+       FloppyDiskMenuItemCount = (int)*((char *)((0x40 * 16) + 0x10)); // Get number of floppy disks from bios data area 40:10
+       if (FloppyDiskMenuItemCount & 1)
+               FloppyDiskMenuItemCount = (FloppyDiskMenuItemCount >> 6) + 1;
+       else
+               FloppyDiskMenuItemCount = 0;
+       HardDiskMenuItemCount = (int)*((char *)((0x40 * 16) + 0x75)); // Get number of hard disks from bios data area 40:75
+       DiskMenuItemCount = FloppyDiskMenuItemCount + HardDiskMenuItemCount;
+
+       for (i=0; i<FloppyDiskMenuItemCount; i++)
+       {
+               strcpy(DiskMenuItems[i], "Floppy Disk ");
+               itoa(i + 1, temp, 10);
+               strcat(DiskMenuItems[i], temp);
+       }
+
+       for (i=0; i<HardDiskMenuItemCount; i++)
+       {
+               strcpy(DiskMenuItems[i + FloppyDiskMenuItemCount], "Hard Disk ");
+               itoa(i + 1, temp, 10);
+               strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], temp);
+               strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], " (");
+               itoa((get_heads(i+0x80) * get_cylinders(i+0x80) * get_sectors(i+0x80)) / 2048, temp, 10);
+               strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], temp);
+               strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], " MB)");
+       }
+
+       DiskMenuItemSelected = 0;
+       while (DiskMenuItemSelected != -1)
+       {
+               DiskMenuItemSelected = RunOptionsMenu(DiskMenuItems, DiskMenuItemCount, DiskMenuItemSelected, "[Boot Wizard]");
+
+               if (DiskMenuItemSelected != -1)
+               {
+                       if (DiskMenuItemSelected < FloppyDiskMenuItemCount)
+                               DoBootOptionsMenu(DiskMenuItemSelected, DiskMenuItems[DiskMenuItemSelected]);
+                       else
+                               DoBootOptionsMenu((DiskMenuItemSelected - FloppyDiskMenuItemCount) + 0x80, DiskMenuItems[DiskMenuItemSelected]);
+               }
+       }
+}
+
+void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
+{
+       int             BootOptionsMenuItemCount = 2;
+       char    BootOptionsMenuItems[2][80] = { "Boot To ", "Pick A Boot Partition"     };
+       int             BootOptionsMenuItemSelected = 0;
+
+       strcat(BootOptionsMenuItems[0], BootDriveText);
+
+       while (BootOptionsMenuItemSelected != -1)
+       {
+               BootOptionsMenuItemSelected = RunOptionsMenu(BootOptionsMenuItems, BootOptionsMenuItemCount, BootOptionsMenuItemSelected, "[Boot Options]");
+
+               switch (BootOptionsMenuItemSelected)
+               {
+               case 0:
+                       BootDrive = BootDriveNum;
+
+                       if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, (void*)0x7c00))
+                       {
+                               MessageBox("Disk Read Error");
+                               return;
+                       }
+
+                       // Check for validity
+                       if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
+                       {
+                               MessageBox("Invalid boot sector magic (0xaa55)");
+                               return;
+                       }
+
+                       RestoreScreen(pScreenBuffer);
+                       showcursor();
+                       gotoxy(nCursorXPos, nCursorYPos);
+
+                       stop_floppy();
+                       JumpToBootCode();
+
+                       break;
+               case 1:
+                       if (BootDriveNum < 0x80)
+                       {
+                               MessageBox("This option is not available for a floppy disk.");
+                               continue;
+                       }
+                       else
+                               DoBootPartitionOptionsMenu(BootDriveNum);
+
+                       break;
+               }
+       }
+}
+
+void DoBootPartitionOptionsMenu(int BootDriveNum)
+{
+       struct
+       {
+               int             partition_num;
+               int             partition_type;
+               int             head, sector, cylinder;
+       } BootPartitions[8];
+       int             BootOptionsMenuItemCount = 0;
+       char    BootOptionsMenuItems[8][80];
+       int             BootOptionsMenuItemSelected = 0;
+       int             head, sector, cylinder;
+       int             offset;
+       int             i;
+       char    temp[25];
+
+
+       BootDrive = BootDriveNum;
+
+       if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
+       {
+               MessageBox("Disk Read Error");
+               return;
+       }
+
+       // Check for validity
+       if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
+       {
+               MessageBox("Invalid partition table magic (0xaa55)");
+               return;
+       }
+
+       offset = 0x1BE;
+
+       for (i=0; i<4; i++)
+       {
+               // Check for valid partition
+               if (SectorBuffer[offset + 4] != 0)
+               {
+                       BootPartitions[BootOptionsMenuItemCount].partition_num = i;
+                       BootPartitions[BootOptionsMenuItemCount].partition_type = SectorBuffer[offset + 4];
+
+                       BootPartitions[BootOptionsMenuItemCount].head = SectorBuffer[offset + 1];
+                       BootPartitions[BootOptionsMenuItemCount].sector = (SectorBuffer[offset + 2] & 0x3F);
+                       BootPartitions[BootOptionsMenuItemCount].cylinder = SectorBuffer[offset + 3];
+                       if (SectorBuffer[offset + 2] & 0x80)
+                               BootPartitions[BootOptionsMenuItemCount].cylinder += 0x200;
+                       if (SectorBuffer[offset + 2] & 0x40)
+                               BootPartitions[BootOptionsMenuItemCount].cylinder += 0x100;
+
+                       strcpy(BootOptionsMenuItems[BootOptionsMenuItemCount], "Boot To Partition ");
+                       itoa(i+1, temp, 10);
+                       strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], temp);
+                       strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], " (Type: 0x");
+                       itoa(BootPartitions[BootOptionsMenuItemCount].partition_type, temp, 16);
+                       if (strlen(temp) < 2)
+                               strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], "0");
+                       strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], temp);
+                       strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], ")");
+
+                       BootOptionsMenuItemCount++;
+               }
+
+               offset += 0x10;
+       }
+
+       while (BootOptionsMenuItemSelected != -1)
+       {
+               BootOptionsMenuItemSelected = RunOptionsMenu(BootOptionsMenuItems, BootOptionsMenuItemCount, BootOptionsMenuItemSelected, "[Boot Partition Options]");
+
+               if (BootOptionsMenuItemSelected != -1)
+               {
+                       head = BootPartitions[BootOptionsMenuItemCount].head;
+                       sector = BootPartitions[BootOptionsMenuItemCount].sector;
+                       cylinder = BootPartitions[BootOptionsMenuItemCount].cylinder;
+
+                       // Read partition boot sector
+                       if (!biosdisk(_DISK_READ, BootDrive, head, cylinder, sector, 1, (void*)0x7c00))
+                       {
+                               MessageBox("Disk Read Error");
+                               return;
+                       }
+
+                       // Check for validity
+                       if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
+                       {
+                               MessageBox("Invalid boot sector magic (0xaa55)");
+                               return;
+                       }
+
+                       RestoreScreen(pScreenBuffer);
+                       showcursor();
+                       gotoxy(nCursorXPos, nCursorYPos);
+
+                       stop_floppy();
+                       JumpToBootCode();
+               }
+       }
+}
+
+int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle)
+{
+       int             key;
+       int             second;
+       BOOL    bDone = FALSE;
+       int             nOptionsMenuBoxLeft;
+       int             nOptionsMenuBoxRight;
+       int             nOptionsMenuBoxTop;
+       int             nOptionsMenuBoxBottom;
+
+
+       // Initialise the menu
+       InitOptionsMenu(&nOptionsMenuBoxLeft, &nOptionsMenuBoxTop, &nOptionsMenuBoxRight, &nOptionsMenuBoxBottom, OptionsMenuItemCount);
+
+       DrawBackdrop();
+
+       // Update the menu
+       DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
+
+       second = getsecond();
+
+       // Loop
+       do
+       {
+               // Check for a keypress
+               if (kbhit())
+               {
+                       // Cancel the timeout
+                       if (nTimeOut != -1)
+                       {
+                               nTimeOut = -1;
+                               DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
+                       }
+
+                       // Get the key
+                       key = getch();
+
+                       // Is it extended?
+                       if (key == 0)
+                               key = getch(); // Yes - so get the extended key
+
+                       // Process the key
+                       switch (key)
+                       {
+                       case KEY_UP:
+                               if (nOptionSelected)
+                               {
+                                       nOptionSelected--;
+
+                                       // Update the menu
+                                       DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
+                               }
+                               break;
+                       case KEY_DOWN:
+                               if (nOptionSelected < (OptionsMenuItemCount - 1))
+                               {
+                                       nOptionSelected++;
+
+                                       // Update the menu
+                                       DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
+                               }
+                               break;
+                       case KEY_ENTER:
+                               //MessageBox("The Advanced Options are still being implemented.");
+                               bDone = TRUE;
+                               break;
+                       case KEY_ESC:
+                               nOptionSelected = -1;
+                               bDone = TRUE;
+                               break;
+                       }
+               }
+
+               // Update the date & time
+               UpdateDateTime();
+
+               if (nTimeOut > 0)
+               {
+                       if (getsecond() != second)
+                       {
+                               second = getsecond();
+                               nTimeOut--;
+
+                               // Update the menu
+                               DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
+                       }
+               }
+
+               if (nTimeOut == 0)
+                       bDone = TRUE;
+       }
+       while (!bDone);
+
+       return nOptionSelected;
+}
+
+void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount)
+{
+       int             height = OptionsMenuItemCount;
+       int             width = 20;
+
+       height += 1; // Allow room for top & bottom borders
+       width += 18; // Allow room for left & right borders, plus 8 spaces on each side
+
+       // Calculate the OS list box area
+       *nOptionsMenuBoxLeft = (nScreenWidth - width) / 2;
+       *nOptionsMenuBoxRight = *nOptionsMenuBoxLeft + width;
+       *nOptionsMenuBoxTop = (nScreenHeight - height) / 2 + 1;
+       *nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;
+}
+
+void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom)
+{
+       int             i, j;
+       char    text[260];
+       int             space, space_left, space_right;
+
+       // Update the status bar
+       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));
+
+       for(i=0; i<OptionsMenuItemCount; i++)
+       {
+               space = (nOptionsMenuBoxRight - nOptionsMenuBoxLeft - 2) - strlen(OptionsMenuItems[i]);
+               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, OptionsMenuItems[i]);
+               for(j=0; j<space_right; j++)
+                       strcat(text, " ");
+
+               if(i == nOptionSelected)
+               {
+                       DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
+               }
+               else
+               {
+                       DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
+               }
+       }
+}
\ No newline at end of file
diff --git a/freeldr/freeldr/options.h b/freeldr/freeldr/options.h
new file mode 100644 (file)
index 0000000..5e1e255
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  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.
+ */
+
+#ifndef __OPTIONS_H
+#define __OPTIONS_H
+
+void   DoOptionsMenu(void);
+void   DoDiskOptionsMenu(void);
+void   DoBootOptionsMenu(int BootDriveNum, char *BootDriveText);
+void   DoBootPartitionOptionsMenu(int BootDriveNum);
+int            RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle);
+void   InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount);
+void   DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom);
+
+#endif // #defined __OPTIONS_H
\ No newline at end of file
diff --git a/freeldr/freeldr/pe.h b/freeldr/freeldr/pe.h
new file mode 100644 (file)
index 0000000..c1454f9
--- /dev/null
@@ -0,0 +1,593 @@
+
+#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
+
+#define IMAGE_SECTION_CHAR_CODE          0x00000020
+#define IMAGE_SECTION_CHAR_DATA          0x00000040
+#define IMAGE_SECTION_CHAR_BSS           0x00000080
+#define IMAGE_SECTION_CHAR_NON_CACHABLE  0x04000000
+#define IMAGE_SECTION_CHAR_NON_PAGEABLE  0x08000000
+#define IMAGE_SECTION_CHAR_SHARED        0x10000000
+#define IMAGE_SECTION_CHAR_EXECUTABLE    0x20000000
+#define IMAGE_SECTION_CHAR_READABLE      0x40000000
+#define IMAGE_SECTION_CHAR_WRITABLE      0x80000000
+
+
+#define IMAGE_DOS_MAGIC  0x5a4d
+#define IMAGE_PE_MAGIC   0x00004550
+
+typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
+    WORD   e_magic;                     // Magic number
+    WORD   e_cblp;                      // Bytes on last page of file
+    WORD   e_cp;                        // Pages in file
+    WORD   e_crlc;                      // Relocations
+    WORD   e_cparhdr;                   // Size of header in paragraphs
+    WORD   e_minalloc;                  // Minimum extra paragraphs needed
+    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
+    WORD   e_ss;                        // Initial (relative) SS value
+    WORD   e_sp;                        // Initial SP value
+    WORD   e_csum;                      // Checksum
+    WORD   e_ip;                        // Initial IP value
+    WORD   e_cs;                        // Initial (relative) CS value
+    WORD   e_lfarlc;                    // File address of relocation table
+    WORD   e_ovno;                      // Overlay number
+    WORD   e_res[4];                    // Reserved words
+    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
+    WORD   e_oeminfo;                   // OEM information; e_oemid specific
+    WORD   e_res2[10];                  // Reserved words
+    LONG   e_lfanew;                    // File address of new exe header
+} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+typedef struct _IMAGE_FILE_HEADER {
+    WORD    Machine;
+    WORD    NumberOfSections;
+    DWORD   TimeDateStamp;
+    DWORD   PointerToSymbolTable;
+    DWORD   NumberOfSymbols;
+    WORD    SizeOfOptionalHeader;
+    WORD    Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+#define IMAGE_SIZEOF_FILE_HEADER             20
+
+#define IMAGE_FILE_RELOCS_STRIPPED           0x0001  // Relocation info stripped from file.
+#define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002  // File is executable  (i.e. no unresolved externel references).
+#define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004  // Line nunbers stripped from file.
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED       0x0008  // Local symbols stripped from file.
+#define IMAGE_FILE_BYTES_REVERSED_LO         0x0080  // Bytes of machine word are reversed.
+#define IMAGE_FILE_32BIT_MACHINE             0x0100  // 32 bit word machine.
+#define IMAGE_FILE_DEBUG_STRIPPED            0x0200  // Debugging info stripped from file in .DBG file
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400  // If Image is on removable media, copy and run from the swap file.
+#define IMAGE_FILE_NET_RUN_FROM_SWAP         0x0800  // If Image is on Net, copy and run from the swap file.
+#define IMAGE_FILE_SYSTEM                    0x1000  // System File.
+#define IMAGE_FILE_DLL                       0x2000  // File is a DLL.
+#define IMAGE_FILE_UP_SYSTEM_ONLY            0x4000  // File should only be run on a UP machine
+#define IMAGE_FILE_BYTES_REVERSED_HI         0x8000  // Bytes of machine word are reversed.
+
+#define IMAGE_FILE_MACHINE_UNKNOWN           0
+#define IMAGE_FILE_MACHINE_I386              0x14c   // Intel 386.
+#define IMAGE_FILE_MACHINE_R3000             0x162   // MIPS little-endian, 0x160 big-endian
+#define IMAGE_FILE_MACHINE_R4000             0x166   // MIPS little-endian
+#define IMAGE_FILE_MACHINE_R10000            0x168   // MIPS little-endian
+#define IMAGE_FILE_MACHINE_ALPHA             0x184   // Alpha_AXP
+#define IMAGE_FILE_MACHINE_POWERPC           0x1F0   // IBM PowerPC Little-Endian
+
+
+//
+// Directory format.
+//
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+    DWORD   VirtualAddress;
+    DWORD   Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16
+
+//
+// Optional header format.
+//
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+    //
+    // Standard fields.
+    //
+
+    WORD    Magic;
+    BYTE    MajorLinkerVersion;
+    BYTE    MinorLinkerVersion;
+    DWORD   SizeOfCode;
+    DWORD   SizeOfInitializedData;
+    DWORD   SizeOfUninitializedData;
+    DWORD   AddressOfEntryPoint;
+    DWORD   BaseOfCode;
+    DWORD   BaseOfData;
+
+    //
+    // NT additional fields.
+    //
+
+    DWORD   ImageBase;
+    DWORD   SectionAlignment;
+    DWORD   FileAlignment;
+    WORD    MajorOperatingSystemVersion;
+    WORD    MinorOperatingSystemVersion;
+    WORD    MajorImageVersion;
+    WORD    MinorImageVersion;
+    WORD    MajorSubsystemVersion;
+    WORD    MinorSubsystemVersion;
+    DWORD   Win32VersionValue;
+    DWORD   SizeOfImage;
+    DWORD   SizeOfHeaders;
+    DWORD   CheckSum;
+    WORD    Subsystem;
+    WORD    DllCharacteristics;
+    DWORD   SizeOfStackReserve;
+    DWORD   SizeOfStackCommit;
+    DWORD   SizeOfHeapReserve;
+    DWORD   SizeOfHeapCommit;
+    DWORD   LoaderFlags;
+    DWORD   NumberOfRvaAndSizes;
+    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
+
+#define IMAGE_SUBSYSTEM_UNKNOWN                0
+#define IMAGE_SUBSYSTEM_NATIVE         1
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI    2
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI    3
+#define IMAGE_SUBSYSTEM_OS2_GUI                4
+#define IMAGE_SUBSYSTEM_OS2_CUI                5
+#define IMAGE_SUBSYSTEM_POSIX_GUI      6
+#define IMAGE_SUBSYSTEM_POSIX_CUI      7
+#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
+
+typedef struct _IMAGE_NT_HEADERS {
+    DWORD Signature;
+    IMAGE_FILE_HEADER FileHeader;
+    IMAGE_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
+
+
+// Directory Entries
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT         0   // Export Directory
+#define IMAGE_DIRECTORY_ENTRY_IMPORT         1   // Import Directory
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2   // Resource Directory
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3   // Exception Directory
+#define IMAGE_DIRECTORY_ENTRY_SECURITY       4   // Security Directory
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5   // Base Relocation Table
+#define IMAGE_DIRECTORY_ENTRY_DEBUG          6   // Debug Directory
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7   // Description String
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8   // Machine Value (MIPS GP)
+#define IMAGE_DIRECTORY_ENTRY_TLS            9   // TLS Directory
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10   // Load Configuration Directory
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11   // Bound Import Directory in headers
+#define IMAGE_DIRECTORY_ENTRY_IAT           12   // Import Address 
+//
+// Section header format.
+//
+
+#define IMAGE_SIZEOF_SHORT_NAME              8
+
+typedef struct _IMAGE_SECTION_HEADER {
+    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
+    union {
+            DWORD   PhysicalAddress;
+            DWORD   VirtualSize;
+    } Misc;
+    DWORD   VirtualAddress;
+    DWORD   SizeOfRawData;
+    DWORD   PointerToRawData;
+    DWORD   PointerToRelocations;
+    DWORD   PointerToLinenumbers;
+    WORD    NumberOfRelocations;
+    WORD    NumberOfLinenumbers;
+    DWORD   Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define IMAGE_SIZEOF_SECTION_HEADER          40
+
+#define IMAGE_SECTION_CODE (0x20)
+#define IMAGE_SECTION_INITIALIZED_DATA (0x40)
+#define IMAGE_SECTION_UNINITIALIZED_DATA (0x80)
+
+//
+// Export Format
+//
+
+typedef struct _IMAGE_EXPORT_DIRECTORY {
+    DWORD   Characteristics;
+    DWORD   TimeDateStamp;
+    WORD    MajorVersion;
+    WORD    MinorVersion;
+    DWORD   Name;
+    DWORD   Base;
+    DWORD   NumberOfFunctions;
+    DWORD   NumberOfNames;
+    PDWORD  *AddressOfFunctions;
+    PDWORD  *AddressOfNames;
+    PWORD   *AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
+
+//
+// Import Format
+//
+
+typedef struct _IMAGE_IMPORT_BY_NAME {
+    WORD    Hint;
+    BYTE    Name[1];
+} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
+
+#define IMAGE_ORDINAL_FLAG 0x80000000
+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+
+// Predefined resource types ... there may be some more, but I don't have
+//                               the information yet.  .....sang cho.....
+
+#define    RT_NEWRESOURCE   0x2000
+#define    RT_ERROR         0x7fff
+#define    NEWBITMAP        (RT_BITMAP|RT_NEWRESOURCE)
+#define    NEWMENU          (RT_MENU|RT_NEWRESOURCE)
+#define    NEWDIALOG        (RT_DIALOG|RT_NEWRESOURCE)
+
+
+//
+// Resource Format.
+//
+
+//
+// Resource directory consists of two counts, following by a variable length
+// array of directory entries.  The first count is the number of entries at
+// beginning of the array that have actual names associated with each entry.
+// The entries are in ascending order, case insensitive strings.  The second
+// count is the number of entries that immediately follow the named entries.
+// This second count identifies the number of entries that have 16-bit integer
+// Ids as their name.  These entries are also sorted in ascending order.
+//
+// This structure allows fast lookup by either name or number, but for any
+// given resource entry only one form of lookup is supported, not both.
+// This is consistant with the syntax of the .RC file and the .RES file.
+//
+
+
+//
+// Each directory contains the 32-bit Name of the entry and an offset,
+// relative to the beginning of the resource directory of the data associated
+// with this directory entry.  If the name of the entry is an actual text
+// string instead of an integer Id, then the high order bit of the name field
+// is set to one and the low order 31-bits are an offset, relative to the
+// beginning of the resource directory of the string, which is of type
+// IMAGE_RESOURCE_DIRECTORY_STRING.  Otherwise the high bit is clear and the
+// low-order 16-bits are the integer Id that identify this resource directory
+// entry. If the directory entry is yet another resource directory (i.e. a
+// subdirectory), then the high order bit of the offset field will be
+// set to indicate this.  Otherwise the high bit is clear and the offset
+// field points to a resource data entry.
+//
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
+    DWORD    Name;
+    DWORD    OffsetToData;
+} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY {
+    DWORD   Characteristics;
+    DWORD   TimeDateStamp;
+    WORD    MajorVersion;
+    WORD    MinorVersion;
+    WORD    NumberOfNamedEntries;
+    WORD    NumberOfIdEntries;
+    IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[0];
+} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
+
+#define IMAGE_RESOURCE_NAME_IS_STRING        0x80000000
+#define IMAGE_RESOURCE_DATA_IS_DIRECTORY     0x80000000
+
+
+
+//
+// For resource directory entries that have actual string names, the Name
+// field of the directory entry points to an object of the following type.
+// All of these string objects are stored together after the last resource
+// directory entry and before the first resource data object.  This minimizes
+// the impact of these variable length objects on the alignment of the fixed
+// size directory entry objects.
+//
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
+    WORD    Length;
+    CHAR    NameString[ 1 ];
+} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING;
+
+
+typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
+    WORD    Length;
+    WCHAR   NameString[ 1 ];
+} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
+
+
+//
+// Each resource data entry describes a leaf node in the resource directory
+// tree.  It contains an offset, relative to the beginning of the resource
+// directory of the data for the resource, a size field that gives the number
+// of bytes of data at that offset, a CodePage that should be used when
+// decoding code point values within the resource data.  Typically for new
+// applications the code page would be the unicode code page.
+//
+
+typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
+    DWORD   OffsetToData;
+    DWORD   Size;
+    DWORD   CodePage;
+    DWORD   Reserved;
+} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
+
+
+//  Menu Resources      ... added by .....sang cho....
+
+// Menu resources are composed of a menu header followed by a sequential list
+// of menu items. There are two types of menu items: pop-ups and normal menu
+// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with
+// an empty name, zero ID, and zero flags.
+
+typedef struct _IMAGE_MENU_HEADER{
+    WORD   wVersion;     // Currently zero
+       WORD   cbHeaderSize;  // Also zero
+} IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER;
+
+typedef struct _IMAGE_POPUP_MENU_ITEM{
+    WORD   fItemFlags; 
+       WCHAR  szItemText[1];
+} IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM;
+
+typedef struct _IMAGE_NORMAL_MENU_ITEM{
+    WORD   fItemFlags; 
+       WORD   wMenuID;
+       WCHAR  szItemText[1];
+} IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM;
+
+#define MI_GRAYED       0x0001 // GRAYED keyword
+#define MI_INACTIVE     0x0002 // INACTIVE keyword
+#define MI_BITMAP       0x0004 // BITMAP keyword
+#define MI_OWNERDRAW    0x0100 // OWNERDRAW keyword
+#define MI_CHECKED      0x0008 // CHECKED keyword
+#define MI_POPUP        0x0010 // used internally
+#define MI_MENUBARBREAK 0x0020 // MENUBARBREAK keyword
+#define MI_MENUBREAK    0x0040 // MENUBREAK keyword
+#define MI_ENDMENU      0x0080 // used internally
+
+// Dialog Box Resources        .................. added by sang cho.
+
+// A dialog box is contained in a single resource and has a header and 
+// a portion repeated for each control in the dialog box.
+// The item DWORD IStyle is a standard window style composed of flags found
+// in WINDOWS.H.
+// The default style for a dialog box is:
+// WS_POPUP | WS_BORDER | WS_SYSMENU
+// 
+// The itme marked "Name or Ordinal" are :
+// If the first word is an 0xffff, the next two bytes contain an ordinal ID.
+// Otherwise, the first one or more WORDS contain a double-null-terminated string.
+// An empty string is represented by a single WORD zero in the first location.
+// 
+// The WORD wPointSize and WCHAR szFontName entries are present if the FONT
+// statement was included for the dialog box. This can be detected by checking
+// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these
+// entries will be present.
+
+typedef struct _IMAGE_DIALOG_BOX_HEADER1{
+    DWORD  IStyle;
+       DWORD  IExtendedStyle;    // New for Windows NT
+       WORD   nControls;         // Number of Controls
+       WORD   x;
+       WORD   y;
+       WORD   cx;
+       WORD   cy;
+//     N_OR_O MenuName;         // Name or Ordinal ID
+//     N_OR_O ClassName;                // Name or Ordinal ID
+//     WCHAR  szCaption[];
+//     WORD   wPointSize;       // Only here if FONT set for dialog
+//     WCHAR  szFontName[];     // This too
+} IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER;
+
+typedef union _NAME_OR_ORDINAL{    // Name or Ordinal ID
+       struct _ORD_ID{
+           WORD   flgId;
+        WORD   Id;
+       } ORD_ID;
+       WCHAR  szName[1];      
+} NAME_OR_ORDINAL, *PNAME_OR_ORDINAL;
+
+// The data for each control starts on a DWORD boundary (which may require
+// some padding from the previous control), and its format is as follows:
+
+typedef struct _IMAGE_CONTROL_DATA{
+    DWORD   IStyle;
+       DWORD   IExtendedStyle;
+       WORD    x;
+       WORD    y;
+       WORD    cx;
+       WORD    cy;
+       WORD    wId;
+//  N_OR_O  ClassId;
+//  N_OR_O  Text;
+//  WORD    nExtraStuff;
+} IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA;
+
+#define BUTTON       0x80
+#define EDIT         0x81
+#define STATIC       0x82
+#define LISTBOX      0x83
+#define SCROLLBAR    0x84
+#define COMBOBOX     0x85
+
+// The various statements used in a dialog script are all mapped to these
+// classes along with certain modifying styles. The values for these styles
+// can be found in WINDOWS.H. All dialog controls have the default styles
+// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows:
+//
+// Statement           Default Class         Default Styles
+// CONTROL             None                  WS_CHILD|WS_VISIBLE
+// LTEXT               STATIC                ES_LEFT
+// RTEXT               STATIC                ES_RIGHT
+// CTEXT               STATIC                ES_CENTER
+// LISTBOX             LISTBOX               WS_BORDER|LBS_NOTIFY
+// CHECKBOX            BUTTON                BS_CHECKBOX|WS_TABSTOP
+// PUSHBUTTON          BUTTON                BS_PUSHBUTTON|WS_TABSTOP
+// GROUPBOX            BUTTON                BS_GROUPBOX
+// DEFPUSHBUTTON       BUTTON                BS_DFPUSHBUTTON|WS_TABSTOP
+// RADIOBUTTON         BUTTON                BS_RADIOBUTTON
+// AUTOCHECKBOX        BUTTON                BS_AUTOCHECKBOX
+// AUTO3STATE          BUTTON                BS_AUTO3STATE
+// AUTORADIOBUTTON     BUTTON                BS_AUTORADIOBUTTON
+// PUSHBOX             BUTTON                BS_PUSHBOX
+// STATE3              BUTTON                BS_3STATE
+// EDITTEXT            EDIT                  ES_LEFT|WS_BORDER|WS_TABSTOP
+// COMBOBOX            COMBOBOX              None
+// ICON                STATIC                SS_ICON
+// SCROLLBAR           SCROLLBAR             None
+///
+
+//
+// Debug Format
+//
+
+typedef struct _IMAGE_DEBUG_DIRECTORY {
+    DWORD   Characteristics;
+    DWORD   TimeDateStamp;
+    WORD    MajorVersion;
+    WORD    MinorVersion;
+    DWORD   Type;
+    DWORD   SizeOfData;
+    DWORD   AddressOfRawData;
+    DWORD   PointerToRawData;
+} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
+
+#define IMAGE_DEBUG_TYPE_UNKNOWN          0
+#define IMAGE_DEBUG_TYPE_COFF             1
+#define IMAGE_DEBUG_TYPE_CODEVIEW         2
+#define IMAGE_DEBUG_TYPE_FPO              3
+#define IMAGE_DEBUG_TYPE_MISC             4
+#define IMAGE_DEBUG_TYPE_EXCEPTION        5
+#define IMAGE_DEBUG_TYPE_FIXUP            6
+#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC      7
+#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC    8
+
+
+typedef struct _IMAGE_DEBUG_MISC {
+    DWORD       DataType;               // type of misc data, see defines
+    DWORD       Length;                 // total length of record, rounded to four
+                                        // byte multiple.
+    BOOL        Unicode;                // TRUE if data is unicode string
+    BYTE        Reserved[ 3 ];
+    BYTE        Data[ 1 ];              // Actual data
+} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;
+
+
+//
+// Debugging information can be stripped from an image file and placed
+// in a separate .DBG file, whose file name part is the same as the
+// image file name part (e.g. symbols for CMD.EXE could be stripped
+// and placed in CMD.DBG).  This is indicated by the IMAGE_FILE_DEBUG_STRIPPED
+// flag in the Characteristics field of the file header.  The beginning of
+// the .DBG file contains the following structure which captures certain
+// information from the image file.  This allows a debug to proceed even if
+// the original image file is not accessable.  This header is followed by
+// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more
+// IMAGE_DEBUG_DIRECTORY structures.  The latter structures and those in
+// the image file contain file offsets relative to the beginning of the
+// .DBG file.
+//
+// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure
+// is left in the image file, but not mapped.  This allows a debugger to
+// compute the name of the .DBG file, from the name of the image in the
+// IMAGE_DEBUG_MISC structure.
+//
+
+typedef struct _IMAGE_SEPARATE_DEBUG_HEADER {
+    WORD        Signature;
+    WORD        Flags;
+    WORD        Machine;
+    WORD        Characteristics;
+    DWORD       TimeDateStamp;
+    DWORD       CheckSum;
+    DWORD       ImageBase;
+    DWORD       SizeOfImage;
+    DWORD       NumberOfSections;
+    DWORD       ExportedNamesSize;
+    DWORD       DebugDirectorySize;
+    DWORD       SectionAlignment;
+    DWORD       Reserved[2];
+} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;
+
+#define IMAGE_SEPARATE_DEBUG_SIGNATURE  0x4944
+
+#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000
+#define IMAGE_SEPARATE_DEBUG_MISMATCH   0x8000  // when DBG was updated, the
+                                                // old checksum didn't match.
+
+//
+// End Image Format
+//
+
+#define SIZE_OF_NT_SIGNATURE   sizeof (DWORD)
+#define MAXRESOURCENAME        13
+
+/* global macros to define header offsets into file */
+/* offset to PE file signature                                */
+#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a                  +  \
+                       ((PIMAGE_DOS_HEADER)a)->e_lfanew))
+
+/* DOS header identifies the NT PEFile signature dword
+   the PEFILE header exists just after that dword             */
+#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a                 +  \
+                        ((PIMAGE_DOS_HEADER)a)->e_lfanew    +  \
+                        SIZE_OF_NT_SIGNATURE))
+
+/* PE optional header is immediately after PEFile header       */
+#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a                 +  \
+                        ((PIMAGE_DOS_HEADER)a)->e_lfanew    +  \
+                        SIZE_OF_NT_SIGNATURE                +  \
+                        sizeof (IMAGE_FILE_HEADER)))
+
+/* section headers are immediately after PE optional header    */
+#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a                 +  \
+                        ((PIMAGE_DOS_HEADER)a)->e_lfanew    +  \
+                        SIZE_OF_NT_SIGNATURE                +  \
+                        sizeof (IMAGE_FILE_HEADER)          +  \
+                        sizeof (IMAGE_OPTIONAL_HEADER)))
+
+#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
+
+typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY
+{
+  DWORD    dwRVAFunctionNameList;
+  DWORD    dwUseless1;
+  DWORD    dwUseless2;
+  DWORD    dwRVAModuleName;
+  DWORD    dwRVAFunctionAddressList;
+} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;
+
+typedef struct _RELOCATION_DIRECTORY
+{
+    DWORD  VirtualAddress; /* adresse virtuelle du bloc ou se font les relocations */
+    DWORD   SizeOfBlock;    // taille de cette structure + des structures
+                       // relocation_entry qui suivent (ces dernieres sont
+                       // donc au nombre de (SizeOfBlock-8)/2
+} RELOCATION_DIRECTORY, *PRELOCATION_DIRECTORY;
+
+typedef struct _RELOCATION_ENTRY
+{
+    WORD    TypeOffset;
+       //      (TypeOffset >> 12) est le type
+       //      (TypeOffset&0xfff) est l'offset dans le bloc
+} RELOCATION_ENTRY, *PRELOCATION_ENTRY;
+
+#define        TYPE_RELOC_ABSOLUTE     0
+#define        TYPE_RELOC_HIGH         1
+#define        TYPE_RELOC_LOW          2
+#define        TYPE_RELOC_HIGHLOW      3
+#define        TYPE_RELOC_HIGHADJ      4
+#define        TYPE_RELOC_MIPS_JMPADDR 5
+
diff --git a/freeldr/freeldr/ros.S b/freeldr/freeldr/ros.S
new file mode 100644 (file)
index 0000000..b10b735
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ *  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.
+ */
+
+       .text
+       .code16
+
+#include "asmcode.h"
+
+       /*
+        * Needed for enabling the a20 address line
+        */
+empty_8042:
+       .word   0x00eb,0x00eb            // jmp $+2, jmp $+2
+       inb     $0x64,%al
+    testb   $0x02,%al
+    jnz     empty_8042
+       ret
+
+       /*
+        * Enable the A20 address line (to allow access to over 1mb)
+        */
+       .code32
+EXTERN(_enable_a20)
+       call    switch_to_real
+       .code16
+
+       call    empty_8042
+    movb       $0xD1,%al                // command write
+    outb       %al,$0x64
+       call    empty_8042
+    mov                $0xDF,%al                // A20 on
+    out                %al,$0x60
+       call    empty_8042
+       call    switch_to_prot
+       .code32
+
+       ret
+
+       .code16
+
+    /*
+     * Reprogram the PIC because they overlap the Intel defined
+     * exceptions 
+        */
+reprogram_pic:
+       movb    $0x11,%al                // initialization sequence
+       outb    %al,$0x20                // send it to 8259A-1
+       .word   0x00eb,0x00eb            // jmp $+2, jmp $+2
+       outb    %al,$0xA0                // and to 8259A-2
+       .word   0x00eb,0x00eb
+       movb    $0x40,%al                // start of hardware int's (0x20)
+       outb    %al,$0x21
+       .word   0x00eb,0x00eb
+       movb    $0x48,%al                // start of hardware int's 2 (0x28)
+       outb    %al,$0xA1
+       .word   0x00eb,0x00eb
+       movb    $0x04,%al                // 8259-1 is master
+       outb    %al,$0x21
+       .word   0x00eb,0x00eb
+       movb    $0x02,%al                // 8259-2 is slave
+       outb    %al,$0xA1
+       .word   0x00eb,0x00eb
+       movb    $0x01,%al                // 8086 mode for both
+       outb    %al,$0x21
+       .word   0x00eb,0x00eb
+       outb    %al,$0xA1
+       .word   0x00eb,0x00eb
+       movb    $0xFF,%al                // mask off all interrupts for now
+       outb    %al,$0x21
+       .word   0x00eb,0x00eb
+       outb    %al,$0xA1
+       ret
+
+       /*
+        * In: EDI = address
+        * Out: FS = segment
+        *      DI = base
+        */
+convert_to_seg:
+       pushl   %eax
+
+       movl    %edi,%eax
+       //shrl  $16,%eax
+       //shll  $12,%eax
+       //movw  %ax,%fs
+
+       shrl    $4,%eax
+       movw    %ax,%fs
+       andl    $0xf,%edi
+
+       //andl  $0xFFFF,%edi
+
+       popl    %eax
+       ret
+
+       /*
+     * Here we assume the kernel is loaded at 1mb
+     * This boots the kernel
+        */
+       .code32
+EXTERN(_boot_ros)
+       call    switch_to_real
+       .code16
+
+    /* Save cursor position */
+       movw    $3,%ax          //! Reset video mode
+       int     $0x10
+
+
+       movb    $10,%bl
+       movb    $12,%ah
+       int     $0x10
+
+       movw    $0x1112,%ax      //! Use 8x8 font
+       xorb    %bl,%bl
+       int     $0x10
+       movw    $0x1200,%ax      //! Use alternate print screen
+       movb    $0x20,%bl
+       int     $0x10
+       movb    $1,%ah         //! Define cursor (scan lines 6 to 7)
+       movw    $0x0607,%cx
+       int     $0x10
+
+       movb    $1,%ah
+       movw    $0x600,%cx
+       int     $0x10
+
+       MOVb      $6,%AH        //SCROLL ACTIVE PAGE UP
+       MOVb      $0x32,%AL      //CLEAR 25 LINES
+       MOVw      $0,%CX       //UPPER LEFT OF SCROLL
+       MOVw      $0x314F,%dx    //LOWER RIGHT OF SCROLL
+       MOVb      $(1*0x10+1),%bh  //USE NORMAL ATTRIBUTE ON BLANKED LINE
+       INT       $0x10         //VIDEO-IO
+
+
+       movw     $0,%dx
+       movb     $0,%dh
+
+       movb     $2,%ah
+       movb     $0,%bh
+       int     $0x10
+
+       movw     $0,%dx
+       movb     $0,%dh
+
+       movb     $2,%ah
+       movb     $0,%bh
+       int      $0x10
+
+       cli
+
+       // The page tables are setup elsewhere
+       /*
+       // Map in the lowmem page table (and reuse it for the identity map)
+       movl    _kernel_page_directory_base,%edi
+       call    convert_to_seg
+
+       movl    _lowmem_page_table_base,%eax
+       addl    $0x07,%eax
+       movl    %eax,%fs:(%edi)
+       movl    %eax,%fs:0xd00(%edi)//(0xd0000000/(1024*1024))(%edi)
+       
+       // Map the page tables from the page directory
+       movl    _kernel_page_directory_base,%eax
+       addl    $0x07,%eax
+       movl    %eax,%fs:0xf00(%edi)//(0xf0000000/(1024*1024))(%edi)
+
+       // Map in the kernel page table
+       movl    _system_page_table_base,%eax
+       addl    $0x07,%eax
+       movl    %eax,%fs:0xc00(%edi)//(0xc0000000/(1024*1024))(%edi)
+
+       // Setup the lowmem page table
+       movl    _lowmem_page_table_base,%edi
+       call    convert_to_seg
+
+       movl    $0,%ebx
+l9:
+       movl    %ebx,%eax
+       shll    $12,%eax        // ebx = ebx * 4096
+       addl    $07,%eax        // user, rw, present
+       movl    %eax,%fs:(%edi,%ebx,4)
+       incl    %ebx
+       cmpl    $1024,%ebx
+       jl              l9
+
+       // Setup the system page table
+       movl    _system_page_table_base,%edi
+       call    convert_to_seg
+
+       movl    $07,%eax
+l8:
+       movl    %eax,%edx
+       addl    _start_kernel,%edx
+       movl    %edx,%fs:(%edi)
+       addl    $4,%edi
+       addl    $0x1000,%eax
+       cmpl    $0x100007,%eax
+       jl      l8
+       */
+
+       /*
+        * Load the page directory into cr3
+        */
+       movl    _kernel_page_directory_base,%eax
+       movl    %eax,%cr3
+
+       /*
+        * Setup various variables
+        */
+       movw    %ds,%bx
+       movzwl  %bx,%eax
+       shll    $4,%eax
+       addl    %eax,kernel_gdtbase
+
+       //call  enable_a20 // enabled elsewhere
+       call    reprogram_pic
+
+       /*
+        * Load stack
+        */
+       movw    %ds,%bx
+       movzwl  %bx,%eax
+       shll    $4,%eax
+       addl    $real_stack_end,%eax
+       movl    %eax,real_stack_base
+       movl    real_stack_base,%esp
+       movl    _boot_param_struct_base,%edx
+
+       /*
+        * load gdt
+        */
+       lgdt    kernel_gdtptr
+
+       /*       
+        * Enter pmode and clear prefetch queue
+        */
+       movl    %cr0,%eax
+       orl             $0x80010001,%eax
+       /*orl           $0x80000001,%eax*/
+       movl    %eax,%cr0
+       jmp             next
+next:
+       /*
+        * NOTE: This must be position independant (no references to
+        * non absolute variables)
+        */
+
+       /*
+        * Initalize segment registers
+        */
+       movw    $KERNEL_DS,%ax
+       movw    %ax,%ds
+       movw    %ax,%ss
+       movw    %ax,%es
+       movw    %ax,%fs
+       movw    %ax,%gs
+
+       /*
+        * Initalize eflags
+        */
+       pushl   $0
+       popfl   
+
+       /*
+        * Jump to start of 32 bit code at 0xc0000000 + 0x1000
+        */
+       pushl   %edx
+       pushl   $0
+       ljmpl   $KERNEL_CS,$(KERNEL_BASE+0x1000)
+
+
+       .p2align        2       /* force 4-byte alignment */
+kernel_gdt:
+       .word 0               // Zero descriptor
+       .word 0
+       .word 0
+       .word 0
+                        
+       //.word 0x0000          // User code descriptor
+       //.word 0x0000          // base: 0h limit: 3gb
+       //.word 0xfa00
+       //.word 0x00cc
+                       
+       //.word 0x0000          // User data descriptor
+       //.word 0x0000          // base: 0h limit: 3gb
+       //.word 0xf200
+       //.word 0x00cc
+                    
+       //.word 0x0000         
+       //.word 0x0000         
+       //.word 0x0000
+       //.word 0x0000
+
+       .word 0xffff          // Kernel code descriptor 
+       .word 0x0000          // 
+       .word 0x9a00          // base 0h limit 4gb
+       .word 0x00cf
+                       
+       .word 0xffff          // Kernel data descriptor
+       .word 0x0000          // 
+       .word 0x9200          // base 0h limit 4gb
+       .word 0x00cf
+
+    /* TSS space */    
+       //.rept NR_TASKS
+       //.word 0
+       //.word 0
+       //.word 0
+       //.word 0
+       //.endr
+
+kernel_gdtptr:
+       .word   (((6+NR_TASKS)*8)-1)    /* Limit */
+kernel_gdtbase:
+       .long   kernel_gdt                              /* Base Address */
+
+EXTERN(_boot_param_struct_base)
+       .long   0
+EXTERN(_start_mem)
+       .long   0
+EXTERN(_kernel_page_directory_base)
+       .long   0
+EXTERN(_system_page_table_base)
+       .long   0
+EXTERN(_lowmem_page_table_base)
+       .long   0
+EXTERN(_start_kernel)
+       .long   0
+EXTERN(_load_base)
+       .long   0
+
+/* boot_param structure */
+EXTERN(_boot_parameters)
+       .long   0               // Magic
+       .long   0               // Cursor X
+       .long   0               // Cursor Y
+       .long   0               // nr_files
+       .long   0               // start_mem
+       .long   0               // end_mem
+
+       .rept   64
+       .long   0               // List of module lengths (terminated by a 0)
+       .endr
+
+       .rept   256
+       .byte   0               // Kernel parameter string
+       .endr
+
+/* Our initial stack */
+real_stack:
+               .rept 1024
+               .byte 0
+               .endr
+real_stack_end:
+
+real_stack_base:
+               .long 0
diff --git a/freeldr/freeldr/rosboot.c b/freeldr/freeldr/rosboot.c
new file mode 100644 (file)
index 0000000..371fe14
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *  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 "asmcode.h"
+#include "rosboot.h"
+#include "stdlib.h"
+#include "fs.h"
+#include "tui.h"
+
+extern boot_param      boot_parameters;                        // Boot parameter structure passed to the kernel
+extern int     boot_param_struct_base;         // Physical address of the boot parameters structure
+extern int     start_mem;                                      // Start of the continuous range of physical kernel memory
+extern int     kernel_page_directory_base;     // Physical address of the kernel page directory
+extern int     system_page_table_base;         // Physical address of the system page table
+extern int     lowmem_page_table_base;         // Physical address of the low mem page table
+extern int     start_kernel;                           // Physical address of the start of kernel code
+extern int     load_base;                                      // Physical address of the loaded kernel modules 
+
+static int     next_load_base;
+
+void LoadAndBootReactOS(int nOSToBoot)
+{
+       FILE            file;
+       char            name[1024];
+       char            value[1024];
+       char            szFileName[1024];
+       int                     i;
+       int                     nNumDriverFiles=0;
+       int                     nNumFilesLoaded=0;
+
+       /*
+        * Enable a20 so we can load at 1mb and initialize the page tables
+        */
+       //enable_a20(); // enabled in freeldr.c
+       ReactOSMemInit();
+
+       // Setup kernel parameters
+       boot_param_struct_base = (int)&boot_parameters;
+       boot_parameters.magic = 0xdeadbeef;
+       boot_parameters.cursorx = 0;
+       boot_parameters.cursory = 0;
+       boot_parameters.nr_files = 0;
+       boot_parameters.start_mem = start_mem;
+       boot_parameters.end_mem = load_base;
+       boot_parameters.kernel_parameters[0] = 0;
+
+       next_load_base = load_base;
+
+       /*
+        * Read the optional kernel parameters
+        */
+       if(ReadSectionSettingByName(OSList[nOSToBoot].name, "Options", name, value))
+       {
+               strcpy(boot_parameters.kernel_parameters,value);
+       }
+
+       /*
+        * Find the kernel image name
+        */
+       if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "Kernel", name, value))
+       {
+               MessageBox("Kernel image file not specified for selected operating system.");
+               return;
+       }
+
+       /*
+        * Get the boot partition
+        */
+       BootPartition = 0;
+       if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
+               BootPartition = atoi(value);
+
+       /*
+        * Make sure the boot drive is set in the .ini file
+        */
+       if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
+       {
+               MessageBox("Boot drive not specified for selected operating system.");
+               return;
+       }
+
+       DrawBackdrop();
+
+       DrawStatusText(" Loading...");
+       DrawProgressBar(0);
+
+       /*
+        * Set the boot drive and try to open it
+        */
+       BootDrive = atoi(value);
+       if (!OpenDiskDrive(BootDrive, BootPartition))
+       {
+               MessageBox("Failed to open boot drive.");
+               return;
+       }
+
+       /*
+        * Parse the ini file and count the kernel and drivers
+        */
+       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       {
+               /*
+                * Read the setting and check if it's a driver
+                */
+               ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
+               if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
+                       nNumDriverFiles++;
+       }
+
+       /*
+        * Parse the ini file and load the kernel and
+        * load all the drivers specified
+        */
+       for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
+       {
+               /*
+                * Read the setting and check if it's a driver
+                */
+               ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
+               if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
+               {
+                       /*
+                        * Set the name and try to open the PE image
+                        */
+                       strcpy(szFileName, value);
+                       if (!OpenFile(szFileName, &file))
+                       {
+                               strcat(value, " not found.");
+                               MessageBox(value);
+                               return;
+                       }
+
+                       /*
+                        * Update the status bar with the current file
+                        */
+                       strcpy(name, " Reading ");
+                       strcat(name, value);
+                       while (strlen(name) < 80)
+                               strcat(name, " ");
+                       DrawStatusText(name);
+
+                       /*
+                        * Load the driver
+                        */
+                       ReactOSLoadPEImage(&file);
+
+                       nNumFilesLoaded++;
+                       DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
+
+                       // Increment the number of files we loaded
+                       boot_parameters.nr_files++;
+               }
+               else if (stricmp(name, "MessageBox") == 0)
+               {
+                       DrawStatusText(" Press ENTER to continue");
+                       MessageBox(value);
+               }
+               else if (stricmp(name, "MessageLine") == 0)
+                       MessageLine(value);
+               else if (stricmp(name, "ReOpenBootDrive") == 0)
+               {
+                       if (!OpenDiskDrive(BootDrive, BootPartition))
+                       {
+                               MessageBox("Failed to open boot drive.");
+                               return;
+                       }
+               }
+       }
+
+       /*
+        * End the list of modules we load with a zero length entry
+        * and update the end of kernel mem
+        */
+       boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
+       boot_parameters.end_mem = next_load_base;
+
+       /*
+        * Clear the screen and redraw the backdrop and status bar
+        */
+       DrawBackdrop();
+       DrawStatusText(" Press any key to boot");
+
+       /*
+        * Wait for user
+        */
+       strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
+       strcat(name, OSList[nOSToBoot].name);
+       strcat(name, ".");
+       //MessageBox(name);
+
+       RestoreScreen(pScreenBuffer);
+
+       /*
+        * Now boot the kernel
+        */
+       stop_floppy();
+       ReactOSBootKernel();
+}
+
+void ReactOSMemInit(void)
+{
+       int             base;
+
+       /* Calculate the start of extended memory */
+       base = 0x100000;
+
+       /* Set the start of the page directory */
+       kernel_page_directory_base = base;
+
+       /*
+        * Set the start of the continuous range of physical memory
+        * occupied by the kernel
+        */
+       start_mem = base;
+       base += 0x1000;
+
+       /* Calculate the start of the system page table (0xc0000000 upwards) */
+       system_page_table_base = base;
+       base += 0x1000;
+
+       /* Calculate the start of the page table to map the first 4mb */
+       lowmem_page_table_base = base;
+       base += 0x1000;
+
+       /* Set the position for the first module to be loaded */
+       load_base = base;
+
+       /* Set the address of the start of kernel code */
+       start_kernel = base;
+}
+
+void ReactOSBootKernel(void)
+{
+       int             i;
+       int             *pPageDirectory = (int *)kernel_page_directory_base;
+       int             *pLowMemPageTable = (int *)lowmem_page_table_base;
+       int             *pSystemPageTable = (int *)system_page_table_base;
+
+       /* Zero out the kernel page directory */
+       for(i=0; i<1024; i++)
+               pPageDirectory[i] = 0;
+
+       /* Map in the lowmem page table */
+       pPageDirectory[(0x00/4)] = lowmem_page_table_base + 0x07;
+
+       /* Map in the lowmem page table (and reuse it for the identity map) */
+       pPageDirectory[(0xd00/4)] = lowmem_page_table_base + 0x07;
+       
+       /* Map the page tables from the page directory */
+       pPageDirectory[(0xf00/4)] = kernel_page_directory_base + 0x07;
+
+       /* Map in the kernel page table */
+       pPageDirectory[(0xc00/4)] = system_page_table_base + 0x07;
+
+       /* Setup the lowmem page table */
+       for(i=0; i<1024; i++)
+               pLowMemPageTable[i] = (i * 4096) + 0x07;
+
+       /* Setup the system page table */
+       for(i=0; i<1024; i++)
+               pSystemPageTable[i] = ((i * 4096) + start_kernel) + 0x07;
+
+       boot_ros();
+}
+
+BOOL ReactOSLoadPEImage(FILE *pImage)
+{
+       unsigned int                    Idx, ImageBase;
+       PULONG                                  PEMagic;
+       PIMAGE_DOS_HEADER               PEDosHeader;
+       PIMAGE_FILE_HEADER              PEFileHeader;
+       PIMAGE_OPTIONAL_HEADER  PEOptionalHeader;
+       PIMAGE_SECTION_HEADER   PESectionHeaders;
+
+       ImageBase = next_load_base;
+       boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
+
+       /*
+        * Load the headers
+        */
+       ReadFile(pImage, 0x1000, (void *)next_load_base);
+
+       /*
+        * Get header pointers
+        */
+       PEDosHeader = (PIMAGE_DOS_HEADER) next_load_base;
+       PEMagic = (PULONG) ((unsigned int) next_load_base + 
+                               PEDosHeader->e_lfanew);
+       PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) next_load_base + 
+                                       PEDosHeader->e_lfanew + sizeof(ULONG));
+       PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) next_load_base + 
+                                       PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
+       PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) next_load_base + 
+                                       PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
+                                       sizeof(IMAGE_OPTIONAL_HEADER));
+
+       /*
+        * Check file magic numbers
+        */
+       if(PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
+       {
+               MessageBox("Incorrect MZ magic");
+               return FALSE;
+       }
+       if(PEDosHeader->e_lfanew == 0)
+       {
+               MessageBox("Invalid lfanew offset");
+               return 0;
+       }
+       if(*PEMagic != IMAGE_PE_MAGIC)
+       {
+               MessageBox("Incorrect PE magic");
+               return 0;
+       }
+       if(PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
+       {
+               MessageBox("Incorrect Architecture");
+               return 0;
+       }
+
+       /*
+        * Get header size and bump next_load_base
+        */
+       next_load_base += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
+       boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
+       boot_parameters.end_mem += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
+
+       /*
+        * Copy image sections into virtual section
+        */
+//  memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
+//  CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
+//     CurrentSize = 0;
+       for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+       {
+               /*
+                * Copy current section into current offset of virtual section
+                */
+               if (PESectionHeaders[Idx].Characteristics & 
+                       (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
+               {
+                       //memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
+                       //      (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
+                       //      PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
+
+                       //MessageBox("loading a section");
+                       fseek(pImage, PESectionHeaders[Idx].PointerToRawData);
+                       ReadFile(pImage, PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/, (void *)next_load_base);
+                       //printf("PointerToRawData: %x\n", PESectionHeaders[Idx].PointerToRawData);
+                       //printf("bytes at next_load_base: %x\n", *((unsigned long *)next_load_base));
+                       //getch();
+               }
+               else
+               {
+                       //memset(PESectionHeaders[Idx].VirtualAddress + DriverBase, 
+                       //      '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
+
+                       //MessageBox("zeroing a section");
+                       memset((void *)next_load_base, '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
+               }
+
+               PESectionHeaders[Idx].PointerToRawData = next_load_base - ImageBase;
+
+               next_load_base += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,      PEOptionalHeader->SectionAlignment);
+               boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,    PEOptionalHeader->SectionAlignment);
+               boot_parameters.end_mem += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,     PEOptionalHeader->SectionAlignment);
+
+               //DrawProgressBar((Idx * 100) / PEFileHeader->NumberOfSections);
+       }
+
+       return TRUE;
+}
\ No newline at end of file
diff --git a/freeldr/freeldr/rosboot.h b/freeldr/freeldr/rosboot.h
new file mode 100644 (file)
index 0000000..19b449e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  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.
+ */
+
+#ifndef __ROSBOOT_H
+#define __ROSBOOT_H
+
+#include "freeldr.h"
+#include "stdlib.h"
+#include "pe.h"
+
+#define PACKED __attribute__((packed))
+
+void   LoadAndBootReactOS(int nOSToBoot);
+void   ReactOSMemInit(void);
+void   ReactOSBootKernel(void);
+BOOL   ReactOSLoadPEImage(FILE *pImage);
+void   enable_a20(void);
+void   boot_ros(void);
+
+
+// WARNING:
+// This structure is prototyped here but allocated in ros.S
+// if you change this prototype make sure to update ros.S
+typedef struct
+{
+       /*
+        * Magic value (useless really)
+        */
+       unsigned int magic;
+
+       /*
+        * Cursor position
+        */
+       unsigned int cursorx;
+       unsigned int cursory;
+
+       /*
+        * Number of files (including the kernel) loaded
+        */
+       unsigned int nr_files;
+
+       /*
+        * Range of physical memory being used by the system
+        */
+       unsigned int start_mem;
+       unsigned int end_mem;
+
+       /*
+        * List of module lengths (terminated by a 0)
+        */
+       unsigned int module_lengths[64];
+
+       /*
+        * Kernel parameter string
+        */
+       char kernel_parameters[256];
+} boot_param PACKED;
+
+#endif // defined __ROSBOOT_H
\ No newline at end of file
diff --git a/freeldr/freeldr/stdlib.c b/freeldr/freeldr/stdlib.c
new file mode 100644 (file)
index 0000000..e90a7eb
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ *  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 "stdlib.h"
+
+/*
+ * print() - prints unformatted text to stdout
+ */
+void print(char *str)
+{
+       int     i;
+
+       for(i=0; i<strlen(str); i++)
+               putchar(str[i]);
+}
+
+/*
+ * convert_to_ascii() - converts a number to it's ascii equivalent
+ * from:
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1996   Erich Boleyn  <erich@uruk.org>
+ */
+char *convert_to_ascii(char *buf, int c, ...)
+{
+  unsigned long num = *((&c) + 1), mult = 10;
+  char *ptr = buf;
+
+  if (c == 'x')
+    mult = 16;
+
+  if ((num & 0x80000000uL) && c == 'd')
+    {
+      num = (~num)+1;
+      *(ptr++) = '-';
+      buf++;
+    }
+
+  do
+    {
+      int dig = num % mult;
+      *(ptr++) = ( (dig > 9) ? dig + 'a' - 10 : '0' + dig );
+    }
+  while (num /= mult);
+
+  /* reorder to correct direction!! */
+  {
+    char *ptr1 = ptr-1;
+    char *ptr2 = buf;
+    while (ptr1 > ptr2)
+      {
+       int c = *ptr1;
+       *ptr1 = *ptr2;
+       *ptr2 = c;
+       ptr1--;
+       ptr2++;
+      }
+  }
+
+  return ptr;
+}
+
+/*
+ * printf() - prints formatted text to stdout
+ * from:
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1996   Erich Boleyn  <erich@uruk.org>
+ */
+void printf(char *format, ... )
+{
+  int *dataptr = (int *) &format;
+  char c, *ptr, str[16];
+
+  dataptr++;
+
+  while ((c = *(format++)))
+    {
+      if (c != '%')
+       putchar(c);
+      else
+       switch (c = *(format++))
+         {
+         case 'd': case 'u': case 'x':
+           *convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
+
+           ptr = str;
+
+           while (*ptr)
+             putchar(*(ptr++));
+           break;
+
+         case 'c': putchar((*(dataptr++))&0xff); break;
+
+         case 's':
+           ptr = (char *)(*(dataptr++));
+
+           while ((c = *(ptr++)))
+             putchar(c);
+           break;
+         }
+    }
+}
+       
+int strlen(char *str)
+{
+       int     len;
+
+       for(len=0; str[len] != '\0'; len++);
+
+       return len;
+}
+
+char *itoa(int value, char *string, int radix)
+{
+       if(radix == 16)
+           *convert_to_ascii(string, 'x', value) = 0;
+       else
+           *convert_to_ascii(string, 'd', value) = 0;
+
+       return string;
+}
+
+int toupper(int c)
+{
+       if((c >= 'a') && (c <= 'z'))
+               c -= 32;
+
+       return c;
+}
+
+int tolower(int c)
+{
+       if((c >= 'A') && (c <= 'Z'))
+               c += 32;
+
+       return c;
+}
+
+int memcmp(const void *buf1, const void *buf2, size_t count)
+{
+       size_t          i;
+       const char      *buffer1 = buf1;
+       const char      *buffer2 = buf2;
+
+       for(i=0; i<count; i++)
+       {
+               if(buffer1[i] == buffer2[i])
+                       continue;
+               else
+                       return (buffer1[i] - buffer2[i]);
+       }
+
+       return 0;
+}
+
+void *memcpy(void *dest, const void *src, size_t count)
+{
+       size_t          i;
+       char            *buf1 = dest;
+       const char      *buf2 = src;
+
+       for(i=0; i<count; i++)
+               buf1[i] = buf2[i];
+
+       return dest;
+}
+
+void *memset(void *dest, int c, size_t count)
+{
+       size_t          i;
+       char            *buf1 = dest;
+
+       for(i=0; i<count; i++)
+               buf1[i] = c;
+
+       return dest;
+}
+
+char *strcpy(char *dest, char *src)
+{
+       char    *ret = dest;
+
+       while(*src)
+               *dest++ = *src++;
+       *dest = 0;
+
+       return ret;
+}
+
+char *strcat(char *dest, char *src)
+{
+       char    *ret = dest;
+
+       while(*dest)
+               dest++;
+
+       while(*src)
+               *dest++ = *src++;
+       *dest = 0;
+
+       return ret;
+}
+
+int strcmp(const char *string1, const char *string2)
+{
+       while(*string1 == *string2)
+       {
+               if(*string1 == 0)
+                       return 0;
+
+               string1++;
+               string2++;
+       }
+
+       return *(unsigned const char *)string1 - *(unsigned const char *)(string2);
+}
+
+int stricmp(const char *string1, const char *string2)
+{
+       while(tolower(*string1) == tolower(*string2))
+       {
+               if(*string1 == 0)
+                       return 0;
+
+               string1++;
+               string2++;
+       }
+
+       return (int)tolower(*string1) - (int)tolower(*string2);
+}
+
+char *fgets(char *string, int n, FILE *stream)
+{
+       int     i;
+
+       for(i=0; i<(n-1); i++)
+       {
+               if(feof(stream))
+               {
+                       i++;
+                       break;
+               }
+
+               ReadFile(stream, 1, string+i);
+
+               if(string[i] == '\n')
+               {
+                       i++;
+                       break;
+               }
+       }
+       string[i] = '\0';
+
+       return string;
+}
+
+int atoi(char *string)
+{
+       int             i, j;
+       int             base;
+       int             result = 0;
+       char    *str;
+
+       if((string[0] == '0') && (string[1] == 'x'))
+       {
+               base = 16;
+               str = string + 2;
+       }
+       else
+       {
+               base = 10;
+               str = string;
+       }
+
+       for(i=strlen(str)-1,j=1; i>=0; i--)
+       {
+               if((str[i] < '0') || (str[i] > '9'))
+                       break;
+
+               if(i == (strlen(str)-1))
+                       result += (str[i] - '0');
+               else
+               {
+                       result += (str[i] - '0') * (j * base);
+                       j *= base;
+               }
+       }
+
+       return result;
+}
diff --git a/freeldr/freeldr/stdlib.h b/freeldr/freeldr/stdlib.h
new file mode 100644 (file)
index 0000000..e222b5c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  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.
+ */
+
+#ifndef __STDLIB_H
+#define __STDLIB_H
+
+#include "fs.h"
+
+void   putchar(int ch);                // Implemented in asmcode.S
+void   clrscr(void);                   // Implemented in asmcode.S
+int            kbhit(void);                    // Implemented in asmcode.S
+int            getch(void);                    // Implemented in asmcode.S
+void   gotoxy(int x, int y);   // Implemented in asmcode.S
+int            getyear(void);                  // Implemented in asmcode.S
+int            getday(void);                   // Implemented in asmcode.S
+int            getmonth(void);                 // Implemented in asmcode.S
+int            gethour(void);                  // Implemented in asmcode.S
+int            getminute(void);                // Implemented in asmcode.S
+int            getsecond(void);                // Implemented in asmcode.S
+void   hidecursor(void);               // Implemented in asmcode.S
+void   showcursor(void);               // Implemented in asmcode.S
+int            wherex(void);                   // Implemented in asmcode.S
+int            wherey(void);                   // Implemented in asmcode.S
+
+int            strlen(char *str);
+char   *strcpy(char *dest, char *src);
+char   *strcat(char *dest, char *src);
+int            strcmp(const char *string1, const char *string2);
+int            stricmp(const char *string1, const char *string2);
+char   *itoa(int value, char *string, int radix);
+int            toupper(int c);
+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);
+int            atoi(char *string);
+
+
+void   print(char *str);
+void   printf(char *fmt, ...);
+
+int            biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
+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
diff --git a/freeldr/freeldr/tui.c b/freeldr/freeldr/tui.c
new file mode 100644 (file)
index 0000000..4ccf5b1
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ *  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 "stdlib.h"
+#include "tui.h"
+
+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] = "";
+
+void DrawBackdrop(void)
+{
+       // Fill in the backdrop
+       FillArea(0, 0, 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));
+       // Draw copyright
+       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 status bar
+       DrawStatusText("");
+
+       // Update the date & time
+       UpdateDateTime();
+}
+
+/*
+ * FillArea()
+ * This function assumes coordinates are zero-based
+ */
+void FillArea(int nLeft, int nTop, int nRight, int nBottom, char cFillChar, char cAttr /* Color Attributes */)
+{
+       char    *screen = (char *)SCREEN_MEM;
+       int             i, j;
+
+       for(i=nTop; i<=nBottom; i++)
+       {
+               for(j=nLeft; j<=nRight; j++)
+               {
+                       screen[((i*2)*nScreenWidth)+(j*2)] = cFillChar;
+                       screen[((i*2)*nScreenWidth)+(j*2)+1] = cAttr;
+               }
+       }
+}
+
+/*
+ * DrawShadow()
+ * This function assumes coordinates are zero-based
+ */
+void DrawShadow(int nLeft, int nTop, int nRight, int nBottom)
+{
+       char    *screen = (char *)SCREEN_MEM;
+       int             i;
+
+       // Shade the bottom of the area
+       if(nBottom < (nScreenHeight-1))
+       {
+               for(i=nLeft+2; i<=nRight; i++)
+                       screen[(((nBottom+1)*2)*nScreenWidth)+(i*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
+       }
+
+       // Shade the right of the area
+       if(nRight < (nScreenWidth-1))
+       {
+               for(i=nTop+1; i<=nBottom; i++)
+                       screen[((i*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
+       }
+       if(nRight+1 < (nScreenWidth-1))
+       {
+               for(i=nTop+1; i<=nBottom; i++)
+                       screen[((i*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
+       }
+
+       // Shade the bottom right corner
+       if((nRight < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
+               screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
+       if((nRight+1 < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
+               screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
+}
+
+/*
+ * DrawBox()
+ * This function assumes coordinates are one-based
+ */
+void DrawBox(int nLeft, int nTop, int nRight, int nBottom, int nVertStyle, int nHorzStyle, int bFill, int bShadow, char cAttr)
+{
+       char    cULCorner, cURCorner, cLLCorner, cLRCorner;
+       char    cHorz, cVert;
+
+       nLeft--;
+       nTop--;
+       nRight--;
+       nBottom--;
+
+       cHorz = nHorzStyle;
+       cVert = nVertStyle;
+       if(nHorzStyle == HORZ)
+       {
+               if(nVertStyle == VERT)
+               {
+                       cULCorner = UL;
+                       cURCorner = UR;
+                       cLLCorner = LL;
+                       cLRCorner = LR;
+               }
+               else // nVertStyle == D_VERT
+               {
+                       cULCorner = VD_UL;
+                       cURCorner = VD_UR;
+                       cLLCorner = VD_LL;
+                       cLRCorner = VD_LR;
+               }
+       }
+       else // nHorzStyle == D_HORZ
+       {
+               if(nVertStyl