From afdf923c65707f267bf3088e9f7712f3d8d869cb Mon Sep 17 00:00:00 2001 From: Brian Palmer Date: Tue, 15 May 2001 03:50:25 +0000 Subject: [PATCH] Initial revision svn path=/trunk/; revision=1904 --- freeldr/COPYING | 339 ++++++++++ freeldr/FREELDR.INI | 130 ++++ freeldr/bootsect/BOOTSECT.ASM | 256 +++++++ freeldr/bootsect/BTSECT32.ASM | 351 ++++++++++ freeldr/bootsect/MAKE.BAT | 2 + freeldr/bootsect/bootsect.h | 35 + freeldr/bootsect/btsect32.h | 67 ++ freeldr/bootsect/c_data.c | 49 ++ freeldr/bootsect/install.bat | 1 + freeldr/bootsect/install.src | 2 + freeldr/bootsect/win2k-12.asm | 197 ++++++ freeldr/bootsect/win2k.asm | 174 +++++ freeldr/build.bat | 7 + freeldr/freeldr/Makefile | 89 +++ freeldr/freeldr/asmcode.S | 1177 +++++++++++++++++++++++++++++++++ freeldr/freeldr/asmcode.h | 57 ++ freeldr/freeldr/boot.S | 45 ++ freeldr/freeldr/freeldr.c | 734 ++++++++++++++++++++ freeldr/freeldr/freeldr.h | 82 +++ freeldr/freeldr/fs.c | 426 ++++++++++++ freeldr/freeldr/fs.h | 182 +++++ freeldr/freeldr/fs_fat.c | 541 +++++++++++++++ freeldr/freeldr/linux.c | 101 +++ freeldr/freeldr/linux.h | 27 + freeldr/freeldr/menu.c | 190 ++++++ freeldr/freeldr/menu.h | 27 + freeldr/freeldr/miscboot.c | 229 +++++++ freeldr/freeldr/miscboot.h | 29 + freeldr/freeldr/options.c | 395 +++++++++++ freeldr/freeldr/options.h | 31 + freeldr/freeldr/pe.h | 593 +++++++++++++++++ freeldr/freeldr/ros.S | 374 +++++++++++ freeldr/freeldr/rosboot.c | 390 +++++++++++ freeldr/freeldr/rosboot.h | 75 +++ freeldr/freeldr/stdlib.c | 306 +++++++++ freeldr/freeldr/stdlib.h | 74 +++ freeldr/freeldr/tui.c | 572 ++++++++++++++++ freeldr/freeldr/tui.h | 162 +++++ freeldr/install.bat | 5 + freeldr/notes.txt | 18 + 40 files changed, 8541 insertions(+) create mode 100644 freeldr/COPYING create mode 100644 freeldr/FREELDR.INI create mode 100644 freeldr/bootsect/BOOTSECT.ASM create mode 100644 freeldr/bootsect/BTSECT32.ASM create mode 100644 freeldr/bootsect/MAKE.BAT create mode 100644 freeldr/bootsect/bootsect.h create mode 100644 freeldr/bootsect/btsect32.h create mode 100644 freeldr/bootsect/c_data.c create mode 100644 freeldr/bootsect/install.bat create mode 100644 freeldr/bootsect/install.src create mode 100644 freeldr/bootsect/win2k-12.asm create mode 100644 freeldr/bootsect/win2k.asm create mode 100644 freeldr/build.bat create mode 100644 freeldr/freeldr/Makefile create mode 100644 freeldr/freeldr/asmcode.S create mode 100644 freeldr/freeldr/asmcode.h create mode 100644 freeldr/freeldr/boot.S create mode 100644 freeldr/freeldr/freeldr.c create mode 100644 freeldr/freeldr/freeldr.h create mode 100644 freeldr/freeldr/fs.c create mode 100644 freeldr/freeldr/fs.h create mode 100644 freeldr/freeldr/fs_fat.c create mode 100644 freeldr/freeldr/linux.c create mode 100644 freeldr/freeldr/linux.h create mode 100644 freeldr/freeldr/menu.c create mode 100644 freeldr/freeldr/menu.h create mode 100644 freeldr/freeldr/miscboot.c create mode 100644 freeldr/freeldr/miscboot.h create mode 100644 freeldr/freeldr/options.c create mode 100644 freeldr/freeldr/options.h create mode 100644 freeldr/freeldr/pe.h create mode 100644 freeldr/freeldr/ros.S create mode 100644 freeldr/freeldr/rosboot.c create mode 100644 freeldr/freeldr/rosboot.h create mode 100644 freeldr/freeldr/stdlib.c create mode 100644 freeldr/freeldr/stdlib.h create mode 100644 freeldr/freeldr/tui.c create mode 100644 freeldr/freeldr/tui.h create mode 100644 freeldr/install.bat create mode 100644 freeldr/notes.txt diff --git a/freeldr/COPYING b/freeldr/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/freeldr/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + 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.) + +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. + + 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. + + 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 + + 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. + + + Copyright (C) 19yy + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/freeldr/FREELDR.INI b/freeldr/FREELDR.INI new file mode 100644 index 00000000000..2a48ce11659 --- /dev/null +++ b/freeldr/FREELDR.INI @@ -0,0 +1,130 @@ +# FreeLoader by Brian Palmer +# FREELDR.INI - FreeLoader Initialization file +# +# Each line must be less than 1024 characters long +# and must be either a section heading (i.e. [section_name]) +# or a setting (i.e. name=value) or a blank line. +# Comments start with a '#' character. + +# Background colors can be any one of the following: +# Black +# Blue +# Green +# Cyan +# Red +# Magenta +# Brown +# Gray + +# Text colors can be any one of the background +# colors and any of the following: +# DarkGray +# LightBlue +# LightGreen +# LightCyan +# LightRed +# LightMagenta +# Yellow +# White + +# [FREELOADER] Section Commands: +# +# MessageBox - displays the specified text in a message box upon bootup +# MessageLine - adds a new line of text to a message box (must come before MessageBox command) +# TitleText - text that is displayed in the title box +# StatusBarColor - color of status bar's background +# StatusBarTextColor - color of status bar's text +# BackdropTextColor - color of the backdrop's fill +# BackdropColor - color of the backdrop's background +# BackdropFillStyle - backdrop fill style - can be Light, Medium, or Dark +# TitleBoxTextColor - title box text color +# TitleBoxColor - title box background color +# MessageBoxTextColor - message box text color +# MessageBoxColor - message box background color +# MenuTextColor - menu text color +# MenuColor - menu color +# TextColor - normal text color +# SelectedTextColor - selected text color +# SelectedColor - selected text background color +# TimeOut - sets the timeout (in seconds) before the first OS listed gets booted automagically + +# [OS-General] Section Commands: +# +# BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive +# BootDrive - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk +# BootPartition - sets the boot partition + +# [BootSector OSType] Section Commands: +# +# BootSector - sets the filename of the bootsector to be loaded + +# [ReactOS OSType] Section Commands: +# +# Options - sets the command line options for the kernel being booted +# Kernel - sets the kernel filename +# Driver - sets the name of one or more drivers to be loaded (one entry per driver) + + + +[FREELOADER] +MessageLine=Welcome to FreeLoader! +MessageLine=Copyright (c) 2000 by Brian Palmer +MessageLine= +MessageBox=Edit your FREELDR.INI file to change your boot settings. +TitleText=Boot Menu +StatusBarColor=Cyan +StatusBarTextColor=Black +BackdropTextColor=White +BackdropColor=Blue +BackdropFillStyle=Medium +TitleBoxTextColor=White +TitleBoxColor=Red +MessageBoxTextColor=White +MessageBoxColor=Blue +MenuTextColor=White +MenuColor=Blue +TextColor=Yellow +SelectedTextColor=Black +SelectedColor=Gray +#OS=ReactOS +#OS=ReactOS (Debug) +#OS=Linux +OS=3« Floppy (A:) +OS=Microsoft Windows (C:) +OS=Drive D: +#TimeOut=0 + +#[ReactOS] +#BootType=ReactOS +#BootDrive=0 +#Options=/DEBUGPORT=SCREEN +#Kernel=\NTOSKRNL.EXE +#Driver=\DRIVERS\IDE.SYS +#Driver=\DRIVERS\VFATFS.SYS + +#[ReactOS (Debug)] +#BootType=ReactOS +#BootDrive=0 +#Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200 +#Kernel=\NTOSKRNL.EXE +#Driver=\DRIVERS\IDE.SYS +#Driver=\DRIVERS\VFATFS.SYS + +#[Linux] +# Linux boot type not implemented yet +#BootType=Partition +#BootDrive=0x80 +#BootPartition=2 + +[3« Floppy (A:)] +BootType=Drive +BootDrive=0 + +[Microsoft Windows (C:)] +BootType=Drive +BootDrive=0x80 + +[Drive D:] +BootType=Partition +BootDrive=0x81 +BootPartition=1 diff --git a/freeldr/bootsect/BOOTSECT.ASM b/freeldr/bootsect/BOOTSECT.ASM new file mode 100644 index 00000000000..2478e4f997d --- /dev/null +++ b/freeldr/bootsect/BOOTSECT.ASM @@ -0,0 +1,256 @@ +; BOOTSECT.ASM +; FAT12/16 Boot Sector +; Copyright (c) 1998 Brian Palmer + +org 7c00h + +segment .text + +bits 16 + +start: + jmp short main + nop + +OEMName db 'FreeLDR!' +BytesPerSector dw 512 +SectsPerCluster db 1 +ReservedSectors dw 1 +NumberOfFats db 2 +MaxRootEntries dw 512 +TotalSectors dw 2880 +MediaDescriptor db 0f0h +SectorsPerFat dw 9 +SectorsPerTrack dw 18 +NumberOfHeads dw 2 +HiddenSectors dd 0 +TotalSectorsBig dd 0 +BootDrive db 0 +Reserved db 0 +ExtendSig db 29h +SerialNumber dd 00000000h +VolumeLabel db 'FreeLoader!' +FileSystem db 'FAT12 ' + +main: + cli + cld + xor ax,ax + mov ss,ax + mov sp,7c00h ; Setup a stack + mov ax,cs ; Setup segment registers + mov ds,ax ; Make DS correct + mov es,ax ; Make ES correct + + + sti ; Enable ints now + mov [BootDrive],dl ; Save the boot drive + xor ax,ax ; Zero out AX + + ; Reset disk controller + int 13h + jnc Continue1 + jmp BadBoot ; Reset failed... + +Continue1: + ; Now we must find our way to the first sector of the root directory + xor ax,ax + xor cx,cx + mov al,[NumberOfFats] ; Number of fats + mul WORD [SectorsPerFat] ; Times sectors per fat + add ax,WORD [HiddenSectors] + adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors + add ax,[ReservedSectors] ; Add the number of reserved sectors + adc dx,cx ; Add carry bit + push ax ; Store it on the stack + push dx ; Save 32-bit logical start sector + push ax + push dx ; Save it for later use also + ; DX:AX now has the number of the starting sector of the root directory + + ; Now calculate the size of the root directory + mov ax,0020h ; Size of dir entry + mul WORD [MaxRootEntries] ; Times the number of entries + mov bx,[BytesPerSector] + add ax,bx + dec ax + div bx ; Divided by the size of a sector + ; AX now has the number of root directory sectors + + xchg ax,cx ; Now CX has number of sectors + pop dx + pop ax ; Restore logical sector start + push cx ; Save for later use + mov bx,7c0h ; We will load the root directory + add bx,20h ; Right after the boot sector in memory + mov es,bx + xor bx,bx ; We will load it to [0000:7e00h] + call ReadSectors ; Read the sectors + jnc Continue2 ; BadBoot on error + jmp BadBoot +Continue2: + + + ; Now we have to find our way through the root directory to + ; The OSLOADER.SYS file + mov bx,[MaxRootEntries]; Search entire root directory + mov ax,7e0h ; We loaded at 07e0:0000 + mov es,ax + xor di,di + mov si,filename + mov cx,11 + rep cmpsb ; Compare filenames + jz FoundFile ; If same we found it + dec bx + jnz FindFile + jmp ErrBoot + +FindFile: + mov ax,es ; We didn't find it in the previous dir entry + add ax,2 ; So lets move to the next one + mov es,ax ; And search again + xor di,di + mov si,filename + mov cx,11 + rep cmpsb ; Compare filenames + jz FoundFile ; If same we found it + dec bx ; Keep searching till we run out of dir entries + jnz FindFile ; Last entry? + jmp ErrBoot + +FoundFile: + xor di,di ; ES:DI has dir entry + xor dx,dx + mov ax,WORD [es:di+1ah] ; Get start cluster + dec ax + dec ax + xor ch,ch + mov cl,BYTE [SectsPerCluster] ; Times sectors per cluster + mul cx + pop cx ; Get number of sectors for root dir + add ax,cx + adc dx,0 + pop cx ; Get logical start sector of + pop bx ; Root directory + add ax,bx ; Now we have DX:AX with the logical start + adc dx,cx ; Sector of OSLOADER.SYS + push ax + push dx + mov ax,WORD [es:di+1ch] + mov dx,WORD [es:di+1eh] + mov bx,[BytesPerSector] + dec bx + add ax,bx + adc dx,0 + div WORD [BytesPerSector] + xchg ax,cx ; Now CX has number of sectors of OSLOADER.SYS + pop dx + pop ax + mov bx,800h + mov es,bx + xor bx,bx ; Load ROSLDR at 0000:8000h + call ReadSectors ; Load it + jc BadBoot + mov dl,[BootDrive] + xor ax,ax + push ax + mov ax,8000h + push ax ; We will do a far return to 0000:8000h + retf ; Transfer control to ROSLDR + + + +; Reads logical sectors into [ES:BX] +; DX:AX has logical sector number to read +; CX has number of sectors to read +; CarryFlag set on error +ReadSectors: + push ax + push dx + push cx + xchg ax,cx + xchg ax,dx + xor dx,dx + div WORD [SectorsPerTrack] + xchg ax,cx + div WORD [SectorsPerTrack] ; Divide logical by SectorsPerTrack + inc dx ; Sectors numbering starts at 1 not 0 + xchg cx,dx + div WORD [NumberOfHeads] ; Number of heads + mov dh,dl ; Head to DH, drive to DL + mov dl,[BootDrive] ; Drive number + mov ch,al ; Cylinder in CX + ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits + ror ah,1 ; in CL shifted to bits 6 & 7 + or cl,ah ; Or with sector number + mov ax,513 + int 13h ; DISK - READ SECTORS INTO MEMORY + ; AL = number of sectors to read, CH = track, CL = sector + ; DH = head, DL = drive, ES:BX -> buffer to fill + ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read + pop cx + pop dx + pop ax + jc ReadFail + inc ax ;Increment Sector to Read + jnz NoCarry + inc dx + + +NoCarry: + push bx + mov bx,es + add bx,20h + mov es,bx + pop bx + ; Increment read buffer for next sector + loop ReadSectors ; Read next sector + + +ReadFail: + ret + + + +; Displays a bad boot message +; And reboots +BadBoot: + mov si,msgDiskError ; Bad boot disk message + call PutChars ; Display it + mov si,msgAnyKey ; Press any key message + call PutChars ; Display it + + jmp Reboot + +; Displays an error message +; And reboots +ErrBoot: + mov si,msgFreeLdr ; FreeLdr not found message + call PutChars ; Display it + mov si,msgAnyKey ; Press any key message + call PutChars ; Display it + +Reboot: + xor ax,ax + int 16h ; Wait for a keypress + int 19h ; Reboot + +PutChars: + lodsb + or al,al + jz short Done + mov ah,0eh + mov bx,07h + int 10h + jmp short PutChars +Done: + retn + +msgDiskError db 'Disk error',0dh,0ah,0 +msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0 +msgAnyKey db 'Press any key to continue.',0dh,0ah,0 +filename db 'FREELDR SYS' + + times 510-($-$$) db 0 ; Pad to 510 bytes + dw 0aa55h ; BootSector signature + diff --git a/freeldr/bootsect/BTSECT32.ASM b/freeldr/bootsect/BTSECT32.ASM new file mode 100644 index 00000000000..092769e87c0 --- /dev/null +++ b/freeldr/bootsect/BTSECT32.ASM @@ -0,0 +1,351 @@ +; BTSECT32.ASM +; FAT32 Boot Sector +; Copyright (c) 1998, 2000 Brian Palmer + +org 7c00h + +segment .text + +bits 16 + +start: + jmp short main + nop + +OEMName db 'FreeLDR!' +BytesPerSector dw 512 +SectsPerCluster db 1 +ReservedSectors dw 1 +NumberOfFats db 2 +MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes +TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes +MediaDescriptor db 0f8h +SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes +SectorsPerTrack dw 18 +NumberOfHeads dw 2 +HiddenSectors dd 0 +TotalSectorsBig dd 0 +; FAT32 Inserted Info +SectorsPerFatBig dd 0 +ExtendedFlags dw 0 +FSVersion dw 0 +RootDirStartCluster dd 0 +FSInfoSector dw 0 +BackupBootSector dw 6 +Reserved1 times 12 db 0 +; End FAT32 Inserted Info +BootDrive db 0 +Reserved db 0 +ExtendSig db 29h +SerialNumber dd 00000000h +VolumeLabel db 'FreeLoader!' +FileSystem db 'FAT32 ' + +main: + cli + cld + xor ax,ax + mov ss,ax + mov sp,7c00h ; Setup a stack + mov ax,cs ; Setup segment registers + mov ds,ax ; Make DS correct + mov es,ax ; Make ES correct + + + sti ; Enable ints now + mov [BootDrive],dl ; Save the boot drive + xor ax,ax ; Zero out AX + + ; Reset disk controller + int 13h + jnc Continue + jmp BadBoot ; Reset failed... + +Continue: + ; First we have to load our extra boot code at + ; sector 14 into memory at [0000:7e00h] + xor dx,dx + mov ax,0eh + add ax,WORD [HiddenSectors] + adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors + mov cx,1 + mov bx,7e0h + mov es,bx ; Read sector to [0000:7e00h] + xor bx,bx + call ReadSectors + jnc Continue1 + jmp BadBoot + + +Continue1: + ; Now we must get the first cluster of the root directory + mov eax,DWORD [RootDirStartCluster] + cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain + jb Continue2 ; If not continue, if so BadBoot + jmp ErrBoot +Continue2: + mov bx,800h + mov es,bx ; Read cluster to [0000:8000h] + call ReadCluster ; Read the cluster + + + ; Now we have to find our way through the root directory to + ; The OSLOADER.SYS file + xor bx,bx + mov bl,[SectsPerCluster] + shl bx,4 ; BX = BX * 512 / 32 + mov ax,800h ; We loaded at 0800:0000 + mov es,ax + xor di,di + mov si,filename + mov cx,11 + rep cmpsb ; Compare filenames + jz FoundFile ; If same we found it + dec bx + jnz FindFile + jmp ErrBoot + +FindFile: + mov ax,es ; We didn't find it in the previous dir entry + add ax,2 ; So lets move to the next one + mov es,ax ; And search again + xor di,di + mov si,filename + mov cx,11 + rep cmpsb ; Compare filenames + jz FoundFile ; If same we found it + dec bx ; Keep searching till we run out of dir entries + jnz FindFile ; Last entry? + + ; Get the next root dir cluster and try again until we run out of clusters + mov eax,DWORD [RootDirStartCluster] + call GetFatEntry + mov [RootDirStartCluster],eax + jmp Continue1 + +FoundFile: + xor di,di ; ES:DI has dir entry + xor dx,dx + mov ax,WORD [es:di+14h] ; Get start cluster high word + shl eax,16 + mov ax,WORD [es:di+1ah] ; Get start cluster low word + + mov bx,800h + mov es,bx + +FoundFile2: + cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain + jae FoundFile3 ; If so continue, if not then read then next one + push eax + xor bx,bx ; Load ROSLDR starting at 0000:8000h + push es + call ReadCluster + pop es + + xor bx,bx + mov bl,[SectsPerCluster] + shl bx,5 ; BX = BX * 512 / 16 + mov ax,es ; Increment the load address by + add ax,bx ; The size of a cluster + mov es,ax + + pop eax + push es + call GetFatEntry ; Get the next entry + pop es + + jmp FoundFile2 ; Load the next cluster (if any) + +FoundFile3: + mov dl,[BootDrive] + xor ax,ax + push ax + mov ax,8000h + push ax ; We will do a far return to 0000:8000h + retf ; Transfer control to ROSLDR + + + +; Reads logical sectors into [ES:BX] +; DX:AX has logical sector number to read +; CX has number of sectors to read +; CarryFlag set on error +ReadSectors: + push ax + push dx + push cx + xchg ax,cx + xchg ax,dx + xor dx,dx + div WORD [SectorsPerTrack] + xchg ax,cx + div WORD [SectorsPerTrack] ; Divide logical by SectorsPerTrack + inc dx ; Sectors numbering starts at 1 not 0 + xchg cx,dx + div WORD [NumberOfHeads] ; Number of heads + mov dh,dl ; Head to DH, drive to DL + mov dl,[BootDrive] ; Drive number + mov ch,al ; Cylinder in CX + ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits + ror ah,1 ; in CL shifted to bits 6 & 7 + or cl,ah ; Or with sector number + mov ax,513 + int 13h ; DISK - READ SECTORS INTO MEMORY + ; AL = number of sectors to read, CH = track, CL = sector + ; DH = head, DL = drive, ES:BX -> buffer to fill + ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read + pop cx + pop dx + pop ax + jc ReadFail + inc ax ;Increment Sector to Read + jnz NoCarry + inc dx + + +NoCarry: + push bx + mov bx,es + add bx,20h + mov es,bx + pop bx + ; Increment read buffer for next sector + loop ReadSectors ; Read next sector + + +ReadFail: + ret + + + + +; Displays a bad boot message +; And reboots +BadBoot: + mov si,msgDiskError ; Bad boot disk message + call PutChars ; Display it + mov si,msgAnyKey ; Press any key message + call PutChars ; Display it + + jmp Reboot + +; Displays an error message +; And reboots +ErrBoot: + mov si,msgFreeLdr ; FreeLdr not found message + call PutChars ; Display it + mov si,msgAnyKey ; Press any key message + call PutChars ; Display it + +Reboot: + xor ax,ax + int 16h ; Wait for a keypress + int 19h ; Reboot + +PutChars: + lodsb + or al,al + jz short Done + mov ah,0eh + mov bx,07h + int 10h + jmp short PutChars +Done: + retn + +msgDiskError db 'Disk error',0dh,0ah,0 +msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0 +msgAnyKey db 'Press any key to continue.',0dh,0ah,0 +filename db 'FREELDR SYS' + + times 510-($-$$) db 0 ; Pad to 510 bytes + dw 0aa55h ; BootSector signature + + +; End of bootsector +; +; Now starts the extra boot code that we will store +; at sector 14 on a FAT32 volume +; +; To remain multi-boot compatible with other operating +; systems we must not overwrite anything other than +; the bootsector which means we will have to use +; a different sector like 14 to store our extra boot code +; +; Note: Win2k uses sector 12 for this purpose + + +; Returns the FAT entry for a given cluster number +; On entry EAX has cluster number +; On return EAX has FAT entry for that cluster +GetFatEntry: + + shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes) + mov ecx,eax ; Save this for later in ECX + xor edx,edx + movzx ebx,WORD [BytesPerSector] + push ebx + div ebx ; FAT Sector Number = EAX / BytesPerSector + movzx ebx,WORD [ReservedSectors] + add eax,ebx ; FAT Sector Number += ReservedSectors + movzx ebx,WORD [HiddenSectors] + add eax,ebx ; FAT Sector Number += HiddenSectors + pop ebx + dec ebx + and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector + ; EAX holds logical FAT sector number + ; ECX holds FAT entry offset + push ecx + ror eax,16 + mov dx,ax + ror eax,16 + ; DX:AX holds logical FAT sector number + mov bx,7000h + mov es,bx + xor bx,bx ; We will load it to [7000:0000h] + mov cx,1 + call ReadSectors + jnc GetFatEntry1 + jmp BadBoot +GetFatEntry1: + mov bx,7000h + mov es,bx + pop ecx + mov eax,DWORD [es:ecx] ; Get FAT entry + and eax,0fffffffh ; Mask off reserved bits + + ret + + +; Reads cluster number in EAX into [ES:0000] +ReadCluster: + ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors; + + dec eax + dec eax + xor edx,edx + movzx ebx,BYTE [SectsPerCluster] + mul ebx + push eax + xor edx,edx + movzx eax,BYTE [NumberOfFats] + mul DWORD [SectorsPerFatBig] + movzx ebx,WORD [ReservedSectors] + add eax,ebx + add eax,DWORD [HiddenSectors] + pop ebx + add eax,ebx ; EAX now contains the logical sector number of the cluster + ror eax,16 + mov dx,ax + ror eax,16 + xor bx,bx ; We will load it to [ES:0000], ES loaded before function call + movzx cx,BYTE [SectsPerCluster] + call ReadSectors + jnc ReadCluster1 + jmp BadBoot + +ReadCluster1: + ret + + times 1022-($-$$) db 0 ; Pad to 1022 bytes + dw 0aa55h ; BootSector signature diff --git a/freeldr/bootsect/MAKE.BAT b/freeldr/bootsect/MAKE.BAT new file mode 100644 index 00000000000..35efa95daa3 --- /dev/null +++ b/freeldr/bootsect/MAKE.BAT @@ -0,0 +1,2 @@ +nasm -o bootsect.bin -f bin bootsect.asm +nasm -o btsect32.bin -f bin btsect32.asm \ No newline at end of file diff --git a/freeldr/bootsect/bootsect.h b/freeldr/bootsect/bootsect.h new file mode 100644 index 00000000000..ef020f33148 --- /dev/null +++ b/freeldr/bootsect/bootsect.h @@ -0,0 +1,35 @@ +unsigned char data[] = { + +0xeb, 0x3c, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00, +0x02, 0x00, 0x02, 0x40, 0x0b, 0xf0, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c, +0x6f, 0x61, 0x64, 0x65, 0x72, 0x21, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc, +0x31, 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16, +0x24, 0x7c, 0x31, 0xc0, 0xcd, 0x13, 0x73, 0x03, 0xe9, 0x0b, 0x01, 0x31, 0xc0, 0x31, 0xc9, 0xa0, +0x10, 0x7c, 0xf7, 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13, 0x16, 0x1e, 0x7c, 0x03, 0x06, +0x0e, 0x7c, 0x11, 0xca, 0x50, 0x52, 0x50, 0x52, 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b, +0x1e, 0x0b, 0x7c, 0x01, 0xd8, 0x48, 0xf7, 0xf3, 0x91, 0x5a, 0x58, 0x51, 0xbb, 0xc0, 0x07, 0x81, +0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x8c, 0x00, 0x73, 0x03, 0xe9, 0xc7, 0x00, 0x8b, +0x1e, 0x11, 0x7c, 0xb8, 0xe0, 0x07, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00, +0xf3, 0xa6, 0x74, 0x1f, 0x4b, 0x75, 0x03, 0xe9, 0xbb, 0x00, 0x8c, 0xc0, 0x05, 0x02, 0x00, 0x8e, +0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x06, 0x4b, 0x75, 0xea, +0xe9, 0xa2, 0x00, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x1a, 0x48, 0x48, 0x30, 0xed, 0x8a, +0x0e, 0x0d, 0x7c, 0xf7, 0xe1, 0x59, 0x01, 0xc8, 0x81, 0xd2, 0x00, 0x00, 0x59, 0x5b, 0x01, 0xd8, +0x11, 0xca, 0x50, 0x52, 0x26, 0x8b, 0x45, 0x1c, 0x26, 0x8b, 0x55, 0x1e, 0x8b, 0x1e, 0x0b, 0x7c, +0x4b, 0x01, 0xd8, 0x81, 0xd2, 0x00, 0x00, 0xf7, 0x36, 0x0b, 0x7c, 0x91, 0x5a, 0x58, 0xbb, 0x00, +0x08, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x0e, 0x00, 0x72, 0x4c, 0x8a, 0x16, 0x24, 0x7c, 0x31, 0xc0, +0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91, 0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18, +0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7, 0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a, +0x16, 0x24, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08, 0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13, +0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53, 0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00, +0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0x96, 0x7d, 0xe8, 0x1b, 0x00, 0xbe, 0xbb, 0x7d, 0xe8, +0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xa3, 0x7d, 0xe8, 0x0c, 0x00, 0xbe, 0xbb, 0x7d, 0xe8, 0x06, +0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0, 0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, +0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, +0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e, +0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, +0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, +0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x20, +0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa +}; \ No newline at end of file diff --git a/freeldr/bootsect/btsect32.h b/freeldr/bootsect/btsect32.h new file mode 100644 index 00000000000..57dc6479c38 --- /dev/null +++ b/freeldr/bootsect/btsect32.h @@ -0,0 +1,67 @@ +unsigned char data[] = { + +0xeb, 0x58, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00, +0x02, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x65, +0x72, 0x21, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xd0, +0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16, 0x40, 0x7c, 0x31, 0xc0, +0xcd, 0x13, 0x73, 0x03, 0xe9, 0x05, 0x01, 0x31, 0xd2, 0xb8, 0x0e, 0x00, 0x03, 0x06, 0x1c, 0x7c, +0x13, 0x16, 0x1e, 0x7c, 0xb9, 0x01, 0x00, 0xbb, 0xe0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0xab, +0x00, 0x73, 0x03, 0xe9, 0xe6, 0x00, 0x66, 0xa1, 0x2c, 0x7c, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f, +0x72, 0x03, 0xe9, 0xe6, 0x00, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0xe8, 0xb2, 0x01, 0x31, 0xdb, 0x8a, +0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x04, 0xb8, 0x00, 0x08, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d, +0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x2a, 0x4b, 0x75, 0x03, 0xe9, 0xbe, 0x00, 0x8c, 0xc0, 0x05, +0x02, 0x00, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x11, +0x4b, 0x75, 0xea, 0x66, 0xa1, 0x2c, 0x7c, 0xe8, 0x16, 0x01, 0x66, 0xa3, 0x2c, 0x7c, 0xe9, 0xa5, +0xff, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x14, 0x66, 0xc1, 0xe0, 0x10, 0x26, 0x8b, 0x45, +0x1a, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f, 0x73, 0x22, 0x66, 0x50, +0x31, 0xdb, 0x06, 0xe8, 0x49, 0x01, 0x07, 0x31, 0xdb, 0x8a, 0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x05, +0x8c, 0xc0, 0x01, 0xd8, 0x8e, 0xc0, 0x66, 0x58, 0x06, 0xe8, 0xd4, 0x00, 0x07, 0xe9, 0xd6, 0xff, +0x8a, 0x16, 0x40, 0x7c, 0x31, 0xc0, 0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91, +0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7, +0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a, 0x16, 0x40, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08, +0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53, +0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0xac, 0x7d, 0xe8, +0x1b, 0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xb9, 0x7d, 0xe8, 0x0c, +0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x06, 0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0, +0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b, +0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, +0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, +0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, +0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52, +0x45, 0x45, 0x4c, 0x44, 0x52, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, +0x66, 0xc1, 0xe0, 0x02, 0x66, 0x89, 0xc1, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb7, 0x1e, 0x0b, 0x7c, +0x66, 0x53, 0x66, 0xf7, 0xf3, 0x66, 0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x0f, +0xb7, 0x1e, 0x1c, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x5b, 0x66, 0x4b, 0x66, 0x21, 0xd9, 0x66, 0x51, +0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, +0xdb, 0xb9, 0x01, 0x00, 0xe8, 0xf5, 0xfe, 0x73, 0x03, 0xe9, 0x30, 0xff, 0xbb, 0x00, 0x70, 0x8e, +0xc3, 0x66, 0x59, 0x26, 0x66, 0x67, 0x8b, 0x01, 0x66, 0x25, 0xff, 0xff, 0xff, 0x0f, 0xc3, 0x66, +0x48, 0x66, 0x48, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x1e, 0x0d, 0x7c, 0x66, 0xf7, 0xe3, 0x66, +0x50, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x06, 0x10, 0x7c, 0x66, 0xf7, 0x26, 0x24, 0x7c, 0x66, +0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x03, 0x06, 0x1c, 0x7c, 0x66, 0x5b, 0x66, +0x01, 0xd8, 0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0x31, 0xdb, 0x0f, 0xb6, +0x0e, 0x0d, 0x7c, 0xe8, 0x96, 0xfe, 0x73, 0x03, 0xe9, 0xd1, 0xfe, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa +}; \ No newline at end of file diff --git a/freeldr/bootsect/c_data.c b/freeldr/bootsect/c_data.c new file mode 100644 index 00000000000..963df42e595 --- /dev/null +++ b/freeldr/bootsect/c_data.c @@ -0,0 +1,49 @@ +#include + +char in_filename[260]; +char out_filename[260]; +FILE *in; +FILE *out; + +int main(void) +{ + unsigned char ch; + int cnt = 0; + + printf("Enter data filename: "); + scanf("%s", in_filename); + printf("Enter output filename: "); + scanf("%s", out_filename); + + if ((in = fopen(in_filename, "rb")) == NULL) + { + printf("Couldn't open data file.\n"); + return 0; + } + if ((out = fopen(out_filename, "wb")) == NULL) + { + printf("Couldn't open output file.\n"); + return 0; + } + + fprintf(out, "unsigned char data[] = {\n"); + + ch = fgetc(in); + while (!feof(in)) + { + if (cnt != 0) + fprintf(out, ", "); + if (!(cnt % 16)) + fprintf(out, "\n"); + fprintf(out, "0x%02x", (int)ch); + cnt++; + ch = fgetc(in); + } + + fprintf(out, "\n};"); + + fclose(in); + fclose(out); + + return 0; +} \ No newline at end of file diff --git a/freeldr/bootsect/install.bat b/freeldr/bootsect/install.bat new file mode 100644 index 00000000000..32e2f3cd2dc --- /dev/null +++ b/freeldr/bootsect/install.bat @@ -0,0 +1 @@ +debug bootsect.bin < install.src diff --git a/freeldr/bootsect/install.src b/freeldr/bootsect/install.src new file mode 100644 index 00000000000..86675020d00 --- /dev/null +++ b/freeldr/bootsect/install.src @@ -0,0 +1,2 @@ +w 100 0 0 1 +q diff --git a/freeldr/bootsect/win2k-12.asm b/freeldr/bootsect/win2k-12.asm new file mode 100644 index 00000000000..d68a6fba4f2 --- /dev/null +++ b/freeldr/bootsect/win2k-12.asm @@ -0,0 +1,197 @@ +00008000 660FB64610 movzx eax,byte [bp+NumberOfFats] +00008005 668B4E24 mov ecx,[bp+SectorsPerFatBig] +00008009 66F7E1 mul ecx +0000800C 6603461C add eax,[bp+HiddenSectors] +00008010 660FB7560E movzx edx,word [bp+ReservedSectors] +00008015 6603C2 add eax,edx +00008018 668946FC mov [bp-0x4],eax +0000801C 66C746F4FFFFFFFF mov dword [bp-0xc],0xffffffff +00008024 668B462C mov eax,[bp+RootDirStartCluster] +00008028 6683F802 cmp eax,byte +0x2 +0000802C 0F82A6FC jc near 0x7cd6 +00008030 663DF8FFFF0F cmp eax,0xffffff8 +00008036 0F839CFC jnc near 0x7cd6 +0000803A 6650 push eax +0000803C 6683E802 sub eax,byte +0x2 +00008040 660FB65E0D movzx ebx,byte [bp+SectsPerCluster] +00008045 8BF3 mov si,bx +00008047 66F7E3 mul ebx +0000804A 660346FC add eax,[bp-0x4] +0000804E BB0082 mov bx,0x8200 +00008051 8BFB mov di,bx +00008053 B90100 mov cx,0x1 +00008056 E887FC call 0x7ce0 +00008059 382D cmp [di],ch +0000805B 741E jz 0x807b +0000805D B10B mov cl,0xb +0000805F 56 push si +00008060 BE707D mov si,0x7d70 +00008063 F3A6 repe cmpsb +00008065 5E pop si +00008066 741B jz 0x8083 +00008068 03F9 add di,cx +0000806A 83C715 add di,byte +0x15 +0000806D 3BFB cmp di,bx +0000806F 72E8 jc 0x8059 +00008071 4E dec si +00008072 75DA jnz 0x804e +00008074 6658 pop eax +00008076 E86500 call 0x80de +00008079 72BF jc 0x803a +0000807B 83C404 add sp,byte +0x4 +0000807E E955FC jmp 0x7cd6 +00008081 0020 add [bx+si],ah +00008083 83C404 add sp,byte +0x4 +00008086 8B7509 mov si,[di+0x9] +00008089 8B7D0F mov di,[di+0xf] +0000808C 8BC6 mov ax,si +0000808E 66C1E010 shl eax,0x10 +00008092 8BC7 mov ax,di +00008094 6683F802 cmp eax,byte +0x2 +00008098 0F823AFC jc near 0x7cd6 +0000809C 663DF8FFFF0F cmp eax,0xffffff8 +000080A2 0F8330FC jnc near 0x7cd6 +000080A6 6650 push eax +000080A8 6683E802 sub eax,byte +0x2 +000080AC 660FB64E0D movzx ecx,byte [bp+0xd] +000080B1 66F7E1 mul ecx +000080B4 660346FC add eax,[bp-0x4] +000080B8 BB0000 mov bx,0x0 +000080BB 06 push es +000080BC 8E068180 mov es,[0x8081] +000080C0 E81DFC call 0x7ce0 +000080C3 07 pop es +000080C4 6658 pop eax +000080C6 C1EB04 shr bx,0x4 +000080C9 011E8180 add [0x8081],bx +000080CD E80E00 call 0x80de +000080D0 0F830200 jnc near 0x80d6 +000080D4 72D0 jc 0x80a6 +000080D6 8A5640 mov dl,[bp+0x40] +000080D9 EA00000020 jmp 0x2000:0x0 +000080DE 66C1E002 shl eax,0x2 +000080E2 E81100 call 0x80f6 +000080E5 26668B01 mov eax,[es:bx+di] +000080E9 6625FFFFFF0F and eax,0xfffffff +000080EF 663DF8FFFF0F cmp eax,0xffffff8 +000080F5 C3 ret +000080F6 BF007E mov di,0x7e00 +000080F9 660FB74E0B movzx ecx,word [bp+0xb] +000080FE 6633D2 xor edx,edx +00008101 66F7F1 div ecx +00008104 663B46F4 cmp eax,[bp-0xc] +00008108 743A jz 0x8144 +0000810A 668946F4 mov [bp-0xc],eax +0000810E 6603461C add eax,[bp+0x1c] +00008112 660FB74E0E movzx ecx,word [bp+0xe] +00008117 6603C1 add eax,ecx +0000811A 660FB75E28 movzx ebx,word [bp+0x28] +0000811F 83E30F and bx,byte +0xf +00008122 7416 jz 0x813a +00008124 3A5E10 cmp bl,[bp+0x10] +00008127 0F83ABFB jnc near 0x7cd6 +0000812B 52 push dx +0000812C 668BC8 mov ecx,eax +0000812F 668B4624 mov eax,[bp+0x24] +00008133 66F7E3 mul ebx +00008136 6603C1 add eax,ecx +00008139 5A pop dx +0000813A 52 push dx +0000813B 8BDF mov bx,di +0000813D B90100 mov cx,0x1 +00008140 E89DFB call 0x7ce0 +00008143 5A pop dx +00008144 8BDA mov bx,dx +00008146 C3 ret +00008147 0000 add [bx+si],al +00008149 0000 add [bx+si],al +0000814B 0000 add [bx+si],al +0000814D 0000 add [bx+si],al +0000814F 0000 add [bx+si],al +00008151 0000 add [bx+si],al +00008153 0000 add [bx+si],al +00008155 0000 add [bx+si],al +00008157 0000 add [bx+si],al +00008159 0000 add [bx+si],al +0000815B 0000 add [bx+si],al +0000815D 0000 add [bx+si],al +0000815F 0000 add [bx+si],al +00008161 0000 add [bx+si],al +00008163 0000 add [bx+si],al +00008165 0000 add [bx+si],al +00008167 0000 add [bx+si],al +00008169 0000 add [bx+si],al +0000816B 0000 add [bx+si],al +0000816D 0000 add [bx+si],al +0000816F 0000 add [bx+si],al +00008171 0000 add [bx+si],al +00008173 0000 add [bx+si],al +00008175 0000 add [bx+si],al +00008177 0000 add [bx+si],al +00008179 0000 add [bx+si],al +0000817B 0000 add [bx+si],al +0000817D 0000 add [bx+si],al +0000817F 0000 add [bx+si],al +00008181 0000 add [bx+si],al +00008183 0000 add [bx+si],al +00008185 0000 add [bx+si],al +00008187 0000 add [bx+si],al +00008189 0000 add [bx+si],al +0000818B 0000 add [bx+si],al +0000818D 0000 add [bx+si],al +0000818F 0000 add [bx+si],al +00008191 0000 add [bx+si],al +00008193 0000 add [bx+si],al +00008195 0000 add [bx+si],al +00008197 0000 add [bx+si],al +00008199 0000 add [bx+si],al +0000819B 0000 add [bx+si],al +0000819D 0000 add [bx+si],al +0000819F 0000 add [bx+si],al +000081A1 0000 add [bx+si],al +000081A3 0000 add [bx+si],al +000081A5 0000 add [bx+si],al +000081A7 0000 add [bx+si],al +000081A9 0000 add [bx+si],al +000081AB 0000 add [bx+si],al +000081AD 0000 add [bx+si],al +000081AF 0000 add [bx+si],al +000081B1 0000 add [bx+si],al +000081B3 0000 add [bx+si],al +000081B5 0000 add [bx+si],al +000081B7 0000 add [bx+si],al +000081B9 0000 add [bx+si],al +000081BB 0000 add [bx+si],al +000081BD 0000 add [bx+si],al +000081BF 0000 add [bx+si],al +000081C1 0000 add [bx+si],al +000081C3 0000 add [bx+si],al +000081C5 0000 add [bx+si],al +000081C7 0000 add [bx+si],al +000081C9 0000 add [bx+si],al +000081CB 0000 add [bx+si],al +000081CD 0000 add [bx+si],al +000081CF 0000 add [bx+si],al +000081D1 0000 add [bx+si],al +000081D3 0000 add [bx+si],al +000081D5 0000 add [bx+si],al +000081D7 0000 add [bx+si],al +000081D9 0000 add [bx+si],al +000081DB 0000 add [bx+si],al +000081DD 0000 add [bx+si],al +000081DF 0000 add [bx+si],al +000081E1 0000 add [bx+si],al +000081E3 0000 add [bx+si],al +000081E5 0000 add [bx+si],al +000081E7 0000 add [bx+si],al +000081E9 0000 add [bx+si],al +000081EB 0000 add [bx+si],al +000081ED 0000 add [bx+si],al +000081EF 0000 add [bx+si],al +000081F1 0000 add [bx+si],al +000081F3 0000 add [bx+si],al +000081F5 0000 add [bx+si],al +000081F7 0000 add [bx+si],al +000081F9 0000 add [bx+si],al +000081FB 0000 add [bx+si],al +000081FD 0055AA add [di-0x56],dl diff --git a/freeldr/bootsect/win2k.asm b/freeldr/bootsect/win2k.asm new file mode 100644 index 00000000000..466ad7e471a --- /dev/null +++ b/freeldr/bootsect/win2k.asm @@ -0,0 +1,174 @@ +segment .text + +bits 16 + +start: + jmp short main + nop + +OEMName db 'FreeLDR!' +BytesPerSector dw 512 +SectsPerCluster db 1 +ReservedSectors dw 1 +NumberOfFats db 2 +MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes +TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes +MediaDescriptor db 0f8h +SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes +SectorsPerTrack dw 18 +NumberOfHeads dw 2 +HiddenSectors dd 0 +TotalSectorsBig dd 0 +; FAT32 Inserted Info +SectorsPerFatBig dd 0 +ExtendedFlags dw 0 +FSVersion dw 0 +RootDirStartCluster dd 0 +FSInfoSector dw 0 +BackupBootSector dw 6 +Reserved1 times 12 db 0 +; End FAT32 Inserted Info +BootDrive db 0 +Reserved db 0 +ExtendSig db 29h +SerialNumber dd 00000000h +VolumeLabel db 'FreeLoader!' +FileSystem db 'FAT12 ' + +main: +00007C5A 33C9 xor cx,cx +00007C5C 8ED1 mov ss,cx +00007C5E BCF47B mov sp,0x7bf4 +00007C61 8EC1 mov es,cx +00007C63 8ED9 mov ds,cx +00007C65 BD007C mov bp,0x7c00 +00007C68 884E02 mov [bp+0x2],cl +00007C6B 8A5640 mov dl,[bp+BootDrive] +00007C6E B408 mov ah,0x8 +00007C70 CD13 int 0x13 ; Int 13, func 8 - Get Drive Parameters +00007C72 7305 jnc 0x7c79 ; If no error jmp + +00007C74 B9FFFF mov cx,0xffff +00007C77 8AF1 mov dh,cl + +00007C79 660FB6C6 movzx eax,dh +00007C7D 40 inc ax +00007C7E 660FB6D1 movzx edx,cl +00007C82 80E23F and dl,0x3f +00007C85 F7E2 mul dx +00007C87 86CD xchg cl,ch +00007C89 C0ED06 shr ch,0x6 +00007C8C 41 inc cx +00007C8D 660FB7C9 movzx ecx,cx +00007C91 66F7E1 mul ecx +00007C94 668946F8 mov [bp-0x8],eax +00007C98 837E1600 cmp word [bp+TotalSectors],byte +0x0 +00007C9C 7538 jnz print_ntldr_error_message + +00007C9E 837E2A00 cmp word [bp+FSVersion],byte +0x0 +00007CA2 7732 ja print_ntldr_error_message + +00007CA4 668B461C mov eax,[bp+0x1c] +00007CA8 6683C00C add eax,byte +0xc +00007CAC BB0080 mov bx,0x8000 +00007CAF B90100 mov cx,0x1 +00007CB2 E82B00 call read_sectors +00007CB5 E94803 jmp 0x8000 + +print_disk_error_message: +00007CB8 A0FA7D mov al,[DISK_ERR_offset_from_0x7d00] +putchars: +00007CBB B47D mov ah,0x7d +00007CBD 8BF0 mov si,ax +get_another_char: +00007CBF AC lodsb +00007CC0 84C0 test al,al +00007CC2 7417 jz reboot +00007CC4 3CFF cmp al,0xff +00007CC6 7409 jz print_reboot_message +00007CC8 B40E mov ah,0xe +00007CCA BB0700 mov bx,0x7 +00007CCD CD10 int 0x10 +00007CCF EBEE jmp short get_another_char +print_reboot_message: +00007CD1 A0FB7D mov al,[RESTART_ERR_offset_from_0x7d00] +00007CD4 EBE5 jmp short putchars +print_ntldr_error_message: +00007CD6 A0F97D mov al,[NTLDR_ERR_offset_from_0x7d00] +00007CD9 EBE0 jmp short putchars +reboot: +00007CDB 98 cbw +00007CDC CD16 int 0x16 +00007CDE CD19 int 0x19 + +read_sectors: +00007CE0 6660 pushad +00007CE2 663B46F8 cmp eax,[bp-0x8] +00007CE6 0F824A00 jc near 0x7d34 +00007CEA 666A00 o32 push byte +0x0 +00007CED 6650 push eax +00007CEF 06 push es +00007CF0 53 push bx +00007CF1 666810000100 push dword 0x10010 +00007CF7 807E0200 cmp byte [bp+0x2],0x0 +00007CFB 0F852000 jnz near 0x7d1f +00007CFF B441 mov ah,0x41 +00007D01 BBAA55 mov bx,0x55aa +00007D04 8A5640 mov dl,[bp+BootDrive] +00007D07 CD13 int 0x13 +00007D09 0F821C00 jc near 0x7d29 +00007D0D 81FB55AA cmp bx,0xaa55 +00007D11 0F851400 jnz near 0x7d29 +00007D15 F6C101 test cl,0x1 +00007D18 0F840D00 jz near 0x7d29 +00007D1C FE4602 inc byte [bp+0x2] +00007D1F B442 mov ah,0x42 +00007D21 8A5640 mov dl,[bp+BootDrive] +00007D24 8BF4 mov si,sp +00007D26 CD13 int 0x13 +00007D28 B0F9 mov al,0xf9 +00007D2A 6658 pop eax +00007D2C 6658 pop eax +00007D2E 6658 pop eax +00007D30 6658 pop eax +00007D32 EB2A jmp short 0x7d5e +00007D34 6633D2 xor edx,edx +00007D37 660FB74E18 movzx ecx,word [bp+SectorsPerTrack] +00007D3C 66F7F1 div ecx +00007D3F FEC2 inc dl +00007D41 8ACA mov cl,dl +00007D43 668BD0 mov edx,eax +00007D46 66C1EA10 shr edx,0x10 +00007D4A F7761A div word [bp+NumberOfHeads] +00007D4D 86D6 xchg dl,dh +00007D4F 8A5640 mov dl,[bp+BootDrive] +00007D52 8AE8 mov ch,al +00007D54 C0E406 shl ah,0x6 +00007D57 0ACC or cl,ah +00007D59 B80102 mov ax,0x201 +00007D5C CD13 int 0x13 +00007D5E 6661 popad +00007D60 0F8254FF jc near print_disk_error_message +00007D64 81C30002 add bx,0x200 +00007D68 6640 inc eax +00007D6A 49 dec cx +00007D6B 0F8571FF jnz near read_sectors +00007D6F C3 ret + +NTLDR db 'NTLDR ' + +filler times 49 db 0 + +NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh +DISK_ERR db 0dh,0ah,'Disk error',0ffh +RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah + +more_filler times 16 db 0 + +NTLDR_offset_from_0x7d00 db 0 +NTLDR_ERR_offset_from_0x7d00 db 0ach +DISK_ERR_offset_from_0x7d00 db 0bfh +RESTART_ERR_offset_from_0x7d00 db 0cch + + dw 0 + dw 0aa55h \ No newline at end of file diff --git a/freeldr/build.bat b/freeldr/build.bat new file mode 100644 index 00000000000..d845e83e68b --- /dev/null +++ b/freeldr/build.bat @@ -0,0 +1,7 @@ +cd bootsect +call make.bat +cd.. +cd freeldr +make +copy freeldr.sys .. +cd .. diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile new file mode 100644 index 00000000000..e28173816b8 --- /dev/null +++ b/freeldr/freeldr/Makefile @@ -0,0 +1,89 @@ +# +# FreeLoader +# Copyright (C) 1999, 2000 Brian Palmer +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +export CC = gcc +export LD = ld +export AR = ar +export RM = cmd /C del +export CP = cmd /C copy + +FLAGS = -Wall -nostdinc -fno-builtin + +# asmcode.o has to be first in the link line because it contains the startup code +OBJS = asmcode.a asmcode.o ros.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \ + rosboot.o tui.o menu.o miscboot.o options.o linux.o +ASM_OBJS = asmcode.o ros.o boot.o +C_OBJS = freeldr.o stdlib.o fs.a rosboot.o tui.o menu.o miscboot.o options.o linux.o + +all: freeldr.sys + +freeldr.sys: asmcode.a c_code.a + $(LD) -N -Ttext=0x8000 --oformat=binary -o freeldr.sys asmcode.a c_code.a + +asmcode.a: $(ASM_OBJS) + $(LD) -r -o asmcode.a $(ASM_OBJS) + +c_code.a: $(C_OBJS) + $(LD) -r -o c_code.a $(C_OBJS) + +asmcode.o: asmcode.S asmcode.h Makefile + $(CC) $(FLAGS) -o asmcode.o -c asmcode.S + +freeldr.o: freeldr.c freeldr.h stdlib.h fs.h rosboot.h tui.h asmcode.h menu.h miscboot.h Makefile + $(CC) $(FLAGS) -o freeldr.o -c freeldr.c + +stdlib.o: stdlib.c freeldr.h stdlib.h Makefile + $(CC) $(FLAGS) -o stdlib.o -c stdlib.c + +fs.a: fs.o fs_fat.o Makefile + $(LD) -r -o fs.a fs.o fs_fat.o + +fs.o: fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile + $(CC) $(FLAGS) -o fs.o -c fs.c + +fs_fat.o: fs_fat.c freeldr.h fs.h stdlib.h tui.h Makefile + $(CC) $(FLAGS) -o fs_fat.o -c fs_fat.c + +rosboot.o: rosboot.c freeldr.h rosboot.h stdlib.h fs.h tui.h Makefile + $(CC) $(FLAGS) -o rosboot.o -c rosboot.c + +ros.o: ros.S asmcode.h Makefile + $(CC) $(FLAGS) -o ros.o -c ros.S + +tui.o: tui.c freeldr.h stdlib.h tui.h Makefile + $(CC) $(FLAGS) -o tui.o -c tui.c + +menu.o: menu.c freeldr.h stdlib.h tui.h menu.h Makefile + $(CC) $(FLAGS) -o menu.o -c menu.c + +boot.o: boot.S asmcode.h Makefile + $(CC) $(FLAGS) -o boot.o -c boot.S + +miscboot.o: miscboot.c freeldr.h asmcode.h stdlib.h fs.h tui.h miscboot.h Makefile + $(CC) $(FLAGS) -o miscboot.o -c miscboot.c + +options.o: options.c freeldr.h stdlib.h tui.h options.h Makefile + $(CC) $(FLAGS) -o options.o -c options.c + +linux.o: linux.c freeldr.h stdlib.h tui.h linux.h Makefile + $(CC) $(FLAGS) -o linux.o -c linux.c + +clean: + $(RM) $(OBJS) diff --git a/freeldr/freeldr/asmcode.S b/freeldr/freeldr/asmcode.S new file mode 100644 index 00000000000..ae91d6e997e --- /dev/null +++ b/freeldr/freeldr/asmcode.S @@ -0,0 +1,1177 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + .text + .code16 + +#include "asmcode.h" + + +EXTERN(start) + + cli + + /* Setup segment registers */ + xorw %ax,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + /* Setup a stack */ + movw stack16,%sp + + sti + + /* Init pmode */ + call switch_to_prot + + .code32 + + /* Store the boot drive */ + movb %dl,(_BootDrive) + + /* GO! */ + call _BootMain + + call switch_to_real + .code16 + + int $0x19 + + /* We should never get here */ +stop: + jmp stop + + +/* + * Switches the processor to protected mode + * it destroys eax + */ +EXTERN(switch_to_prot) + + .code16 + + cli /* None of these */ + + /* Get the return address off the stack */ + popw (code32ret) + + /* Save 16-bit stack pointer */ + movw %sp,stack16 + + /* Load the GDT */ + lgdt gdtptr + + /* Enable Protected Mode */ + mov %cr0,%eax + orl $CR0_PE_SET,%eax + mov %eax,%cr0 + + /* Clear prefetch queue & correct CS */ + ljmp $PMODE_CS, $inpmode + + + .code32 + +inpmode: + /* Setup segment selectors */ + movw $PMODE_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + movl stack32,%esp + + /* Put the return address back onto the stack */ + pushl (code32ret) + + /* Now return in p-mode! */ + ret + +/* + * Switches the processor back to real mode + * it destroys eax + */ +EXTERN(switch_to_real) + + .code32 + + /* Get the return address off the stack */ + popl (code16ret) + + /* Save 32-bit stack pointer */ + movl %esp,stack32 + + /* jmp to 16-bit segment to set the limit correctly */ + ljmp $RMODE_CS, $switch_to_real16 + +switch_to_real16: + .code16 + + /* Restore segment registers to correct limit */ + movw $RMODE_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + + /* Disable Protected Mode */ + mov %cr0,%eax + andl $CR0_PE_CLR,%eax + mov %eax,%cr0 + + /* Clear prefetch queue & correct CS */ + ljmp $0, $inrmode + +inrmode: + movw %cs,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + movw stack16,%sp + + /* Put the return address back onto the stack */ + pushw (code16ret) + + sti /* These are ok now */ + + /* Now return in r-mode! */ + ret + + +/* + * void putchar(int ch); + */ +EXTERN(_putchar) + .code32 + + push %eax + push %ebx + push %ebp + + /* Get character to display */ + movb 0x10(%esp),%bl + + /* If we are displaying a CR '\n' then do a LF also */ + cmpb $0x0a,%bl + jnz putchar_1 + + /* Display the LF */ + pushl $0x0d + call _putchar + popl %eax + +putchar_1: + /* If we are displaying a TAB '\t' then display 8 spaces ' ' */ + cmpb $0x09,%bl + jnz putchar_2 + + /* Display the 8 spaces ' ' */ + pushl $0x20 + call _putchar + call _putchar + call _putchar + call _putchar + call _putchar + call _putchar + call _putchar + call _putchar + popl %eax + pop %ebp + pop %ebx + pop %eax + ret + +putchar_2: + call switch_to_real + + .code16 + + /* Display the character via BIOS int 0x10 function 0x0e */ + movb $0x0e,%ah + movb %bl,%al + movw $1,%bx + int $0x10 + + call switch_to_prot + + .code32 + + pop %ebp + pop %ebx + pop %eax + ret + +/* + * void clrscr(void); + */ +EXTERN(_clrscr) + .code32 + + push %eax + push %ebp + + call switch_to_real + + .code16 + + /* Int 0x10, AH = 0x0F - Get Current Video Mode */ + movb $0x0f,%ah + int $0x10 + + /* Int 0x10, AH = 0x00 - Set Current Video Mode, also clears the screen */ + movb $0x00,%ah + int $0x10 + + call switch_to_prot + + .code32 + + pop %ebp + pop %eax + ret + +/* + * int kbhit(void); + */ +EXTERN(_kbhit) + .code32 + + push %ebp + push %ebx + + call switch_to_real + + .code16 + + /* Int 0x16, AH = 0x01 - Get Keyboard Status */ + movb $0x01,%ah + int $0x16 + jz kbhit_1 // ZF=0 if no key is available + + /* Return value is non-zero if a key is available */ + movl $1,%ebx + jmp kbhit_done + +kbhit_1: + /* Return value is zero if no key is available */ + movl $0,%ebx + +kbhit_done: + + call switch_to_prot + + .code32 + + /* Get return value from ebx */ + movl %ebx,%eax + + pop %ebx + pop %ebp + ret + +/* + * int getch(void); + */ +extended_scancode: + .byte 0 +EXTERN(_getch) + .code32 + + push %ebp + push %ebx + + call switch_to_real + + .code16 + + /* Check and see if we have an extended scancode to return */ + movb extended_scancode,%al + movb $0,extended_scancode + movzbl %al,%ebx + cmpb $0,%al + jnz getch_done + + /* Int 0x16, AH = 0x00 - Wait for keypress */ + movb $0,%ah + int $0x16 + + /* If al is zero then it is an extended key */ + cmp $0,%al + jnz getch_1 + + /* Save the scan code to be returned on the next call to getch() */ + movb %ah,extended_scancode + +getch_1: + /* Store character in ebx */ + movzbl %al,%ebx + +getch_done: + call switch_to_prot + + .code32 + + /* Get return value from ebx */ + movl %ebx,%eax + + pop %ebx + pop %ebp + ret + +/* + * void gotoxy(int x, int y); + */ +EXTERN(_gotoxy) + .code32 + + push %ebp + push %eax + push %ebx + push %edx + + /* Get cursor positions */ + movb 0x14(%esp),%dl + movb 0x18(%esp),%dh + + call switch_to_real + + .code16 + + /* Update the cursor position */ + movb $2,%ah + movb $0,%bh + int $0x10 + + call switch_to_prot + + .code32 + + pop %edx + pop %ebx + pop %eax + pop %ebp + ret + +/* + * int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); + */ +_biosdisk_cmd: + .long 0 +_biosdisk_drive: + .long 0 +_biosdisk_head: + .long 0 +_biosdisk_track: + .long 0 +_biosdisk_sector: + .long 0 +_biosdisk_nsects: + .long 0 +_biosdisk_buffer: + .long 0 +_biosdisk_retval: + .long 0 +_biosdisk_retrycount: + .byte 0 +EXTERN(_biosdisk) + .code32 + + push %ebp + push %esi + push %edi + push %ebx + push %ecx + push %edx + + /* Get parameters */ + movl 0x1c(%esp),%eax + movl %eax,_biosdisk_cmd + movl 0x20(%esp),%eax + movl %eax,_biosdisk_drive + movl 0x24(%esp),%eax + movl %eax,_biosdisk_head + movl 0x28(%esp),%eax + movl %eax,_biosdisk_track + movl 0x2c(%esp),%eax + movl %eax,_biosdisk_sector + movl 0x30(%esp),%eax + movl %eax,_biosdisk_nsects + movl 0x34(%esp),%eax + movl %eax,_biosdisk_buffer + + call switch_to_real + + .code16 + pushw %es // Save this just in case + movb $3,_biosdisk_retrycount // Set the retry count to 3 + +_biosdisk_read: + movw $SCRATCHSEG,%ax // Load ES with 7000 + movw %ax,%es // and BX with 0 + movw $SCRATCHOFF,%bx // so that the sector gets loaded to 7000:0000 + movb _biosdisk_sector,%cl // Get the sector in CL + movw _biosdisk_track,%ax // Cylinder in AX + movb %al,%ch // Now put it in CH + rorb $1,%ah // Low 8 bits of cylinder in CH, high 2 bits + rorb $1,%ah // in CL shifted to bits 6 & 7 + andb $0xc0,%ah // Clear out low six bits + orb %ah,%cl // Or with sector number + movb _biosdisk_head,%dh // Get the head + movb _biosdisk_drive,%dl // Get the drive + movb $2,%ah // BIOS int 0x13, function 2 - Read Disk Sectors + movb _biosdisk_nsects,%al // Number of sectors to read + int $0x13 // Read a sector + + // I have recently learned that not all bioses return + // the sector read count in the AL register (at least mine doesn't) + // even if the sectors were read correctly. So instead + // of checking the sector read count we will rely solely + // on the carry flag being set on error + + //jmp _biosdisk_done + //cmpb _biosdisk_nsects,%al // See how many sectors we actually read + //jne _biosdisk_error // Jump if no error + + movb $1,%al // Set the return value to be one (will be set to zero later if needed) + jc _biosdisk_error // Jump if error (CF = 1 on error) + jmp _biosdisk_done + + +_biosdisk_error: + cmpb $0x11,%ah // Check and see if it was a corrected ECC error + je _biosdisk_done // If so then the data is still good, if not fail + + movb _biosdisk_retrycount,%al// Get the current retry count + decb %al // Decrement it + movb %al,_biosdisk_retrycount// Save it + cmpb $0,%al // Is it zero? + jz _biosdisk_zero // Yes, return zero + + movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System + movb _biosdisk_drive,%dl // Get the drive + int $0x13 // Reset the disk system + jmp _biosdisk_read // Try reading again + +_biosdisk_zero: + movb $0,%al // We will return zero + +_biosdisk_done: + movzbl %al,%eax // Put the number of sectors read into EAX + movl %eax,_biosdisk_retval // Save it as the return value + + popw %es // Restore ES + call switch_to_prot + + .code32 + + /* Copy the sector contents from 7000:0000 to the buffer */ + cld + movl $SCRATCHAREA,%esi + movl _biosdisk_buffer,%edi + movl _biosdisk_nsects,%eax + movl $0x100,%ebx + mull %ebx + movl %eax,%ecx + rep + movsw + + movl _biosdisk_retval,%eax // Get return value + //movl $1,%eax + + pop %edx + pop %ecx + pop %ebx + pop %edi + pop %esi + pop %ebp + ret + +/* + * int getyear(void); + */ +EXTERN(_getyear) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the date */ + movb $4,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %ch,%al + andb $0x0f,%al + movb %al,%dl + movb %ch,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + movb %dl,%dh + + movb %cl,%al + andb $0x0f,%al + movb %al,%dl + movb %cl,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + + movb %dl,%cl + + movzbl %dh,%eax + movl $100,%ebx + mull %ebx + movl %eax,%edx + addb %cl,%dl + + /* Save return value */ + movl %edx,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int getday(void); + */ +EXTERN(_getday) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the date */ + movb $4,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %dl,%al + andb $0x0f,%al + movb %al,%cl + movb %dl,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%cl + + /* Save return value */ + movzbl %cl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int getmonth(void); + */ +EXTERN(_getmonth) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the date */ + movb $4,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %dh,%al + andb $0x0f,%al + movb %al,%dl + movb %dh,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + + /* Save return value */ + movzbl %dl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int gethour(void); + */ +EXTERN(_gethour) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the time */ + movb $2,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %ch,%al + andb $0x0f,%al + movb %al,%dl + movb %ch,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + + /* Save return value */ + movzbl %dl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int getminute(void); + */ +EXTERN(_getminute) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the time */ + movb $2,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %cl,%al + andb $0x0f,%al + movb %al,%dl + movb %cl,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + + /* Save return value */ + movzbl %dl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int getsecond(void); + */ +EXTERN(_getsecond) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the time */ + movb $2,%ah + int $0x1a + + /* Convert from BCD to normal */ + movb %dh,%al + andb $0x0f,%al + movb %al,%dl + movb %dh,%al + shrb $0x04,%al + andb $0x0f,%al + movb $0x0a,%bl + mulb %bl + addb %al,%dl + + /* Save return value */ + movzbl %dl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * void hidecursor(void); + */ +EXTERN(_hidecursor) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Hide the cursor */ + movb $1,%ah + movw $0x2000,%cx + int $0x10 + + call switch_to_prot + + .code32 + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * void showcursor(void); + */ +EXTERN(_showcursor) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Show the cursor */ + movb $1,%ah + movb $0x0d,%ch + movb $0x0e,%cl + int $0x10 + + call switch_to_prot + + .code32 + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int wherex(void); + */ +EXTERN(_wherex) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the cursor position */ + movb $3,%ah + movb $0,%bh + int $0x10 + + /* Save return value */ + movzbl %dl,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * int wherey(void); + */ +EXTERN(_wherey) + .code32 + + push %ebp + push %ebx + push %ecx + push %edx + + call switch_to_real + + .code16 + + /* Get the cursor position */ + movb $3,%ah + movb $0,%bh + int $0x10 + + /* Save return value */ + movzbl %dh,%edx + + call switch_to_prot + + .code32 + + /* Restore return value */ + movl %edx,%eax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + +/* + * void stop_floppy(void); + * + * Stops the floppy drive from spinning, so that other software is + * jumped to with a known state. + */ +EXTERN(_stop_floppy) + .code32 + + push %eax + push %edx + + call switch_to_real + + .code16 + + movw $0x3F2, %dx + xorb %al, %al + outb %al, %dx + + call switch_to_prot + + .code32 + + pop %edx + pop %eax + ret + +/* + * int get_heads(int drive); + */ +EXTERN(_get_heads) + .code32 + + push %ebx + push %ecx + push %edx + push %edi + push %es + + /* Get drive */ + movl 0x18(%esp),%eax + movl %eax,_biosdisk_drive + + call switch_to_real + + .code16 + + movb $0x08,%ah + movb _biosdisk_drive,%dl + int $0x13 + jc _get_heads_error + + incb %dh + movzbl %dh,%edx + movl %edx,_biosdisk_retval + jmp _get_heads_done + +_get_heads_error: + movl $0x0e,_biosdisk_retval + +_get_heads_done: + + call switch_to_prot + + .code32 + + movl _biosdisk_retval,%eax // Get return value + + pop %es + pop %edi + pop %edx + pop %ecx + pop %ebx + + ret + +/* + * int get_cylinders(int drive); + */ +EXTERN(_get_cylinders) + .code32 + + push %ebx + push %ecx + push %edx + push %edi + push %es + + /* Get drive */ + movl 0x18(%esp),%eax + movl %eax,_biosdisk_drive + + call switch_to_real + + .code16 + + movb $0x08,%ah + movb _biosdisk_drive,%dl + int $0x13 + jc _get_cylinders_error + + xorl %edx,%edx + andb $0xc0,%cl + shrb $0x06,%cl + movb %cl,%dh + movb %ch,%dl + incl %edx + movl %edx,_biosdisk_retval + jmp _get_cylinders_done + +_get_cylinders_error: + movl $0x00,_biosdisk_retval + +_get_cylinders_done: + + call switch_to_prot + + .code32 + + movl _biosdisk_retval,%eax // Get return value + + pop %es + pop %edi + pop %edx + pop %ecx + pop %ebx + + ret + +/* + * int get_sectors(int drive); + */ +EXTERN(_get_sectors) + .code32 + + push %ebx + push %ecx + push %edx + push %edi + push %es + + /* Get drive */ + movl 0x18(%esp),%eax + movl %eax,_biosdisk_drive + + call switch_to_real + + .code16 + + movb $0x08,%ah + movb _biosdisk_drive,%dl + int $0x13 + jc _get_sectors_error + + andb $0x3f,%cl + movzbl %cl,%ecx + movl %ecx,_biosdisk_retval + jmp _get_sectors_done + +_get_sectors_error: + movl $0x00,_biosdisk_retval + +_get_sectors_done: + + call switch_to_prot + + .code32 + + movl _biosdisk_retval,%eax // Get return value + + pop %es + pop %edi + pop %edx + pop %ecx + pop %ebx + + ret + + + + + + /* 16-bit stack pointer */ +stack16: + .word STACK16ADDR + + /* 32-bit stack pointer */ +stack32: + .long STACK32ADDR + + /* 16-bit return address */ +code16ret: + .long 0 + + /* 32-bit return address */ +code32ret: + .long 0 + + + .p2align 2 /* force 4-byte alignment */ +gdt: + /* NULL Descriptor */ + .word 0x0000 + .word 0x0000 + .word 0x0000 + .word 0x0000 + + /* 32-bit flat CS */ + .word 0xFFFF + .word 0x0000 + .word 0x9A00 + .word 0x00CF + + /* 32-bit flat DS */ + .word 0xFFFF + .word 0x0000 + .word 0x9200 + .word 0x00CF + + /* 16-bit real mode CS */ + .word 0xFFFF + .word 0x0000 + .word 0x9E00 + .word 0x0000 + + /* 16-bit real mode DS */ + .word 0xFFFF + .word 0x0000 + .word 0x9200 + .word 0x0000 + +/* GDT table pointer */ +gdtptr: + .word 0x27 /* Limit */ + .long gdt /* Base Address */ + +EXTERN(_BootDrive) + .long 0 diff --git a/freeldr/freeldr/asmcode.h b/freeldr/freeldr/asmcode.h new file mode 100644 index 00000000000..5ab2b7247ca --- /dev/null +++ b/freeldr/freeldr/asmcode.h @@ -0,0 +1,57 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* Defines needed for switching between real and protected mode */ +#define NULL_DESC 0x00 /* NULL descriptor */ +#define PMODE_CS 0x08 /* PMode code selector, base 0 limit 4g */ +#define PMODE_DS 0x10 /* PMode data selector, base 0 limit 4g */ +#define RMODE_CS 0x18 /* RMode code selector, base 0 limit 64k */ +#define RMODE_DS 0x20 /* RMode data selector, base 0 limit 64k */ + +#define KERNEL_BASE 0xC0000000 +//#define USER_CS 0x08 +//#define USER_DS 0x10 +//#define KERNEL_CS 0x20 +//#define KERNEL_DS 0x28 +#define KERNEL_CS 0x08 +#define KERNEL_DS 0x10 + +#define CR0_PE_SET 0x00000001 /* OR this value with CR0 to enable pmode */ +#define CR0_PE_CLR 0xFFFFFFFE /* AND this value with CR0 to disable pmode */ + +#define NR_TASKS 128 /* Space reserved in the GDT for TSS descriptors */ + +#define STACK16ADDR 0x7000 /* The 16-bit stack top will be at 0000:7000 */ +#define STACK32ADDR 0x60000 /* The 32-bit stack top will be at 6000:0000, or 0x60000 */ + +#define FILESYSADDR 0x80000 /* The filesystem data address will be at 8000:0000, or 0x80000 */ + +#define FATCLUSTERBUF 0x60000 /* The fat filesystem's cluster buffer */ + +#define SCREENBUFFER 0x68000 /* The screen contents will be saved here */ +#define FREELDRINIADDR 0x6C000 /* The freeldr.ini load address will be at 6000:C000, or 0x6C000 */ + +#define SCRATCHSEG 0x7000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */ +#define SCRATCHOFF 0x0000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */ +#define SCRATCHAREA 0x70000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */ + +/* Makes "x" a global variable or label */ +#define EXTERN(x) .global x; x: + diff --git a/freeldr/freeldr/boot.S b/freeldr/freeldr/boot.S new file mode 100644 index 00000000000..c8f5124dbea --- /dev/null +++ b/freeldr/freeldr/boot.S @@ -0,0 +1,45 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + .text + .code16 + +#include "asmcode.h" + + + .code32 +EXTERN(_JumpToBootCode) + call switch_to_real + .code16 + + /* Set the boot drive */ + movb (_BootDrive),%dl + + ljmpl $0x0000,$0x7C00 + + + .code32 +EXTERN(_JumpToLinuxBootCode) + call switch_to_real + .code16 + + /* Set the boot drive */ + movb (_BootDrive),%dl + + ljmpl $0x0200,$0x9000 diff --git a/freeldr/freeldr/freeldr.c b/freeldr/freeldr/freeldr.c new file mode 100644 index 00000000000..b38d1892914 --- /dev/null +++ b/freeldr/freeldr/freeldr.c @@ -0,0 +1,734 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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= 16) + { + printf("Error: you can only boot to at most 16 different operating systems.\n"); + printf("Press any key to continue\n"); + getch(); + return; + } + + if(!GetNumSectionItems(value)) + { + printf("Error: OS \"%s\" listed.\n", value); + printf("It does not have it's own [section], or it is empty.\n"); + printf("Press any key to continue\n"); + getch(); + return; + } + + strcpy(OSList[nNumOS].name, value); + + if (!ReadSectionSettingByName(value, "BootType", name, v)) + { + printf("Unknown BootType for OS \"%s\"\n", value); + printf("Press any key to continue\n"); + getch(); + return; + } + + if (stricmp(v, "ReactOS") == 0) + OSList[nNumOS].nOSType = OSTYPE_REACTOS; + else if (stricmp(v, "Linux") == 0) + OSList[nNumOS].nOSType = OSTYPE_LINUX; + else if (stricmp(v, "BootSector") == 0) + OSList[nNumOS].nOSType = OSTYPE_BOOTSECTOR; + else if (stricmp(v, "Partition") == 0) + OSList[nNumOS].nOSType = OSTYPE_PARTITION; + else if (stricmp(v, "Drive") == 0) + OSList[nNumOS].nOSType = OSTYPE_DRIVE; + else + { + printf("Unknown BootType for OS \"%s\"\n", value); + printf("Press any key to continue\n"); + getch(); + return; + } + + nNumOS++; + } + else if(stricmp(setting, "TimeOut") == 0) + nTimeOut = atoi(value); +} diff --git a/freeldr/freeldr/freeldr.h b/freeldr/freeldr/freeldr.h new file mode 100644 index 00000000000..d8e3fd10e36 --- /dev/null +++ b/freeldr/freeldr/freeldr.h @@ -0,0 +1,82 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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 " + +#define ROSLDR_MAJOR_VERSION 0 +#define ROSLDR_MINOR_VERSION 8 +#define ROSLDR_PATCH_VERSION 0 + +#define size_t unsigned int +#define BOOL int +#define NULL 0 +#define TRUE 1 +#define FALSE 0 +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long +#define CHAR char +#define WCHAR unsigned short +#define LONG long +#define ULONG unsigned long +#define PULONG unsigned long * +#define PDWORD DWORD * +#define PWORD WORD * + +#define OSTYPE_REACTOS 1 +#define OSTYPE_LINUX 2 +#define OSTYPE_BOOTSECTOR 3 +#define OSTYPE_PARTITION 4 +#define OSTYPE_DRIVE 5 + +typedef struct +{ + char name[260]; + int nOSType; // ReactOS or Linux or a bootsector, etc. +} OSTYPE; + +extern unsigned int BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc. +extern unsigned int BootPartition; // Boot Partition, 1-4 +extern BOOL bTUILoaded; // Tells us if the user interface is loaded + +extern char *pFreeldrIni; // Load address for freeldr.ini +extern char *pScreenBuffer; // Save address for screen contents +extern int nCursorXPos; // Cursor's X Position +extern int nCursorYPos; // Cursor's Y Position + +extern OSTYPE OSList[16]; // The OS list +extern int nNumOS; // Number of OSes listed + +extern int nTimeOut; // Time to wait for the user before booting + +void BootMain(void); +BOOL ParseIniFile(void); +int GetNumSectionItems(char *section); // returns the number of items in a particular section (i.e. [FREELOADER]) +BOOL ReadSectionSettingByNumber(char *section, int num, char *name, char *value); // Reads the num'th value from section +BOOL ReadSectionSettingByName(char *section, char *valuename, char *name, char *value); // Reads the value named name from section +BOOL IsValidSetting(char *setting, char *value); +void SetSetting(char *setting, char *value); + +#endif // defined __FREELDR_H \ No newline at end of file diff --git a/freeldr/freeldr/fs.c b/freeldr/freeldr/fs.c new file mode 100644 index 00000000000..03419dd8040 --- /dev/null +++ b/freeldr/freeldr/fs.c @@ -0,0 +1,426 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "freeldr.h" +#include "fs.h" +#include "stdlib.h" +#include "tui.h" +#include "asmcode.h" + +#define FS_DO_ERROR(s) \ + { \ + if (bTUILoaded) \ + MessageBox(s); \ + else \ + { \ + printf(s); \ + printf("\nPress any key\n"); \ + getch(); \ + } \ + } + + +int nSectorBuffered = -1; // Tells us which sector was read into SectorBuffer[] + +BYTE SectorBuffer[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here + +int FSType = NULL; // Type of filesystem on boot device, set by OpenDiskDrive() + +char *pFileSysData = (char *)(FILESYSADDR); // Load address for filesystem data +char *pFat32FATCacheIndex = (char *)(FILESYSADDR); // Load address for filesystem data + +BOOL OpenDiskDrive(int nDrive, int nPartition) +{ + int num_bootable_partitions = 0; + int boot_partition = 0; + int partition_type = 0; + int head, sector, cylinder; + int offset; + + // Check and see if it is a floppy drive + if (nDrive < 0x80) + { + // Read boot sector + if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer)) + { + FS_DO_ERROR("Disk Read Error"); + return FALSE; + } + + // Check for validity + if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA)) + { + FS_DO_ERROR("Invalid boot sector magic (0xaa55)"); + return FALSE; + } + } + else + { + // Read master boot record + if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer)) + { + FS_DO_ERROR("Disk Read Error"); + return FALSE; + } + + // Check for validity + if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA)) + { + FS_DO_ERROR("Invalid partition table magic (0xaa55)"); + return FALSE; + } + + if (nPartition == 0) + { + // Check for bootable partitions + if (SectorBuffer[0x1BE] == 0x80) + num_bootable_partitions++; + if (SectorBuffer[0x1CE] == 0x80) + { + num_bootable_partitions++; + boot_partition = 1; + } + if (SectorBuffer[0x1DE] == 0x80) + { + num_bootable_partitions++; + boot_partition = 2; + } + if (SectorBuffer[0x1EE] == 0x80) + { + num_bootable_partitions++; + boot_partition = 3; + } + + // Make sure there was only one bootable partition + if (num_bootable_partitions > 1) + { + FS_DO_ERROR("Too many boot partitions"); + return FALSE; + } + + offset = 0x1BE + (boot_partition * 0x10); + } + else + offset = 0x1BE + ((nPartition-1) * 0x10); + + partition_type = SectorBuffer[offset + 4]; + + // Check for valid partition + if (partition_type == 0) + { + FS_DO_ERROR("Invalid boot partition"); + return FALSE; + } + + head = SectorBuffer[offset + 1]; + sector = (SectorBuffer[offset + 2] & 0x3F); + cylinder = SectorBuffer[offset + 3]; + if (SectorBuffer[offset + 2] & 0x80) + cylinder += 0x200; + if (SectorBuffer[offset + 2] & 0x40) + cylinder += 0x100; + + // Read partition boot sector + if (!biosdisk(_DISK_READ, nDrive, head, cylinder, sector, 1, SectorBuffer)) + { + FS_DO_ERROR("Disk Read Error"); + return FALSE; + } + + // Check for validity + if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA)) + { + FS_DO_ERROR("Invalid boot sector magic (0xaa55)"); + return FALSE; + } + } + + + // Reset data + nBytesPerSector = 0; + nSectorsPerCluster = 0; + nReservedSectors = 0; + nNumberOfFATs = 0; + nRootDirEntries = 0; + nTotalSectors16 = 0; + nSectorsPerFAT16 = 0; + nSectorsPerTrack = 0; + nNumberOfHeads = 0; + nHiddenSectors = 0; + nTotalSectors32 = 0; + + nSectorsPerFAT32 = 0; + nExtendedFlags = 0; + nFileSystemVersion = 0; + nRootDirStartCluster = 0; + + nRootDirSectorStart = 0; + nDataSectorStart = 0; + nSectorsPerFAT = 0; + nRootDirSectors = 0; + nTotalSectors = 0; + nNumberOfClusters = 0; + + // Get data + memcpy(&nBytesPerSector, SectorBuffer + BPB_BYTESPERSECTOR, 2); + memcpy(&nSectorsPerCluster, SectorBuffer + BPB_SECTORSPERCLUSTER, 1); + memcpy(&nReservedSectors, SectorBuffer + BPB_RESERVEDSECTORS, 2); + memcpy(&nNumberOfFATs, SectorBuffer + BPB_NUMBEROFFATS, 1); + memcpy(&nRootDirEntries, SectorBuffer + BPB_ROOTDIRENTRIES, 2); + memcpy(&nTotalSectors16, SectorBuffer + BPB_TOTALSECTORS16, 2); + memcpy(&nSectorsPerFAT16, SectorBuffer + BPB_SECTORSPERFAT16, 2); + memcpy(&nSectorsPerTrack, SectorBuffer + BPB_SECTORSPERTRACK, 2); + memcpy(&nNumberOfHeads, SectorBuffer + BPB_NUMBEROFHEADS, 2); + memcpy(&nHiddenSectors, SectorBuffer + BPB_HIDDENSECTORS, 4); + memcpy(&nTotalSectors32, SectorBuffer + BPB_TOTALSECTORS32, 4); + + memcpy(&nSectorsPerFAT32, SectorBuffer + BPB_SECTORSPERFAT32, 4); + memcpy(&nExtendedFlags, SectorBuffer + BPB_EXTENDEDFLAGS32, 2); + memcpy(&nFileSystemVersion, SectorBuffer + BPB_FILESYSTEMVERSION32, 2); + memcpy(&nRootDirStartCluster, SectorBuffer + BPB_ROOTDIRSTARTCLUSTER32, 4); + + // Calc some stuff + if (nTotalSectors16 != 0) + nTotalSectors = nTotalSectors16; + else + nTotalSectors = nTotalSectors32; + + if (nSectorsPerFAT16 != 0) + nSectorsPerFAT = nSectorsPerFAT16; + else + nSectorsPerFAT = nSectorsPerFAT32; + + nRootDirSectorStart = (nNumberOfFATs * nSectorsPerFAT) + nReservedSectors; + nRootDirSectors = ((nRootDirEntries * 32) + (nBytesPerSector - 1)) / nBytesPerSector; + nDataSectorStart = nReservedSectors + (nNumberOfFATs * nSectorsPerFAT) + nRootDirSectors; + nNumberOfClusters = (nTotalSectors - nDataSectorStart) / nSectorsPerCluster; + + // Determine FAT type + if (nNumberOfClusters < 4085) + { + /* Volume is FAT12 */ + nFATType = FAT12; + } + else if (nNumberOfClusters < 65525) + { + /* Volume is FAT16 */ + nFATType = FAT16; + } + else + { + /* Volume is FAT32 */ + nFATType = FAT32; + + // Check version + // we only work with version 0 + if (*((WORD*)(SectorBuffer + BPB_FILESYSTEMVERSION32)) != 0) + { + FS_DO_ERROR("Error: FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader."); + return FALSE; + } + } + + FSType = FS_FAT; + + // Buffer the FAT table if it is small enough + if ((FSType == FS_FAT) && (nFATType == FAT12)) + { + if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData)) + return FALSE; + } + else if ((FSType == FS_FAT) && (nFATType == FAT16)) + { + if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData)) + return FALSE; + } + else if ((FSType == FS_FAT) && (nFATType == FAT32)) + { + // The FAT table is too big to be buffered so + // we will initialize our cache and cache it + // on demand + for (offset=0; offset<256; offset++) + ((int*)pFat32FATCacheIndex)[offset] = -1; + } + + return TRUE; +} + +BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer) +{ + BOOL bRetVal; + int PhysicalSector; + int PhysicalHead; + int PhysicalTrack; + int nNum; + + nSect += nHiddenSectors; + + while (nNumberOfSectors) + { + PhysicalSector = 1 + (nSect % nSectorsPerTrack); + PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads; + PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads); + + if (PhysicalSector > 1) + { + if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1))) + nNum = (nSectorsPerTrack - (PhysicalSector - 1)); + else + nNum = nNumberOfSectors; + } + else + { + if (nNumberOfSectors >= nSectorsPerTrack) + nNum = nSectorsPerTrack; + else + nNum = nNumberOfSectors; + } + + bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer); + + if (!bRetVal) + { + FS_DO_ERROR("Disk Error"); + return FALSE; + } + + pBuffer += (nNum * 512); + nNumberOfSectors -= nNum; + nSect += nNum; + } + + return TRUE; +} + +BOOL ReadOneSector(int nSect) +{ + BOOL bRetVal; + int PhysicalSector; + int PhysicalHead; + int PhysicalTrack; + + nSectorBuffered = nSect; + + nSect += nHiddenSectors; + PhysicalSector = 1 + (nSect % nSectorsPerTrack); + PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads; + PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads); + + + bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, 1, SectorBuffer); + + if (!bRetVal) + { + FS_DO_ERROR("Disk Error"); + return FALSE; + } + + return TRUE; +} + +BOOL OpenFile(char *filename, FILE *pFile) +{ + switch(FSType) + { + case FS_FAT: + if(!FATOpenFile(filename, &(pFile->fat))) + return FALSE; + pFile->filesize = pFile->fat.dwSize; + break; + default: + FS_DO_ERROR("Error: Unknown filesystem."); + return FALSE; + break; + } + + return TRUE; +} + +/* + * ReadFile() + * returns number of bytes read or EOF + */ +int ReadFile(FILE *pFile, int count, void *buffer) +{ + switch(FSType) + { + case FS_FAT: + return FATRead(&(pFile->fat), count, buffer); + default: + FS_DO_ERROR("Error: Unknown filesystem."); + return EOF; + } + + return 0; +} + +DWORD GetFileSize(FILE *pFile) +{ + return pFile->filesize; +} + +DWORD Rewind(FILE *pFile) +{ + switch (FSType) + { + case FS_FAT: + pFile->fat.dwCurrentCluster = pFile->fat.dwStartCluster; + pFile->fat.dwCurrentReadOffset = 0; + break; + default: + FS_DO_ERROR("Error: Unknown filesystem."); + break; + } + + return pFile->filesize; +} + +int feof(FILE *pFile) +{ + switch (FSType) + { + case FS_FAT: + if (pFile->fat.dwCurrentReadOffset >= pFile->fat.dwSize) + return TRUE; + else + return FALSE; + break; + default: + FS_DO_ERROR("Error: Unknown filesystem."); + return TRUE; + break; + } + + return TRUE; +} + +int fseek(FILE *pFile, DWORD offset) +{ + switch (FSType) + { + case FS_FAT: + return FATfseek(&(pFile->fat), offset); + break; + default: + FS_DO_ERROR("Error: Unknown filesystem."); + break; + } + + return -1; +} diff --git a/freeldr/freeldr/fs.h b/freeldr/freeldr/fs.h new file mode 100644 index 00000000000..e80dadb56c9 --- /dev/null +++ b/freeldr/freeldr/fs.h @@ -0,0 +1,182 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FS_FAT_H +#define __FS_FAT_H + +// Bootsector BPB defines +#define BPB_JMPBOOT 0 +#define BPB_OEMNAME 3 +#define BPB_BYTESPERSECTOR 11 +#define BPB_SECTORSPERCLUSTER 13 +#define BPB_RESERVEDSECTORS 14 +#define BPB_NUMBEROFFATS 16 +#define BPB_ROOTDIRENTRIES 17 +#define BPB_TOTALSECTORS16 19 +#define BPB_MEDIADESCRIPTOR 21 +#define BPB_SECTORSPERFAT16 22 +#define BPB_SECTORSPERTRACK 24 +#define BPB_NUMBEROFHEADS 26 +#define BPB_HIDDENSECTORS 28 +#define BPB_TOTALSECTORS32 32 + +// Fat12/16 extended BPB defines +#define BPB_DRIVENUMBER16 36 +#define BPB_RESERVED16_1 37 +#define BPB_BOOTSIGNATURE16 38 +#define BPB_VOLUMESERIAL16 39 +#define BPB_VOLUMELABEL16 43 +#define BPB_FILESYSTEMTYPE16 54 + +// Fat32 extended BPB defines +#define BPB_SECTORSPERFAT32 36 +#define BPB_EXTENDEDFLAGS32 40 +#define BPB_FILESYSTEMVERSION32 42 +#define BPB_ROOTDIRSTARTCLUSTER32 44 +#define BPB_FILESYSTEMINFOSECTOR32 48 +#define BPB_BACKUPBOOTSECTOR32 50 +#define BPB_RESERVED32_1 52 +#define BPB_DRIVENUMBER32 64 +#define BPB_RESERVED32_2 65 +#define BPB_BOOTSIGNATURE32 66 +#define BPB_VOLUMESERIAL32 67 +#define BPB_VOLUMELABEL32 71 +#define BPB_FILESYSTEMTYPE32 82 + +/* + * Structure of MSDOS directory entry + */ +typedef struct //_DIRENTRY +{ + BYTE cFileName[11]; /* Filename + extension */ + BYTE cAttr; /* File attributes */ + BYTE cReserved[10]; /* Reserved area */ + WORD wTime; /* Time last modified */ + WORD wData; /* Date last modified */ + WORD wCluster; /* First cluster number */ + DWORD dwSize; /* File size */ +} DIRENTRY, * PDIRENTRY; + +/* + * Structure of internal file control block + */ +typedef struct //_FCB +{ + BYTE cAttr; /* Open attributes */ + BYTE cSector; /* Sector within cluster */ + PDIRENTRY pDirptr; /* Pointer to directory entry */ + WORD wDirSector; /* Directory sector */ + WORD wFirstCluster; /* First cluster in file */ + WORD wLastCluster; /* Last cluster read/written */ + WORD wNextCluster; /* Next cluster to read/write */ + WORD wOffset; /* Read/Write offset within sector */ + DWORD dwSize; /* File size */ + BYTE cBuffer[512]; /* Data transfer buffer */ +} FCB, * PFCB; + +typedef struct //_FAT_STRUCT +{ + DWORD dwStartCluster; // File's starting cluster + DWORD dwCurrentCluster; // Current read cluster number + DWORD dwSize; // File size + DWORD dwCurrentReadOffset;// Amount of data already read +} FAT_STRUCT, * PFAT_STRUCT; + +typedef struct //_FILE +{ + //DIRENTRY de; + //FCB fcb; + FAT_STRUCT fat; + unsigned long filesize; +} FILE; + +extern int nSectorBuffered; // Tells us which sector was read into SectorBuffer[] +extern BYTE SectorBuffer[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here + +extern int nFATType; + +extern DWORD nBytesPerSector; // Bytes per sector +extern DWORD nSectorsPerCluster; // Number of sectors in a cluster +extern DWORD nReservedSectors; // Reserved sectors, usually 1 (the bootsector) +extern DWORD nNumberOfFATs; // Number of FAT tables +extern DWORD nRootDirEntries; // Number of root directory entries (fat12/16) +extern DWORD nTotalSectors16; // Number of total sectors on the drive, 16-bit +extern DWORD nSectorsPerFAT16; // Sectors per FAT table (fat12/16) +extern DWORD nSectorsPerTrack; // Number of sectors in a track +extern DWORD nNumberOfHeads; // Number of heads on the disk +extern DWORD nHiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) +extern DWORD nTotalSectors32; // Number of total sectors on the drive, 32-bit + +extern DWORD nSectorsPerFAT32; // Sectors per FAT table (fat32) +extern DWORD nExtendedFlags; // Extended flags (fat32) +extern DWORD nFileSystemVersion; // File system version (fat32) +extern DWORD nRootDirStartCluster; // Starting cluster of the root directory (fat32) + +extern DWORD nRootDirSectorStart; // Starting sector of the root directory (fat12/16) +extern DWORD nDataSectorStart; // Starting sector of the data area +extern DWORD nSectorsPerFAT; // Sectors per FAT table +extern DWORD nRootDirSectors; // Number of sectors of the root directory (fat32) +extern DWORD nTotalSectors; // Total sectors on the drive +extern DWORD nNumberOfClusters; // Number of clusters on the drive + +extern int FSType; // Type of filesystem on boot device, set by OpenDiskDrive() + +extern char *pFileSysData; // Load address for filesystem data +extern char *pFat32FATCacheIndex; // Load address for filesystem data + +BOOL OpenDiskDrive(int nDrive, int nPartition); // Opens the disk drive device for reading +BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer);// Reads a sector from the open device +BOOL ReadOneSector(int nSect); // Reads one sector from the open device +BOOL OpenFile(char *filename, FILE *pFile); // Opens a file +int ReadFile(FILE *pFile, int count, void *buffer); // Reads count bytes from pFile into buffer +DWORD GetFileSize(FILE *pFile); +DWORD Rewind(FILE *pFile); // Rewinds a file and returns it's size +int feof(FILE *pFile); +int fseek(FILE *pFILE, DWORD offset); + +BOOL FATLookupFile(char *file, PFAT_STRUCT pFatStruct); +int FATGetNumPathParts(char *name); +BOOL FATGetFirstNameFromPath(char *buffer, char *name); +void FATParseFileName(char *buffer, char *name); +DWORD FATGetFATEntry(DWORD nCluster); +BOOL FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct); +int FATReadCluster(DWORD nCluster, char *cBuffer); +int FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer); +int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset); + + +#define EOF -1 + +#define ATTR_NORMAL 0x00 +#define ATTR_READONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUMENAME 0x08 +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 + +#define FS_FAT 1 +#define FS_NTFS 2 +#define FS_EXT2 3 + +#define FAT12 1 +#define FAT16 2 +#define FAT32 3 + +#endif // #defined __FS_FAT_H \ No newline at end of file diff --git a/freeldr/freeldr/fs_fat.c b/freeldr/freeldr/fs_fat.c new file mode 100644 index 00000000000..828d1dc828c --- /dev/null +++ b/freeldr/freeldr/fs_fat.c @@ -0,0 +1,541 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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; idwStartCluster, direntry + 26, sizeof(WORD)); + memcpy(&pFatStruct->dwCurrentCluster, direntry + 20, sizeof(WORD)); + pFatStruct->dwStartCluster += (pFatStruct->dwCurrentCluster * 0x10000); + pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster; + + memcpy(&pFatStruct->dwSize, direntry + 28, sizeof(DWORD)); + pFatStruct->dwCurrentReadOffset = 0; + + return TRUE; +} + +/* + * FATGetNumPathParts() + * This function parses a path in the form of dir1\dir2\file1.ext + * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext) + */ +int FATGetNumPathParts(char *name) +{ + int i, num; + + for(i=0,num=0; i<(int)strlen(name); i++) + { + if(name[i] == '\\') + num++; + } + num++; + + return num; +} + +/* + * FATGetFirstNameFromPath() + * This function parses a path in the form of dir1\dir2\file1.ext + * and puts the first name of the path (e.g. "dir1") in buffer + * compatible with the MSDOS directory structure + */ +BOOL FATGetFirstNameFromPath(char *buffer, char *name) +{ + int i; + char temp[260]; + + // Copy all the characters up to the end of the + // string or until we hit a '\' character + // and put them in temp + for(i=0; i<(int)strlen(name); i++) + { + if(name[i] == '\\') + break; + else + temp[i] = name[i]; + } + temp[i] = 0; + + // If the filename is too long then fail + if(strlen(temp) > 12) + return FALSE; + + FATParseFileName(buffer, temp); + + return TRUE; +} + +/* + * FATParseFileName() + * This function parses "name" which is in the form of file.ext + * and puts it in "buffer" in the form of "FILE EXT" which + * is compatible with the MSDOS directory structure + */ +void FATParseFileName(char *buffer, char *name) +{ + int i, j; + + i = 0; + j = 0; + + while(i < 8) + buffer[i++] = (name[j] && (name[j] != '.')) ? toupper(name[j++]) : ' '; + + if(name[j] == '.') + j++; + + while(i < 11) + buffer[i++] = name[j] ? toupper(name[j++]) : ' '; + + buffer[i] = 0; +} + +/* + * FATGetFATEntry() + * returns the FAT entry for a given cluster number + */ +DWORD FATGetFATEntry(DWORD nCluster) +{ + DWORD fat; + int FATOffset; + int ThisFATSecNum; + int ThisFATEntOffset; + int Idx; + BOOL bEntryFound; + + switch(nFATType) + { + case FAT12: + FATOffset = nCluster + (nCluster / 2); + ThisFATSecNum = (FATOffset / nBytesPerSector); + ThisFATEntOffset = (FATOffset % nBytesPerSector); + fat = *((WORD *) (pFileSysData + (ThisFATSecNum * nBytesPerSector) + ThisFATEntOffset)); + if (nCluster & 0x0001) + fat = fat >> 4; /* Cluster number is ODD */ + else + fat = fat & 0x0FFF; /* Cluster number is EVEN */ + + return fat; + break; + case FAT16: + FATOffset = (nCluster * 2); + //ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector); + //ThisFATEntOffset = (FATOffset % nBytesPerSector); + + //if (!ReadOneSector(ThisFATSecNum)) + // return NULL; + + //fat = *((WORD *) &SectorBuffer[ThisFATEntOffset]); + fat = *((WORD *) (pFileSysData + FATOffset)); + + return fat; + break; + case FAT32: + //if (!ReadOneSector(ThisFATSecNum)) + // return NULL; + + //fat = *((DWORD *) &SectorBuffer[ThisFATEntOffset]) & 0x0FFFFFFF; + //return fat; + + // This code manages the fat32 fat table entry cache + // The cache is at address FILESYSADDR which is 128k in size + // The first two sectors will contain an array of DWORDs that + // Specify what fat sector is cached. The first two DWORDs + // should be zero. + FATOffset = (nCluster * 4); + ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector); + ThisFATEntOffset = (FATOffset % nBytesPerSector); + + // Now we go through our cache and see if we already have the sector cached + bEntryFound = FALSE; + for (Idx=2; Idx<256; Idx++) + { + if (((int*)pFat32FATCacheIndex)[Idx] == ThisFATSecNum) + { + bEntryFound = TRUE; + break; + } + } + + if (bEntryFound) + { + // Get the fat entry + fat = (*((DWORD *) (pFat32FATCacheIndex + + (Idx * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF; + } + else + { + if (!ReadOneSector(ThisFATSecNum)) + return NULL; + + // Move each sector down in the cache to make room for new sector + for (Idx=255; Idx>2; Idx--) + { + memcpy(pFat32FATCacheIndex + (Idx * nBytesPerSector), pFat32FATCacheIndex + ((Idx - 1) * nBytesPerSector), nBytesPerSector); + ((int*)pFat32FATCacheIndex)[Idx] = ((int*)pFat32FATCacheIndex)[Idx - 1]; + } + + // Insert it into the cache + memcpy(pFat32FATCacheIndex + (2 * nBytesPerSector), SectorBuffer, nBytesPerSector); + ((int*)pFat32FATCacheIndex)[2] = ThisFATSecNum; + + // Get the fat entry + fat = (*((DWORD *) (pFat32FATCacheIndex + + (2 * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF; + } + + return fat; + break; + } + + return NULL; +} + +/* + * FATOpenFile() + * Tries to open the file 'name' and returns true or false + * for success and failure respectively + */ +BOOL FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct) +{ + if(!FATLookupFile(szFileName, pFatStruct)) + return FALSE; + + /* Fill in file control information */ + pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster; + pFatStruct->dwCurrentReadOffset = 0; + + return TRUE; +} + +/* + * FATReadCluster() + * Reads the specified cluster into memory + * and returns the number of bytes read + */ +int FATReadCluster(DWORD nCluster, char *cBuffer) +{ + int nStartSector; + + nStartSector = ((nCluster - 2) * nSectorsPerCluster) + nDataSectorStart; + + ReadMultipleSectors(nStartSector, nSectorsPerCluster, cBuffer); + + return (nSectorsPerCluster * nBytesPerSector); +} + +/* + * FATRead() + * Reads nNumBytes from open file and + * returns the number of bytes read + */ +int FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer) +{ + int nSectorWithinCluster; + int nOffsetWithinSector; + int nOffsetWithinCluster; + int nNum; + int nBytesRead = 0; + + // If all the data is read return zero + if (pFatStruct->dwCurrentReadOffset >= pFatStruct->dwSize) + return 0; + + // If they are trying to read more than there is to read + // then adjust the amount to read + if ((pFatStruct->dwCurrentReadOffset + nNumBytes) > pFatStruct->dwSize) + nNumBytes = pFatStruct->dwSize - pFatStruct->dwCurrentReadOffset; + + while (nNumBytes) + { + // Check and see if the read offset is aligned to a cluster boundary + // if so great, if not then read the rest of the current cluster + if ((pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector)) != 0) + { + nSectorWithinCluster = ((pFatStruct->dwCurrentReadOffset / nBytesPerSector) % nSectorsPerCluster); + nOffsetWithinSector = (pFatStruct->dwCurrentReadOffset % nBytesPerSector); + nOffsetWithinCluster = (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector)); + + // Read the cluster into the scratch area + FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF); + + nNum = (nSectorsPerCluster * nBytesPerSector) - (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector)); + if (nNumBytes >= nNum) + { + memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNum); + nBytesRead += nNum; + cBuffer += nNum; + pFatStruct->dwCurrentReadOffset += nNum; + pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster); + nNumBytes -= nNum; + } + else + { + memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNumBytes); + nBytesRead += nNumBytes; + cBuffer += nNumBytes; + pFatStruct->dwCurrentReadOffset += nNumBytes; + nNumBytes -= nNumBytes; + } + } + else + { + // Read the cluster into the scratch area + FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF); + + nNum = (nSectorsPerCluster * nBytesPerSector); + if (nNumBytes >= nNum) + { + memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNum); + nBytesRead += nNum; + cBuffer += nNum; + pFatStruct->dwCurrentReadOffset += nNum; + pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster); + nNumBytes -= nNum; + } + else + { + memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNumBytes); + nBytesRead += nNumBytes; + cBuffer += nNumBytes; + pFatStruct->dwCurrentReadOffset += nNumBytes; + nNumBytes -= nNumBytes; + } + } + } + + return nBytesRead; +} + +int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset) +{ + DWORD cluster; + int numclusters; + + numclusters = offset / (nSectorsPerCluster * nBytesPerSector); + for (cluster=pFatStruct->dwStartCluster; numclusters > 0; numclusters--) + cluster = FATGetFATEntry(cluster); + + pFatStruct->dwCurrentCluster = cluster; + pFatStruct->dwCurrentReadOffset = offset; + + return 0; +} diff --git a/freeldr/freeldr/linux.c b/freeldr/freeldr/linux.c new file mode 100644 index 00000000000..003389727ac --- /dev/null +++ b/freeldr/freeldr/linux.c @@ -0,0 +1,101 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "freeldr.h" +#include "asmcode.h" +#include "miscboot.h" +#include "stdlib.h" +#include "fs.h" +#include "tui.h" +#include "linux.h" + +void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line) +{ + FILE file; + char temp[260]; + char bootsector[512]; + char setup[2048]; + int len; + + BootDrive = DriveNum; + BootPartition = Partition; + + if (!OpenDiskDrive(BootDrive, BootPartition)) + { + MessageBox("Failed to open boot drive."); + return; + } + + if (!OpenFile(vmlinuz, &file)) + { + strcpy(temp, vmlinuz); + strcat(temp, " not found."); + MessageBox(temp); + return; + } + + // Read boot sector + if (ReadFile(&file, 512, bootsector) != 512) + { + MessageBox("Disk Read Error"); + return; + } + MessageBox("bootsector loaded"); + + // Read setup code + if (ReadFile(&file, 2048, setup) != 2048) + { + MessageBox("Disk Read Error"); + return; + } + MessageBox("setup loaded"); + + // Read kernel code + len = GetFileSize(&file) - (2048 + 512); + //len = 0x200; + if (ReadFile(&file, len, (void*)0x100000) != len) + { + MessageBox("Disk Read Error"); + return; + } + MessageBox("kernel loaded"); + + // Check for validity + if (*((WORD*)(bootsector + 0x1fe)) != 0xaa55) + { + MessageBox("Invalid boot sector magic (0xaa55)"); + return; + } + if (*((DWORD*)(setup + 2)) != 0x53726448) + { + MessageBox("Invalid setup magic (\"HdrS\")"); + return; + } + + memcpy((void*)0x90000, bootsector, 512); + memcpy((void*)0x90200, setup, 2048); + + RestoreScreen(pScreenBuffer); + showcursor(); + gotoxy(nCursorXPos, nCursorYPos); + + stop_floppy(); + JumpToLinuxBootCode(); +} diff --git a/freeldr/freeldr/linux.h b/freeldr/freeldr/linux.h new file mode 100644 index 00000000000..3f6eb030d7b --- /dev/null +++ b/freeldr/freeldr/linux.h @@ -0,0 +1,27 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_H +#define __LINUX_H + +void JumpToLinuxBootCode(void); // Implemented in boot.S + +void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line); + +#endif // defined __LINUX_H \ No newline at end of file diff --git a/freeldr/freeldr/menu.c b/freeldr/freeldr/menu.c new file mode 100644 index 00000000000..90846db4ba4 --- /dev/null +++ b/freeldr/freeldr/menu.c @@ -0,0 +1,190 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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 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= 0) + { + strcpy(text, "[ Time Remaining: "); + itoa(nTimeOut, temp, 10); + strcat(text, temp); + strcat(text, " ]"); + + DrawText(nOSListBoxRight - strlen(text) - 1, nOSListBoxBottom, text, ATTR(cMenuFgColor, cMenuBgColor)); + } +} \ No newline at end of file diff --git a/freeldr/freeldr/menu.h b/freeldr/freeldr/menu.h new file mode 100644 index 00000000000..ebf085ff534 --- /dev/null +++ b/freeldr/freeldr/menu.h @@ -0,0 +1,27 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MENU_H +#define __MENU_H + +int RunMenu(void); +void InitMenu(void); +void DrawMenu(void); + +#endif // #defined __MENU_H \ No newline at end of file diff --git a/freeldr/freeldr/miscboot.c b/freeldr/freeldr/miscboot.c new file mode 100644 index 00000000000..8b6026ac31d --- /dev/null +++ b/freeldr/freeldr/miscboot.c @@ -0,0 +1,229 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "freeldr.h" +#include "asmcode.h" +#include "miscboot.h" +#include "stdlib.h" +#include "fs.h" +#include "tui.h" + +void LoadAndBootBootSector(int nOSToBoot) +{ + FILE file; + char name[260]; + char value[260]; + char szFileName[1024]; + int i; + + // Find all the message box settings and run them + for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++) + { + ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value); + if (stricmp(name, "MessageBox") == 0) + MessageBox(value); + if (stricmp(name, "MessageLine") == 0) + MessageLine(value); + } + + if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value)) + { + MessageBox("Boot drive not specified for selected OS!"); + return; + } + + BootDrive = atoi(value); + + BootPartition = 0; + if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value)) + BootPartition = atoi(value); + + if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootSector", name, value)) + { + MessageBox("Boot sector file not specified for selected OS!"); + return; + } + + if (!OpenDiskDrive(BootDrive, BootPartition)) + { + MessageBox("Failed to open boot drive."); + return; + } + + strcpy(szFileName, value); + if (!OpenFile(szFileName, &file)) + { + strcat(value, " not found."); + MessageBox(value); + return; + } + + // Read boot sector + if (ReadFile(&file, 512, (void*)0x7c00) != 512) + { + MessageBox("Disk Read Error"); + return; + } + + // Check for validity + if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55) + { + MessageBox("Invalid boot sector magic (0xaa55)"); + return; + } + + RestoreScreen(pScreenBuffer); + showcursor(); + gotoxy(nCursorXPos, nCursorYPos); + + stop_floppy(); + JumpToBootCode(); +} + +void LoadAndBootPartition(int nOSToBoot) +{ + char name[260]; + char value[260]; + int head, sector, cylinder; + int offset; + int i; + + // Find all the message box settings and run them + for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++) + { + ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value); + if (stricmp(name, "MessageBox") == 0) + MessageBox(value); + if (stricmp(name, "MessageLine") == 0) + MessageLine(value); + } + + if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value)) + { + MessageBox("Boot drive not specified for selected OS!"); + return; + } + + BootDrive = atoi(value); + + if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value)) + { + MessageBox("Boot partition not specified for selected OS!"); + return; + } + + BootPartition = atoi(value); + + if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer)) + { + MessageBox("Disk Read Error"); + return; + } + + // Check for validity + if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55) + { + MessageBox("Invalid partition table magic (0xaa55)"); + return; + } + + offset = 0x1BE + ((BootPartition-1) * 0x10); + + // Check for valid partition + if (SectorBuffer[offset + 4] == 0) + { + MessageBox("Invalid boot partition"); + return; + } + + head = SectorBuffer[offset + 1]; + sector = (SectorBuffer[offset + 2] & 0x3F); + cylinder = SectorBuffer[offset + 3]; + if (SectorBuffer[offset + 2] & 0x80) + cylinder += 0x200; + if (SectorBuffer[offset + 2] & 0x40) + cylinder += 0x100; + + // Read partition boot sector + if (!biosdisk(_DISK_READ, BootDrive, head, cylinder, sector, 1, (void*)0x7c00)) + { + MessageBox("Disk Read Error"); + return; + } + + // Check for validity + if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55) + { + MessageBox("Invalid boot sector magic (0xaa55)"); + return; + } + + RestoreScreen(pScreenBuffer); + showcursor(); + gotoxy(nCursorXPos, nCursorYPos); + + stop_floppy(); + JumpToBootCode(); +} + +void LoadAndBootDrive(int nOSToBoot) +{ + char name[260]; + char value[260]; + int i; + + // Find all the message box settings and run them + for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++) + { + ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value); + if (stricmp(name, "MessageBox") == 0) + MessageBox(value); + if (stricmp(name, "MessageLine") == 0) + MessageLine(value); + } + + if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value)) + { + MessageBox("Boot drive not specified for selected OS!"); + return; + } + + BootDrive = atoi(value); + + if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, (void*)0x7c00)) + { + MessageBox("Disk Read Error"); + return; + } + + // Check for validity + if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55) + { + MessageBox("Invalid boot sector magic (0xaa55)"); + return; + } + + RestoreScreen(pScreenBuffer); + showcursor(); + gotoxy(nCursorXPos, nCursorYPos); + + stop_floppy(); + JumpToBootCode(); +} diff --git a/freeldr/freeldr/miscboot.h b/freeldr/freeldr/miscboot.h new file mode 100644 index 00000000000..d6b6ef2dda0 --- /dev/null +++ b/freeldr/freeldr/miscboot.h @@ -0,0 +1,29 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __BOOT_H +#define __BOOT_H + +void JumpToBootCode(void); // Implemented in boot.S + +void LoadAndBootBootSector(int nOSToBoot); +void LoadAndBootPartition(int nOSToBoot); +void LoadAndBootDrive(int nOSToBoot); + +#endif // defined __BOOT_H \ No newline at end of file diff --git a/freeldr/freeldr/options.c b/freeldr/freeldr/options.c new file mode 100644 index 00000000000..8550e24043f --- /dev/null +++ b/freeldr/freeldr/options.c @@ -0,0 +1,395 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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 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 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __OPTIONS_H +#define __OPTIONS_H + +void DoOptionsMenu(void); +void DoDiskOptionsMenu(void); +void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText); +void DoBootPartitionOptionsMenu(int BootDriveNum); +int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle); +void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount); +void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom); + +#endif // #defined __OPTIONS_H \ No newline at end of file diff --git a/freeldr/freeldr/pe.h b/freeldr/freeldr/pe.h new file mode 100644 index 00000000000..c1454f9c7b3 --- /dev/null +++ b/freeldr/freeldr/pe.h @@ -0,0 +1,593 @@ + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + +#define IMAGE_SECTION_CHAR_CODE 0x00000020 +#define IMAGE_SECTION_CHAR_DATA 0x00000040 +#define IMAGE_SECTION_CHAR_BSS 0x00000080 +#define IMAGE_SECTION_CHAR_NON_CACHABLE 0x04000000 +#define IMAGE_SECTION_CHAR_NON_PAGEABLE 0x08000000 +#define IMAGE_SECTION_CHAR_SHARED 0x10000000 +#define IMAGE_SECTION_CHAR_EXECUTABLE 0x20000000 +#define IMAGE_SECTION_CHAR_READABLE 0x40000000 +#define IMAGE_SECTION_CHAR_WRITABLE 0x80000000 + + +#define IMAGE_DOS_MAGIC 0x5a4d +#define IMAGE_PE_MAGIC 0x00004550 + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + WORD e_magic; // Magic number + WORD e_cblp; // Bytes on last page of file + WORD e_cp; // Pages in file + WORD e_crlc; // Relocations + WORD e_cparhdr; // Size of header in paragraphs + WORD e_minalloc; // Minimum extra paragraphs needed + WORD e_maxalloc; // Maximum extra paragraphs needed + WORD e_ss; // Initial (relative) SS value + WORD e_sp; // Initial SP value + WORD e_csum; // Checksum + WORD e_ip; // Initial IP value + WORD e_cs; // Initial (relative) CS value + WORD e_lfarlc; // File address of relocation table + WORD e_ovno; // Overlay number + WORD e_res[4]; // Reserved words + WORD e_oemid; // OEM identifier (for e_oeminfo) + WORD e_oeminfo; // OEM information; e_oemid specific + WORD e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0x160 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_R10000 0x168 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian + + +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + // + // NT additional fields. + // + + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_OS2_GUI 4 +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_GUI 6 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 + +typedef struct _IMAGE_NT_HEADERS { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SECTION_CODE (0x20) +#define IMAGE_SECTION_INITIALIZED_DATA (0x40) +#define IMAGE_SECTION_UNINITIALIZED_DATA (0x80) + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + PDWORD *AddressOfFunctions; + PDWORD *AddressOfNames; + PWORD *AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + WORD Hint; + BYTE Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + + +// Predefined resource types ... there may be some more, but I don't have +// the information yet. .....sang cho..... + +#define RT_NEWRESOURCE 0x2000 +#define RT_ERROR 0x7fff +#define NEWBITMAP (RT_BITMAP|RT_NEWRESOURCE) +#define NEWMENU (RT_MENU|RT_NEWRESOURCE) +#define NEWDIALOG (RT_DIALOG|RT_NEWRESOURCE) + + +// +// Resource Format. +// + +// +// Resource directory consists of two counts, following by a variable length +// array of directory entries. The first count is the number of entries at +// beginning of the array that have actual names associated with each entry. +// The entries are in ascending order, case insensitive strings. The second +// count is the number of entries that immediately follow the named entries. +// This second count identifies the number of entries that have 16-bit integer +// Ids as their name. These entries are also sorted in ascending order. +// +// This structure allows fast lookup by either name or number, but for any +// given resource entry only one form of lookup is supported, not both. +// This is consistant with the syntax of the .RC file and the .RES file. +// + + +// +// Each directory contains the 32-bit Name of the entry and an offset, +// relative to the beginning of the resource directory of the data associated +// with this directory entry. If the name of the entry is an actual text +// string instead of an integer Id, then the high order bit of the name field +// is set to one and the low order 31-bits are an offset, relative to the +// beginning of the resource directory of the string, which is of type +// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the +// low-order 16-bits are the integer Id that identify this resource directory +// entry. If the directory entry is yet another resource directory (i.e. a +// subdirectory), then the high order bit of the offset field will be +// set to indicate this. Otherwise the high bit is clear and the offset +// field points to a resource data entry. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + DWORD Name; + DWORD OffsetToData; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[0]; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + + + +// +// For resource directory entries that have actual string names, the Name +// field of the directory entry points to an object of the following type. +// All of these string objects are stored together after the last resource +// directory entry and before the first resource data object. This minimizes +// the impact of these variable length objects on the alignment of the fixed +// size directory entry objects. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + WORD Length; + WCHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; + + +// +// Each resource data entry describes a leaf node in the resource directory +// tree. It contains an offset, relative to the beginning of the resource +// directory of the data for the resource, a size field that gives the number +// of bytes of data at that offset, a CodePage that should be used when +// decoding code point values within the resource data. Typically for new +// applications the code page would be the unicode code page. +// + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + + +// Menu Resources ... added by .....sang cho.... + +// Menu resources are composed of a menu header followed by a sequential list +// of menu items. There are two types of menu items: pop-ups and normal menu +// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with +// an empty name, zero ID, and zero flags. + +typedef struct _IMAGE_MENU_HEADER{ + WORD wVersion; // Currently zero + WORD cbHeaderSize; // Also zero +} IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER; + +typedef struct _IMAGE_POPUP_MENU_ITEM{ + WORD fItemFlags; + WCHAR szItemText[1]; +} IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM; + +typedef struct _IMAGE_NORMAL_MENU_ITEM{ + WORD fItemFlags; + WORD wMenuID; + WCHAR szItemText[1]; +} IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM; + +#define MI_GRAYED 0x0001 // GRAYED keyword +#define MI_INACTIVE 0x0002 // INACTIVE keyword +#define MI_BITMAP 0x0004 // BITMAP keyword +#define MI_OWNERDRAW 0x0100 // OWNERDRAW keyword +#define MI_CHECKED 0x0008 // CHECKED keyword +#define MI_POPUP 0x0010 // used internally +#define MI_MENUBARBREAK 0x0020 // MENUBARBREAK keyword +#define MI_MENUBREAK 0x0040 // MENUBREAK keyword +#define MI_ENDMENU 0x0080 // used internally + +// Dialog Box Resources .................. added by sang cho. + +// A dialog box is contained in a single resource and has a header and +// a portion repeated for each control in the dialog box. +// The item DWORD IStyle is a standard window style composed of flags found +// in WINDOWS.H. +// The default style for a dialog box is: +// WS_POPUP | WS_BORDER | WS_SYSMENU +// +// The itme marked "Name or Ordinal" are : +// If the first word is an 0xffff, the next two bytes contain an ordinal ID. +// Otherwise, the first one or more WORDS contain a double-null-terminated string. +// An empty string is represented by a single WORD zero in the first location. +// +// The WORD wPointSize and WCHAR szFontName entries are present if the FONT +// statement was included for the dialog box. This can be detected by checking +// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these +// entries will be present. + +typedef struct _IMAGE_DIALOG_BOX_HEADER1{ + DWORD IStyle; + DWORD IExtendedStyle; // New for Windows NT + WORD nControls; // Number of Controls + WORD x; + WORD y; + WORD cx; + WORD cy; +// N_OR_O MenuName; // Name or Ordinal ID +// N_OR_O ClassName; // Name or Ordinal ID +// WCHAR szCaption[]; +// WORD wPointSize; // Only here if FONT set for dialog +// WCHAR szFontName[]; // This too +} IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER; + +typedef union _NAME_OR_ORDINAL{ // Name or Ordinal ID + struct _ORD_ID{ + WORD flgId; + WORD Id; + } ORD_ID; + WCHAR szName[1]; +} NAME_OR_ORDINAL, *PNAME_OR_ORDINAL; + +// The data for each control starts on a DWORD boundary (which may require +// some padding from the previous control), and its format is as follows: + +typedef struct _IMAGE_CONTROL_DATA{ + DWORD IStyle; + DWORD IExtendedStyle; + WORD x; + WORD y; + WORD cx; + WORD cy; + WORD wId; +// N_OR_O ClassId; +// N_OR_O Text; +// WORD nExtraStuff; +} IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA; + +#define BUTTON 0x80 +#define EDIT 0x81 +#define STATIC 0x82 +#define LISTBOX 0x83 +#define SCROLLBAR 0x84 +#define COMBOBOX 0x85 + +// The various statements used in a dialog script are all mapped to these +// classes along with certain modifying styles. The values for these styles +// can be found in WINDOWS.H. All dialog controls have the default styles +// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows: +// +// Statement Default Class Default Styles +// CONTROL None WS_CHILD|WS_VISIBLE +// LTEXT STATIC ES_LEFT +// RTEXT STATIC ES_RIGHT +// CTEXT STATIC ES_CENTER +// LISTBOX LISTBOX WS_BORDER|LBS_NOTIFY +// CHECKBOX BUTTON BS_CHECKBOX|WS_TABSTOP +// PUSHBUTTON BUTTON BS_PUSHBUTTON|WS_TABSTOP +// GROUPBOX BUTTON BS_GROUPBOX +// DEFPUSHBUTTON BUTTON BS_DFPUSHBUTTON|WS_TABSTOP +// RADIOBUTTON BUTTON BS_RADIOBUTTON +// AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX +// AUTO3STATE BUTTON BS_AUTO3STATE +// AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON +// PUSHBOX BUTTON BS_PUSHBOX +// STATE3 BUTTON BS_3STATE +// EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP +// COMBOBOX COMBOBOX None +// ICON STATIC SS_ICON +// SCROLLBAR SCROLLBAR None +/// + +// +// Debug Format +// + +typedef struct _IMAGE_DEBUG_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Type; + DWORD SizeOfData; + DWORD AddressOfRawData; + DWORD PointerToRawData; +} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 + + +typedef struct _IMAGE_DEBUG_MISC { + DWORD DataType; // type of misc data, see defines + DWORD Length; // total length of record, rounded to four + // byte multiple. + BOOL Unicode; // TRUE if data is unicode string + BYTE Reserved[ 3 ]; + BYTE Data[ 1 ]; // Actual data +} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC; + + +// +// Debugging information can be stripped from an image file and placed +// in a separate .DBG file, whose file name part is the same as the +// image file name part (e.g. symbols for CMD.EXE could be stripped +// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED +// flag in the Characteristics field of the file header. The beginning of +// the .DBG file contains the following structure which captures certain +// information from the image file. This allows a debug to proceed even if +// the original image file is not accessable. This header is followed by +// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more +// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in +// the image file contain file offsets relative to the beginning of the +// .DBG file. +// +// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure +// is left in the image file, but not mapped. This allows a debugger to +// compute the name of the .DBG file, from the name of the image in the +// IMAGE_DEBUG_MISC structure. +// + +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { + WORD Signature; + WORD Flags; + WORD Machine; + WORD Characteristics; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD NumberOfSections; + DWORD ExportedNamesSize; + DWORD DebugDirectorySize; + DWORD SectionAlignment; + DWORD Reserved[2]; +} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; + +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 + +#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 +#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the + // old checksum didn't match. + +// +// End Image Format +// + +#define SIZE_OF_NT_SIGNATURE sizeof (DWORD) +#define MAXRESOURCENAME 13 + +/* global macros to define header offsets into file */ +/* offset to PE file signature */ +#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew)) + +/* DOS header identifies the NT PEFile signature dword + the PEFILE header exists just after that dword */ +#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE)) + +/* PE optional header is immediately after PEFile header */ +#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER))) + +/* section headers are immediately after PE optional header */ +#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER) + \ + sizeof (IMAGE_OPTIONAL_HEADER))) + +#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue)) + +typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY +{ + DWORD dwRVAFunctionNameList; + DWORD dwUseless1; + DWORD dwUseless2; + DWORD dwRVAModuleName; + DWORD dwRVAFunctionAddressList; +} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY; + +typedef struct _RELOCATION_DIRECTORY +{ + DWORD VirtualAddress; /* adresse virtuelle du bloc ou se font les relocations */ + DWORD SizeOfBlock; // taille de cette structure + des structures + // relocation_entry qui suivent (ces dernieres sont + // donc au nombre de (SizeOfBlock-8)/2 +} RELOCATION_DIRECTORY, *PRELOCATION_DIRECTORY; + +typedef struct _RELOCATION_ENTRY +{ + WORD TypeOffset; + // (TypeOffset >> 12) est le type + // (TypeOffset&0xfff) est l'offset dans le bloc +} RELOCATION_ENTRY, *PRELOCATION_ENTRY; + +#define TYPE_RELOC_ABSOLUTE 0 +#define TYPE_RELOC_HIGH 1 +#define TYPE_RELOC_LOW 2 +#define TYPE_RELOC_HIGHLOW 3 +#define TYPE_RELOC_HIGHADJ 4 +#define TYPE_RELOC_MIPS_JMPADDR 5 + diff --git a/freeldr/freeldr/ros.S b/freeldr/freeldr/ros.S new file mode 100644 index 00000000000..b10b735b3eb --- /dev/null +++ b/freeldr/freeldr/ros.S @@ -0,0 +1,374 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + .text + .code16 + +#include "asmcode.h" + + /* + * Needed for enabling the a20 address line + */ +empty_8042: + .word 0x00eb,0x00eb // jmp $+2, jmp $+2 + inb $0x64,%al + testb $0x02,%al + jnz empty_8042 + ret + + /* + * Enable the A20 address line (to allow access to over 1mb) + */ + .code32 +EXTERN(_enable_a20) + call switch_to_real + .code16 + + call empty_8042 + movb $0xD1,%al // command write + outb %al,$0x64 + call empty_8042 + mov $0xDF,%al // A20 on + out %al,$0x60 + call empty_8042 + call switch_to_prot + .code32 + + ret + + .code16 + + /* + * Reprogram the PIC because they overlap the Intel defined + * exceptions + */ +reprogram_pic: + movb $0x11,%al // initialization sequence + outb %al,$0x20 // send it to 8259A-1 + .word 0x00eb,0x00eb // jmp $+2, jmp $+2 + outb %al,$0xA0 // and to 8259A-2 + .word 0x00eb,0x00eb + movb $0x40,%al // start of hardware int's (0x20) + outb %al,$0x21 + .word 0x00eb,0x00eb + movb $0x48,%al // start of hardware int's 2 (0x28) + outb %al,$0xA1 + .word 0x00eb,0x00eb + movb $0x04,%al // 8259-1 is master + outb %al,$0x21 + .word 0x00eb,0x00eb + movb $0x02,%al // 8259-2 is slave + outb %al,$0xA1 + .word 0x00eb,0x00eb + movb $0x01,%al // 8086 mode for both + outb %al,$0x21 + .word 0x00eb,0x00eb + outb %al,$0xA1 + .word 0x00eb,0x00eb + movb $0xFF,%al // mask off all interrupts for now + outb %al,$0x21 + .word 0x00eb,0x00eb + outb %al,$0xA1 + ret + + /* + * In: EDI = address + * Out: FS = segment + * DI = base + */ +convert_to_seg: + pushl %eax + + movl %edi,%eax + //shrl $16,%eax + //shll $12,%eax + //movw %ax,%fs + + shrl $4,%eax + movw %ax,%fs + andl $0xf,%edi + + //andl $0xFFFF,%edi + + popl %eax + ret + + /* + * Here we assume the kernel is loaded at 1mb + * This boots the kernel + */ + .code32 +EXTERN(_boot_ros) + call switch_to_real + .code16 + + /* Save cursor position */ + movw $3,%ax //! Reset video mode + int $0x10 + + + movb $10,%bl + movb $12,%ah + int $0x10 + + movw $0x1112,%ax //! Use 8x8 font + xorb %bl,%bl + int $0x10 + movw $0x1200,%ax //! Use alternate print screen + movb $0x20,%bl + int $0x10 + movb $1,%ah //! Define cursor (scan lines 6 to 7) + movw $0x0607,%cx + int $0x10 + + movb $1,%ah + movw $0x600,%cx + int $0x10 + + MOVb $6,%AH //SCROLL ACTIVE PAGE UP + MOVb $0x32,%AL //CLEAR 25 LINES + MOVw $0,%CX //UPPER LEFT OF SCROLL + MOVw $0x314F,%dx //LOWER RIGHT OF SCROLL + MOVb $(1*0x10+1),%bh //USE NORMAL ATTRIBUTE ON BLANKED LINE + INT $0x10 //VIDEO-IO + + + movw $0,%dx + movb $0,%dh + + movb $2,%ah + movb $0,%bh + int $0x10 + + movw $0,%dx + movb $0,%dh + + movb $2,%ah + movb $0,%bh + int $0x10 + + cli + + // The page tables are setup elsewhere + /* + // Map in the lowmem page table (and reuse it for the identity map) + movl _kernel_page_directory_base,%edi + call convert_to_seg + + movl _lowmem_page_table_base,%eax + addl $0x07,%eax + movl %eax,%fs:(%edi) + movl %eax,%fs:0xd00(%edi)//(0xd0000000/(1024*1024))(%edi) + + // Map the page tables from the page directory + movl _kernel_page_directory_base,%eax + addl $0x07,%eax + movl %eax,%fs:0xf00(%edi)//(0xf0000000/(1024*1024))(%edi) + + // Map in the kernel page table + movl _system_page_table_base,%eax + addl $0x07,%eax + movl %eax,%fs:0xc00(%edi)//(0xc0000000/(1024*1024))(%edi) + + // Setup the lowmem page table + movl _lowmem_page_table_base,%edi + call convert_to_seg + + movl $0,%ebx +l9: + movl %ebx,%eax + shll $12,%eax // ebx = ebx * 4096 + addl $07,%eax // user, rw, present + movl %eax,%fs:(%edi,%ebx,4) + incl %ebx + cmpl $1024,%ebx + jl l9 + + // Setup the system page table + movl _system_page_table_base,%edi + call convert_to_seg + + movl $07,%eax +l8: + movl %eax,%edx + addl _start_kernel,%edx + movl %edx,%fs:(%edi) + addl $4,%edi + addl $0x1000,%eax + cmpl $0x100007,%eax + jl l8 + */ + + /* + * Load the page directory into cr3 + */ + movl _kernel_page_directory_base,%eax + movl %eax,%cr3 + + /* + * Setup various variables + */ + movw %ds,%bx + movzwl %bx,%eax + shll $4,%eax + addl %eax,kernel_gdtbase + + //call enable_a20 // enabled elsewhere + call reprogram_pic + + /* + * Load stack + */ + movw %ds,%bx + movzwl %bx,%eax + shll $4,%eax + addl $real_stack_end,%eax + movl %eax,real_stack_base + movl real_stack_base,%esp + movl _boot_param_struct_base,%edx + + /* + * load gdt + */ + lgdt kernel_gdtptr + + /* + * Enter pmode and clear prefetch queue + */ + movl %cr0,%eax + orl $0x80010001,%eax + /*orl $0x80000001,%eax*/ + movl %eax,%cr0 + jmp next +next: + /* + * NOTE: This must be position independant (no references to + * non absolute variables) + */ + + /* + * Initalize segment registers + */ + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%ss + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + + /* + * Initalize eflags + */ + pushl $0 + popfl + + /* + * Jump to start of 32 bit code at 0xc0000000 + 0x1000 + */ + pushl %edx + pushl $0 + ljmpl $KERNEL_CS,$(KERNEL_BASE+0x1000) + + + .p2align 2 /* force 4-byte alignment */ +kernel_gdt: + .word 0 // Zero descriptor + .word 0 + .word 0 + .word 0 + + //.word 0x0000 // User code descriptor + //.word 0x0000 // base: 0h limit: 3gb + //.word 0xfa00 + //.word 0x00cc + + //.word 0x0000 // User data descriptor + //.word 0x0000 // base: 0h limit: 3gb + //.word 0xf200 + //.word 0x00cc + + //.word 0x0000 + //.word 0x0000 + //.word 0x0000 + //.word 0x0000 + + .word 0xffff // Kernel code descriptor + .word 0x0000 // + .word 0x9a00 // base 0h limit 4gb + .word 0x00cf + + .word 0xffff // Kernel data descriptor + .word 0x0000 // + .word 0x9200 // base 0h limit 4gb + .word 0x00cf + + /* TSS space */ + //.rept NR_TASKS + //.word 0 + //.word 0 + //.word 0 + //.word 0 + //.endr + +kernel_gdtptr: + .word (((6+NR_TASKS)*8)-1) /* Limit */ +kernel_gdtbase: + .long kernel_gdt /* Base Address */ + +EXTERN(_boot_param_struct_base) + .long 0 +EXTERN(_start_mem) + .long 0 +EXTERN(_kernel_page_directory_base) + .long 0 +EXTERN(_system_page_table_base) + .long 0 +EXTERN(_lowmem_page_table_base) + .long 0 +EXTERN(_start_kernel) + .long 0 +EXTERN(_load_base) + .long 0 + +/* boot_param structure */ +EXTERN(_boot_parameters) + .long 0 // Magic + .long 0 // Cursor X + .long 0 // Cursor Y + .long 0 // nr_files + .long 0 // start_mem + .long 0 // end_mem + + .rept 64 + .long 0 // List of module lengths (terminated by a 0) + .endr + + .rept 256 + .byte 0 // Kernel parameter string + .endr + +/* Our initial stack */ +real_stack: + .rept 1024 + .byte 0 + .endr +real_stack_end: + +real_stack_base: + .long 0 diff --git a/freeldr/freeldr/rosboot.c b/freeldr/freeldr/rosboot.c new file mode 100644 index 00000000000..371fe14b4c7 --- /dev/null +++ b/freeldr/freeldr/rosboot.c @@ -0,0 +1,390 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "freeldr.h" +#include "asmcode.h" +#include "rosboot.h" +#include "stdlib.h" +#include "fs.h" +#include "tui.h" + +extern boot_param boot_parameters; // Boot parameter structure passed to the kernel +extern int boot_param_struct_base; // Physical address of the boot parameters structure +extern int start_mem; // Start of the continuous range of physical kernel memory +extern int kernel_page_directory_base; // Physical address of the kernel page directory +extern int system_page_table_base; // Physical address of the system page table +extern int lowmem_page_table_base; // Physical address of the low mem page table +extern int start_kernel; // Physical address of the start of kernel code +extern int load_base; // Physical address of the loaded kernel modules + +static int next_load_base; + +void LoadAndBootReactOS(int nOSToBoot) +{ + FILE file; + char name[1024]; + char value[1024]; + char szFileName[1024]; + int i; + int nNumDriverFiles=0; + int nNumFilesLoaded=0; + + /* + * Enable a20 so we can load at 1mb and initialize the page tables + */ + //enable_a20(); // enabled in freeldr.c + ReactOSMemInit(); + + // Setup kernel parameters + boot_param_struct_base = (int)&boot_parameters; + boot_parameters.magic = 0xdeadbeef; + boot_parameters.cursorx = 0; + boot_parameters.cursory = 0; + boot_parameters.nr_files = 0; + boot_parameters.start_mem = start_mem; + boot_parameters.end_mem = load_base; + boot_parameters.kernel_parameters[0] = 0; + + next_load_base = load_base; + + /* + * Read the optional kernel parameters + */ + if(ReadSectionSettingByName(OSList[nOSToBoot].name, "Options", name, value)) + { + strcpy(boot_parameters.kernel_parameters,value); + } + + /* + * Find the kernel image name + */ + if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "Kernel", name, value)) + { + MessageBox("Kernel image file not specified for selected operating system."); + return; + } + + /* + * Get the boot partition + */ + BootPartition = 0; + if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value)) + BootPartition = atoi(value); + + /* + * Make sure the boot drive is set in the .ini file + */ + if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value)) + { + MessageBox("Boot drive not specified for selected operating system."); + return; + } + + DrawBackdrop(); + + DrawStatusText(" Loading..."); + DrawProgressBar(0); + + /* + * Set the boot drive and try to open it + */ + BootDrive = atoi(value); + if (!OpenDiskDrive(BootDrive, BootPartition)) + { + MessageBox("Failed to open boot drive."); + return; + } + + /* + * Parse the ini file and count the kernel and drivers + */ + for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++) + { + /* + * Read the setting and check if it's a driver + */ + ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value); + if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0)) + nNumDriverFiles++; + } + + /* + * Parse the ini file and load the kernel and + * load all the drivers specified + */ + for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++) + { + /* + * Read the setting and check if it's a driver + */ + ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value); + if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0)) + { + /* + * Set the name and try to open the PE image + */ + strcpy(szFileName, value); + if (!OpenFile(szFileName, &file)) + { + strcat(value, " not found."); + MessageBox(value); + return; + } + + /* + * Update the status bar with the current file + */ + strcpy(name, " Reading "); + strcat(name, value); + while (strlen(name) < 80) + strcat(name, " "); + DrawStatusText(name); + + /* + * Load the driver + */ + ReactOSLoadPEImage(&file); + + nNumFilesLoaded++; + DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles); + + // Increment the number of files we loaded + boot_parameters.nr_files++; + } + else if (stricmp(name, "MessageBox") == 0) + { + DrawStatusText(" Press ENTER to continue"); + MessageBox(value); + } + else if (stricmp(name, "MessageLine") == 0) + MessageLine(value); + else if (stricmp(name, "ReOpenBootDrive") == 0) + { + if (!OpenDiskDrive(BootDrive, BootPartition)) + { + MessageBox("Failed to open boot drive."); + return; + } + } + } + + /* + * End the list of modules we load with a zero length entry + * and update the end of kernel mem + */ + boot_parameters.module_lengths[boot_parameters.nr_files] = 0; + boot_parameters.end_mem = next_load_base; + + /* + * Clear the screen and redraw the backdrop and status bar + */ + DrawBackdrop(); + DrawStatusText(" Press any key to boot"); + + /* + * Wait for user + */ + strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot "); + strcat(name, OSList[nOSToBoot].name); + strcat(name, "."); + //MessageBox(name); + + RestoreScreen(pScreenBuffer); + + /* + * Now boot the kernel + */ + stop_floppy(); + ReactOSBootKernel(); +} + +void ReactOSMemInit(void) +{ + int base; + + /* Calculate the start of extended memory */ + base = 0x100000; + + /* Set the start of the page directory */ + kernel_page_directory_base = base; + + /* + * Set the start of the continuous range of physical memory + * occupied by the kernel + */ + start_mem = base; + base += 0x1000; + + /* Calculate the start of the system page table (0xc0000000 upwards) */ + system_page_table_base = base; + base += 0x1000; + + /* Calculate the start of the page table to map the first 4mb */ + lowmem_page_table_base = base; + base += 0x1000; + + /* Set the position for the first module to be loaded */ + load_base = base; + + /* Set the address of the start of kernel code */ + start_kernel = base; +} + +void ReactOSBootKernel(void) +{ + int i; + int *pPageDirectory = (int *)kernel_page_directory_base; + int *pLowMemPageTable = (int *)lowmem_page_table_base; + int *pSystemPageTable = (int *)system_page_table_base; + + /* Zero out the kernel page directory */ + for(i=0; i<1024; i++) + pPageDirectory[i] = 0; + + /* Map in the lowmem page table */ + pPageDirectory[(0x00/4)] = lowmem_page_table_base + 0x07; + + /* Map in the lowmem page table (and reuse it for the identity map) */ + pPageDirectory[(0xd00/4)] = lowmem_page_table_base + 0x07; + + /* Map the page tables from the page directory */ + pPageDirectory[(0xf00/4)] = kernel_page_directory_base + 0x07; + + /* Map in the kernel page table */ + pPageDirectory[(0xc00/4)] = system_page_table_base + 0x07; + + /* Setup the lowmem page table */ + for(i=0; i<1024; i++) + pLowMemPageTable[i] = (i * 4096) + 0x07; + + /* Setup the system page table */ + for(i=0; i<1024; i++) + pSystemPageTable[i] = ((i * 4096) + start_kernel) + 0x07; + + boot_ros(); +} + +BOOL ReactOSLoadPEImage(FILE *pImage) +{ + unsigned int Idx, ImageBase; + PULONG PEMagic; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptionalHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + + ImageBase = next_load_base; + boot_parameters.module_lengths[boot_parameters.nr_files] = 0; + + /* + * Load the headers + */ + ReadFile(pImage, 0x1000, (void *)next_load_base); + + /* + * Get header pointers + */ + PEDosHeader = (PIMAGE_DOS_HEADER) next_load_base; + PEMagic = (PULONG) ((unsigned int) next_load_base + + PEDosHeader->e_lfanew); + PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) next_load_base + + PEDosHeader->e_lfanew + sizeof(ULONG)); + PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) next_load_base + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)); + PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) next_load_base + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + + sizeof(IMAGE_OPTIONAL_HEADER)); + + /* + * Check file magic numbers + */ + if(PEDosHeader->e_magic != IMAGE_DOS_MAGIC) + { + MessageBox("Incorrect MZ magic"); + return FALSE; + } + if(PEDosHeader->e_lfanew == 0) + { + MessageBox("Invalid lfanew offset"); + return 0; + } + if(*PEMagic != IMAGE_PE_MAGIC) + { + MessageBox("Incorrect PE magic"); + return 0; + } + if(PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386) + { + MessageBox("Incorrect Architecture"); + return 0; + } + + /* + * Get header size and bump next_load_base + */ + next_load_base += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment); + boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment); + boot_parameters.end_mem += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment); + + /* + * Copy image sections into virtual section + */ +// memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData); +// CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData); +// CurrentSize = 0; + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + /* + * Copy current section into current offset of virtual section + */ + if (PESectionHeaders[Idx].Characteristics & + (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA)) + { + //memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase, + // (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData), + // PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/); + + //MessageBox("loading a section"); + fseek(pImage, PESectionHeaders[Idx].PointerToRawData); + ReadFile(pImage, PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/, (void *)next_load_base); + //printf("PointerToRawData: %x\n", PESectionHeaders[Idx].PointerToRawData); + //printf("bytes at next_load_base: %x\n", *((unsigned long *)next_load_base)); + //getch(); + } + else + { + //memset(PESectionHeaders[Idx].VirtualAddress + DriverBase, + // '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/); + + //MessageBox("zeroing a section"); + memset((void *)next_load_base, '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/); + } + + PESectionHeaders[Idx].PointerToRawData = next_load_base - ImageBase; + + next_load_base += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment); + boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment); + boot_parameters.end_mem += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment); + + //DrawProgressBar((Idx * 100) / PEFileHeader->NumberOfSections); + } + + return TRUE; +} \ No newline at end of file diff --git a/freeldr/freeldr/rosboot.h b/freeldr/freeldr/rosboot.h new file mode 100644 index 00000000000..19b449e56f4 --- /dev/null +++ b/freeldr/freeldr/rosboot.h @@ -0,0 +1,75 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ROSBOOT_H +#define __ROSBOOT_H + +#include "freeldr.h" +#include "stdlib.h" +#include "pe.h" + +#define PACKED __attribute__((packed)) + +void LoadAndBootReactOS(int nOSToBoot); +void ReactOSMemInit(void); +void ReactOSBootKernel(void); +BOOL ReactOSLoadPEImage(FILE *pImage); +void enable_a20(void); +void boot_ros(void); + + +// WARNING: +// This structure is prototyped here but allocated in ros.S +// if you change this prototype make sure to update ros.S +typedef struct +{ + /* + * Magic value (useless really) + */ + unsigned int magic; + + /* + * Cursor position + */ + unsigned int cursorx; + unsigned int cursory; + + /* + * Number of files (including the kernel) loaded + */ + unsigned int nr_files; + + /* + * Range of physical memory being used by the system + */ + unsigned int start_mem; + unsigned int end_mem; + + /* + * List of module lengths (terminated by a 0) + */ + unsigned int module_lengths[64]; + + /* + * Kernel parameter string + */ + char kernel_parameters[256]; +} boot_param PACKED; + +#endif // defined __ROSBOOT_H \ No newline at end of file diff --git a/freeldr/freeldr/stdlib.c b/freeldr/freeldr/stdlib.c new file mode 100644 index 00000000000..e90a7eba390 --- /dev/null +++ b/freeldr/freeldr/stdlib.c @@ -0,0 +1,306 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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 + */ +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 + */ +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=0; i--) + { + if((str[i] < '0') || (str[i] > '9')) + break; + + if(i == (strlen(str)-1)) + result += (str[i] - '0'); + else + { + result += (str[i] - '0') * (j * base); + j *= base; + } + } + + return result; +} diff --git a/freeldr/freeldr/stdlib.h b/freeldr/freeldr/stdlib.h new file mode 100644 index 00000000000..e222b5c9d4a --- /dev/null +++ b/freeldr/freeldr/stdlib.h @@ -0,0 +1,74 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __STDLIB_H +#define __STDLIB_H + +#include "fs.h" + +void putchar(int ch); // Implemented in asmcode.S +void clrscr(void); // Implemented in asmcode.S +int kbhit(void); // Implemented in asmcode.S +int getch(void); // Implemented in asmcode.S +void gotoxy(int x, int y); // Implemented in asmcode.S +int getyear(void); // Implemented in asmcode.S +int getday(void); // Implemented in asmcode.S +int getmonth(void); // Implemented in asmcode.S +int gethour(void); // Implemented in asmcode.S +int getminute(void); // Implemented in asmcode.S +int getsecond(void); // Implemented in asmcode.S +void hidecursor(void); // Implemented in asmcode.S +void showcursor(void); // Implemented in asmcode.S +int wherex(void); // Implemented in asmcode.S +int wherey(void); // Implemented in asmcode.S + +int strlen(char *str); +char *strcpy(char *dest, char *src); +char *strcat(char *dest, char *src); +int strcmp(const char *string1, const char *string2); +int stricmp(const char *string1, const char *string2); +char *itoa(int value, char *string, int radix); +int toupper(int c); +int tolower(int c); +int memcmp(const void *buf1, const void *buf2, size_t count); +void *memcpy(void *dest, const void *src, size_t count); +void *memset(void *dest, int c, size_t count); +char *fgets(char *string, int n, FILE *stream); +int atoi(char *string); + + +void print(char *str); +void printf(char *fmt, ...); + +int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S +void stop_floppy(void); // Implemented in asmcode.S +int get_heads(int drive); // Implemented in asmcode.S +int get_cylinders(int drive); // Implemented in asmcode.S +int get_sectors(int drive); // Implemented in asmcode.S + +/* Values for biosdisk() */ +#define _DISK_RESET 0 // Unimplemented +#define _DISK_STATUS 1 // Unimplemented +#define _DISK_READ 2 // Reads a sector into memory +#define _DISK_WRITE 3 // Unimplemented +#define _DISK_VERIFY 4 // Unimplemented +#define _DISK_FORMAT 5 // Unimplemented + + +#endif // defined __STDLIB_H \ No newline at end of file diff --git a/freeldr/freeldr/tui.c b/freeldr/freeldr/tui.c new file mode 100644 index 00000000000..4ccf5b14be3 --- /dev/null +++ b/freeldr/freeldr/tui.c @@ -0,0 +1,572 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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, "", 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(nVertStyle == VERT) + { + cULCorner = HD_UL; + cURCorner = HD_UR; + cLLCorner = HD_LL; + cLRCorner = HD_LR; + } + else // nVertStyle == D_VERT + { + cULCorner = D_UL; + cURCorner = D_UR; + cLLCorner = D_LL; + cLRCorner = D_LR; + } + } + + // Fill in box background + if(bFill) + FillArea(nLeft, nTop, nRight, nBottom, ' ', cAttr); + + // Fill in corners + FillArea(nLeft, nTop, nLeft, nTop, cULCorner, cAttr); + FillArea(nRight, nTop, nRight, nTop, cURCorner, cAttr); + FillArea(nLeft, nBottom, nLeft, nBottom, cLLCorner, cAttr); + FillArea(nRight, nBottom, nRight, nBottom, cLRCorner, cAttr); + + // Fill in left line + FillArea(nLeft, nTop+1, nLeft, nBottom-1, cVert, cAttr); + // Fill in top line + FillArea(nLeft+1, nTop, nRight-1, nTop, cHorz, cAttr); + // Fill in right line + FillArea(nRight, nTop+1, nRight, nBottom-1, cVert, cAttr); + // Fill in bottom line + FillArea(nLeft+1, nBottom, nRight-1, nBottom, cHorz, cAttr); + + if(bShadow) + DrawShadow(nLeft, nTop, nRight, nBottom); +} + +/* + * DrawText() + * This function assumes coordinates are one-based + */ +void DrawText(int nX, int nY, char *text, char cAttr) +{ + char *screen = (char *)SCREEN_MEM; + int i, j; + + nX--; + nY--; + + // Draw the text + for(i=nX, j=0; text[j]; i++,j++) + { + screen[((nY*2)*nScreenWidth)+(i*2)] = text[j]; + screen[((nY*2)*nScreenWidth)+(i*2)+1] = cAttr; + } +} + +void DrawStatusText(char *text) +{ + int i; + + DrawText(1, nScreenHeight, text, ATTR(cStatusBarFgColor, cStatusBarBgColor)); + + for(i=strlen(text)+1; i<=nScreenWidth; i++) + DrawText(i, nScreenHeight, " ", ATTR(cStatusBarFgColor, cStatusBarBgColor)); +} + +void UpdateDateTime(void) +{ + char date[260]; + char time[260]; + char temp[20]; + int hour, minute, second, bPM=FALSE; + + switch(getmonth()) + { + case 1: + strcpy(date, "January "); + break; + case 2: + strcpy(date, "February "); + break; + case 3: + strcpy(date, "March "); + break; + case 4: + strcpy(date, "April "); + break; + case 5: + strcpy(date, "May "); + break; + case 6: + strcpy(date, "June "); + break; + case 7: + strcpy(date, "July "); + break; + case 8: + strcpy(date, "August "); + break; + case 9: + strcpy(date, "September "); + break; + case 10: + strcpy(date, "October "); + break; + case 11: + strcpy(date, "November "); + break; + case 12: + strcpy(date, "December "); + break; + } + itoa(getday(), temp, 10); + if((getday() == 1) || (getday() == 21) || (getday() == 31)) + strcat(temp, "st"); + else if((getday() == 2) || (getday() == 22)) + strcat(temp, "nd"); + else if((getday() == 3) || (getday() == 23)) + strcat(temp, "rd"); + else + strcat(temp, "th"); + + strcat(date, temp); + strcat(date, " "); + itoa(getyear(), temp, 10); + strcat(date, temp); + + // Draw the date + DrawText(nScreenWidth-strlen(date)-1, 2, date, ATTR(cTitleBoxFgColor, cTitleBoxBgColor)); + + hour = gethour(); + if(hour > 12) + { + hour -= 12; + bPM = TRUE; + } + if (hour == 0) + hour = 12; + minute = getminute(); + second = getsecond(); + itoa(hour, temp, 10); + strcpy(time, " "); + strcat(time, temp); + strcat(time, ":"); + itoa(minute, temp, 10); + if(minute < 10) + strcat(time, "0"); + strcat(time, temp); + strcat(time, ":"); + itoa(second, temp, 10); + if(second < 10) + strcat(time, "0"); + strcat(time, temp); + if(bPM) + strcat(time, " PM"); + else + strcat(time, " AM"); + + // Draw the time + DrawText(nScreenWidth-strlen(time)-1, 3, time, ATTR(cTitleBoxFgColor, cTitleBoxBgColor)); +} + +void SaveScreen(char *buffer) +{ + char *screen = (char *)SCREEN_MEM; + int i; + + for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++) + buffer[i] = screen[i]; +} + +void RestoreScreen(char *buffer) +{ + char *screen = (char *)SCREEN_MEM; + int i; + + for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++) + screen[i] = buffer[i]; +} + +void MessageBox(char *text) +{ + int width = 8; + int height = 1; + int curline = 0; + int i , j, k; + int x1, x2, y1, y2; + char savebuffer[8000]; + char temp[260]; + char key; + + SaveScreen(savebuffer); + strcat(szMessageBoxLineText, text); + + // Find the height + for(i=0; i width) + width = k; + + k = 0; + j++; + } + + // Calculate box area + x1 = (nScreenWidth - (width+2))/2; + x2 = x1 + width + 3; + y1 = ((nScreenHeight - height - 2)/2) + 1; + y2 = y1 + height + 4; + + // Draw the box + DrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMessageBoxFgColor, cMessageBoxBgColor)); + + // Draw the text + for(i=0,j=0; i 100) + nPos = 100; + + left = (nScreenWidth - width - 4) / 2; + right = left + width + 3; + top = (nScreenHeight - height - 2) / 2; + top += 4; + bottom = top + height + 1; + + // Draw the box + DrawBox(left, top, right, bottom, VERT, HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor)); + + // Draw the "Loading..." text + DrawText(70/2, top+1, "Loading...", ATTR(cTextColor, cMenuBgColor)); + + // Draw the percent complete + for(i=0; i<(nPos/2); i++) + DrawText(left+2+i, top+2, "\xDB", ATTR(cTextColor, cMenuBgColor)); + + // Draw the rest + for(; i<50; i++) + DrawText(left+2+i, top+2, "\xB2", ATTR(cTextColor, cMenuBgColor)); + + UpdateDateTime(); +} \ No newline at end of file diff --git a/freeldr/freeldr/tui.h b/freeldr/freeldr/tui.h new file mode 100644 index 00000000000..8dc6cf0914f --- /dev/null +++ b/freeldr/freeldr/tui.h @@ -0,0 +1,162 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000 Brian Palmer + * + * 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 __TUI_H +#define __TUI_H + +#define SCREEN_MEM 0xB8000 + +extern int nScreenWidth; // Screen Width +extern int nScreenHeight; // Screen Height + +extern char cStatusBarFgColor; // Status bar foreground color +extern char cStatusBarBgColor; // Status bar background color +extern char cBackdropFgColor; // Backdrop foreground color +extern char cBackdropBgColor; // Backdrop background color +extern char cBackdropFillStyle; // Backdrop fill style +extern char cTitleBoxFgColor; // Title box foreground color +extern char cTitleBoxBgColor; // Title box background color +extern char cMessageBoxFgColor; // Message box foreground color +extern char cMessageBoxBgColor; // Message box background color +extern char cMenuFgColor; // Menu foreground color +extern char cMenuBgColor; // Menu background color +extern char cTextColor; // Normal text color +extern char cSelectedTextColor; // Selected text color +extern char cSelectedTextBgColor; // Selected text background color +extern char szTitleBoxTitleText[260]; // Title box's title text + +// Fills the entire screen with a backdrop +void DrawBackdrop(void); +// Fills the area specified with cFillChar and cAttr +void FillArea(int nLeft, int nTop, int nRight, int nBottom, char cFillChar, char cAttr /* Color Attributes */); +// Draws a shadow on the bottom and right sides of the area specified +void DrawShadow(int nLeft, int nTop, int nRight, int nBottom); +// Draws a box around the area specified +void DrawBox(int nLeft, int nTop, int nRight, int nBottom, int nVertStyle, int nHorzStyle, int bFill, int bShadow, char cAttr); +// Draws text at coordinates specified +void DrawText(int nX, int nY, char *text, char cAttr); +// Draws text at the very bottom line on the screen +void DrawStatusText(char *text); +// Updates the date and time +void UpdateDateTime(void); +// Saves the screen so that it can be restored later +void SaveScreen(char *buffer); +// Restores the screen from a previous save +void RestoreScreen(char *buffer); +// Displays a message box on the screen with an ok button +void MessageBox(char *text); +// Adds a line of text to the message box buffer +void MessageLine(char *text); +// Returns true if color is valid +BOOL IsValidColor(char *color); +// Converts the text color into it's equivalent color value +char TextToColor(char *color); +// Returns true if fill is valid +BOOL IsValidFillStyle(char *fill); +// Converts the text fill into it's equivalent fill value +char TextToFillStyle(char *fill); +// Draws the progress bar showing nPos percent filled +void DrawProgressBar(int nPos); + +/* + * Combines the foreground and background colors into a single attribute byte + */ +#define ATTR(cFore, cBack) ((cBack << 4)|cFore) + +/* + * Fill styles for DrawBackdrop() + */ +#define LIGHT_FILL 0xB0 +#define MEDIUM_FILL 0xB1 +#define DARK_FILL 0xB2 + +/* + * Screen colors + */ +#define COLOR_BLACK 0 +#define COLOR_BLUE 1 +#define COLOR_GREEN 2 +#define COLOR_CYAN 3 +#define COLOR_RED 4 +#define COLOR_MAGENTA 5 +#define COLOR_BROWN 6 +#define COLOR_GRAY 7 + +#define COLOR_DARKGRAY 8 +#define COLOR_LIGHTBLUE 9 +#define COLOR_LIGHTGREEN 10 +#define COLOR_LIGHTCYAN 11 +#define COLOR_LIGHTRED 12 +#define COLOR_LIGHTMAGENTA 13 +#define COLOR_YELLOW 14 +#define COLOR_WHITE 15 + +/* Add COLOR_BLINK to a background to cause blinking */ +#define COLOR_BLINK 8 + +/* + * Defines for IBM box drawing characters + */ +#define HORZ (0xc4) /* Single horizontal line */ +#define D_HORZ (0xcd) /* Double horizontal line.*/ +#define VERT (0xb3) /* Single vertical line */ +#define D_VERT (0xba) /* Double vertical line. */ + +/* Definitions for corners, depending on HORIZ and VERT */ +#define UL (0xda) +#define UR (0xbf) /* HORZ and VERT */ +#define LL (0xc0) +#define LR (0xd9) + +#define D_UL (0xc9) +#define D_UR (0xbb) /* D_HORZ and D_VERT */ +#define D_LL (0xc8) +#define D_LR (0xbc) + +#define HD_UL (0xd5) +#define HD_UR (0xb8) /* D_HORZ and VERT */ +#define HD_LL (0xd4) +#define HD_LR (0xbe) + +#define VD_UL (0xd6) +#define VD_UR (0xb7) /* HORZ and D_VERT */ +#define VD_LL (0xd3) +#define VD_LR (0xbd) + +// Key codes +#define KEY_EXTENDED 0x00 +#define KEY_ENTER 0x0D +#define KEY_SPACE 0x20 +#define KEY_UP 0x48 +#define KEY_DOWN 0x50 +#define KEY_LEFT 0x4B +#define KEY_RIGHT 0x4D +#define KEY_ESC 0x1B +#define KEY_F1 0x3B +#define KEY_F2 0x3C +#define KEY_F3 0x3D +#define KEY_F4 0x3E +#define KEY_F5 0x3F +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 +#define KEY_F10 0x44 + +#endif // #defined __TUI_H \ No newline at end of file diff --git a/freeldr/install.bat b/freeldr/install.bat new file mode 100644 index 00000000000..4abeb52e495 --- /dev/null +++ b/freeldr/install.bat @@ -0,0 +1,5 @@ +cd bootsect +call install.bat +cd.. +copy freeldr.sys a:\ +copy freeldr.ini a:\ \ No newline at end of file diff --git a/freeldr/notes.txt b/freeldr/notes.txt new file mode 100644 index 00000000000..8dcc68e76a8 --- /dev/null +++ b/freeldr/notes.txt @@ -0,0 +1,18 @@ +FreeLoader notes + +To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code +FreeLoader does not currently work with extended partitions. +Linux booting support needs to be added. +ext2 filesystem support needs to be added. + +Current memory layout: + +0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data +0000:1000 - 0000:6FFF: Real mode stack area +0000:7000 - xxxx:xxxx: FreeLoader program & data area +xxxx:xxxx - 6000:0000: Protected mode stack area & heap +6000:0000 - 6000:C000: Filesystem data buffer +6000:C000 - 7000:0000: FREELDR.INI loaded here +7000:0000 - 7000:FFFF: scratch area for any function's use (ie sector buffer for biosdisk()) - can be overwritten by any function +8000:0000 - 9000:FFFF: fat table entry buffer +A000:0000 - FFFF:FFFF: reserved