--- /dev/null
+ 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.
--- /dev/null
+# 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
--- /dev/null
+; 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
+
--- /dev/null
+; 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
--- /dev/null
+nasm -o bootsect.bin -f bin bootsect.asm
+nasm -o btsect32.bin -f bin btsect32.asm
\ No newline at end of file
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+debug bootsect.bin < install.src
--- /dev/null
+w 100 0 0 1
+q
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+cd bootsect
+call make.bat
+cd..
+cd freeldr
+make
+copy freeldr.sys ..
+cd ..
--- /dev/null
+#
+# 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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:
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+
+#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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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