Full memory management support (memory.c & memory.h & mem.S)

Preliminary debug code (debug.c & debug.h)
Reworked .ini file code (parseini.c & parseini.h)
Size optimizations (fat.asm & fat32.asm)
FAT12/16 boot sector now fully understands the FAT (fat.asm)

svn path=/trunk/; revision=2049
This commit is contained in:
Brian Palmer 2001-07-06 22:05:05 +00:00
parent e575ed9544
commit 17dc9b5270
34 changed files with 1891 additions and 1181 deletions

43
freeldr/Makefile Normal file
View file

@ -0,0 +1,43 @@
#
# FreeLoader
# Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export NASM = nasm
export MAKE = make
.PHONY : bootsect freeldr install clean
all: bootsect freeldr install
bootsect:
$(MAKE) -C bootsect
freeldr: bootsect
$(MAKE) -C freeldr
install:
$(MAKE) -C install
clean:
$(RM) *.bin

View file

@ -1,256 +0,0 @@
; 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 224
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

View file

@ -1,2 +0,0 @@
nasm -o bootsect.bin -f bin bootsect.asm
nasm -o btsect32.bin -f bin btsect32.asm

54
freeldr/bootsect/Makefile Normal file
View file

@ -0,0 +1,54 @@
#
# FreeLoader
# Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export NASM = nasm
.PHONY : clean
all: fat.bin fat32.bin bin2c.exe split.exe stubit.exe
fat.bin: fat.asm bin2c.exe split.exe
$(NASM) -o fat_tmp.bin -f bin fat.asm
split fat_tmp.bin fat.bin fatstub.bin 512
$(RM) fat_tmp.bin
bin2c fat.bin fat.h fat_data
fat32.bin: fat32.asm bin2c.exe
$(NASM) -o fat32.bin -f bin fat32.asm
bin2c fat32.bin fat32.h fat32_data
bin2c.exe: bin2c.c
$(CC) -o bin2c.exe bin2c.c
split.exe: split.c
$(CC) -o split.exe split.c
stubit.exe: stubit.c
$(CC) -o stubit.exe stubit.c
clean:
$(RM) *.bin
$(RM) *.exe
$(RM) *.h

View file

@ -1,32 +1,31 @@
#include <stdio.h>
char in_filename[260];
char out_filename[260];
FILE *in;
FILE *out;
int main(void)
int main(int argc, char *argv[])
{
unsigned char ch;
int cnt = 0;
printf("Enter data filename: ");
scanf("%s", in_filename);
printf("Enter output filename: ");
scanf("%s", out_filename);
if (argc < 4)
{
printf("usage: bin2c infile.bin outfile.h array_name\n");
return -1;
}
if ((in = fopen(in_filename, "rb")) == NULL)
if ((in = fopen(argv[1], "rb")) == NULL)
{
printf("Couldn't open data file.\n");
return 0;
return -1;
}
if ((out = fopen(out_filename, "wb")) == NULL)
if ((out = fopen(argv[2], "wb")) == NULL)
{
printf("Couldn't open output file.\n");
return 0;
return -1;
}
fprintf(out, "unsigned char data[] = {\n");
fprintf(out, "unsigned char %s[] = {\n", argv[3]);
ch = fgetc(in);
while (!feof(in))

View file

@ -1,35 +0,0 @@
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
};

View file

@ -1,67 +0,0 @@
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
};

494
freeldr/bootsect/fat.asm Normal file
View file

@ -0,0 +1,494 @@
; FAT.ASM
; FAT12/16 Boot Sector
; Copyright (c) 1998, 2001 Brian Palmer
; This is a FAT12/16 file system boot sector
; that searches the entire root directory
; for the file freeldr.sys and loads it into
; memory.
;
; The stack is set to 0000:7C00 so that the first
; DWORD pushed will be placed at 0000:7BFC
;
; When it locates freeldr.sys on the disk it will
; load the first sector of the file to 0000:7E00
; With the help of this sector we should be able
; to load the entire file off the disk, no matter
; how fragmented it is.
;
; We load the entire FAT table into memory at
; 7000:0000. This improves the speed of floppy disk
; boots dramatically.
org 7c00h
segment .text
bits 16
start:
jmp short main
nop
OEMName db 'FrLdr1.0'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
NumberOfFats db 2
MaxRootEntries dw 224
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 'NO NAME '
FileSystem db 'FAT12 '
main:
cli
cld
xor ax,ax
mov ss,ax
mov bp,7c00h
mov sp,bp ; Setup a stack
mov ax,cs ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
sti ; Enable ints now
mov [BYTE bp+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 dx,dx
mov al,[BYTE bp+NumberOfFats] ; Number of fats
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
add ax,WORD [BYTE bp+HiddenSectors]
adc dx,WORD [BYTE bp+HiddenSectors+2] ; Add the number of hidden sectors
add ax,WORD [BYTE bp+ReservedSectors] ; Add the number of reserved sectors
adc dx,byte 0 ; Add carry bit
push ax ; Store it on the stack
push dx ; Save 32-bit logical start sector
push ax
push dx ; Save it for later use also
; DX:AX now has the number of the starting sector of the root directory
; Now calculate the size of the root directory
mov ax,0020h ; Size of dir entry
mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries
mov bx,[BYTE bp+BytesPerSector]
add ax,bx
dec ax
div bx ; Divided by the size of a sector
; AX now has the number of root directory sectors
xchg ax,cx ; Now CX has number of sectors
pop dx
pop ax ; Restore logical sector start
push cx ; Save number of root dir sectors for later use
mov bx,7c0h ; We will load the root directory
add bx,byte 20h ; Right after the boot sector in memory
mov es,bx
xor bx,bx ; We will load it to [0000:7e00h]
call ReadSectors ; Read the sectors
; Now we have to find our way through the root directory to
; The OSLOADER.SYS file
mov bx,[BYTE bp+MaxRootEntries]; Search entire root directory
mov ax,7e0h ; We loaded at 07e0:0000
mov es,ax
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx
jnz FindFile
jmp ErrBoot
FindFile:
mov ax,es ; We didn't find it in the previous dir entry
add ax,byte 2 ; So lets move to the next one
mov es,ax ; And search again
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx ; Keep searching till we run out of dir entries
jnz FindFile ; Last entry?
jmp ErrBoot
FoundFile:
; We found freeldr.sys on the disk
; so we need to load the first 512
; bytes of it to 0000:7E00
xor di,di ; ES:DI has dir entry
xor dx,dx
mov ax,WORD [es:di+1ah]; Get start cluster
dec ax ; Adjust start cluster by 2
dec ax ; Because the data area starts on cluster 2
xor ch,ch
mov cl,BYTE [BYTE bp+SectsPerCluster] ; Times sectors per cluster
mul cx
pop cx ; Get number of sectors for root dir
add ax,cx ; Add it to the start sector of freeldr.sys
adc dx,byte 0
pop cx ; Get logical start sector of
pop bx ; Root directory
add ax,bx ; Now we have DX:AX with the logical start
adc dx,cx ; Sector of OSLOADER.SYS
mov cx,1 ; We will load 1 sector
push WORD [es:di+1ah] ; Save start cluster
mov bx,7e0h
mov es,bx
xor bx,bx
call ReadSectors ; Load it
pop ax ; Restore start cluster
jmp LoadFile
; Reads logical sectors into [ES:BX]
; DX:AX has logical sector number to read
; CX has number of sectors to read
; CarryFlag set on error
ReadSectors:
push ax
push dx
push cx
xchg ax,cx
xchg ax,dx
xor dx,dx
div WORD [BYTE bp+SectorsPerTrack]
xchg ax,cx
div WORD [BYTE bp+SectorsPerTrack] ; Divide logical by SectorsPerTrack
inc dx ; Sectors numbering starts at 1 not 0
xchg cx,dx
div WORD [BYTE bp+NumberOfHeads] ; Number of heads
mov dh,dl ; Head to DH, drive to DL
mov dl,[BYTE bp+BootDrive] ; Drive number
mov ch,al ; Cylinder in CX
ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
ror ah,1 ; in CL shifted to bits 6 & 7
or cl,ah ; Or with sector number
mov ax,0201h
int 13h ; DISK - READ SECTORS INTO MEMORY
; AL = number of sectors to read, CH = track, CL = sector
; DH = head, DL = drive, ES:BX -> buffer to fill
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
jc BadBoot
pop cx
pop dx
pop ax
inc ax ;Increment Sector to Read
jnz NoCarry
inc dx
NoCarry:
push bx
mov bx,es
add bx,byte 20h
mov es,bx
pop bx
; Increment read buffer for next sector
loop ReadSectors ; Read next sector
ret
; Displays a bad boot message
; And reboots
BadBoot:
mov si,msgDiskError ; Bad boot disk message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
jmp Reboot
; Displays an error message
; And reboots
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
; in the first 512 bytes of freeldr.sys
LoadFile:
; Display "Loading FreeLoader..." message
push ax
mov si,msgLoading ; Loading message
call PutChars ; Display it
pop ax
; AX has start cluster of freeldr.sys
push ax
call ReadFatIntoMemory
pop ax
mov bx,7e0h
mov es,bx
LoadFile2:
push ax
call IsFat12
pop ax
jnc LoadFile3
cmp ax,0ff8h ; Check to see if this is the last cluster in the chain
jmp LoadFile4
LoadFile3:
cmp ax,0fff8h
LoadFile4:
jae LoadFile_Done ; If so continue, if not then read then next one
push ax
xor bx,bx ; Load ROSLDR starting at 0000:8000h
push es
call ReadCluster
pop es
xor bx,bx
mov bl,BYTE [BYTE bp+SectsPerCluster]
shl bx,5 ; BX = BX * 512 / 16
mov ax,es ; Increment the load address by
add ax,bx ; The size of a cluster
mov es,ax
call IsFat12
pop ax
push es
jnc LoadFile5
call GetFatEntry12 ; Get the next entry
jmp LoadFile6
LoadFile5:
call GetFatEntry16
LoadFile6:
pop es
jmp LoadFile2 ; Load the next cluster (if any)
LoadFile_Done:
mov dl,BYTE [BYTE bp+BootDrive]
xor ax,ax
push ax
mov ax,8000h
push ax ; We will do a far return to 0000:8000h
retf ; Transfer control to ROSLDR
; Reads the entire FAT into memory at 7000:0000
ReadFatIntoMemory:
mov ax,WORD [BYTE bp+HiddenSectors]
mov dx,WORD [BYTE bp+HiddenSectors+2]
add ax,WORD [BYTE bp+ReservedSectors]
adc dx,byte 0
mov cx,WORD [BYTE bp+SectorsPerFat]
mov bx,7000h
mov es,bx
xor bx,bx
call ReadSectors
ret
; Returns the FAT entry for a given cluster number for 16-bit FAT
; On entry AX has cluster number
; On return AX has FAT entry for that cluster
GetFatEntry16:
xor dx,dx
mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes)
mul cx
shl dx,0fh
mov bx,7000h
add bx,dx
mov es,bx
mov bx,ax ; Restore FAT entry offset
mov ax,WORD [es:bx] ; Get FAT entry
ret
; Returns the FAT entry for a given cluster number for 12-bit FAT
; On entry AX has cluster number
; On return AX has FAT entry for that cluster
GetFatEntry12:
push ax
mov cx,ax
shr ax,1
add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
mov bx,7000h
mov es,bx
mov bx,ax ; Put FAT entry offset into BX
mov ax,WORD [es:bx] ; Get FAT entry
pop cx ; Get cluster number from stack
and cx,1
jz UseLow12Bits
and ax,0fff0h
shr ax,4
jmp GetFatEntry12_Done
UseLow12Bits:
and ax,0fffh
GetFatEntry12_Done:
ret
; Reads cluster number in AX into [ES:0000]
ReadCluster:
; StartSector = ((Cluster - 2) * SectorsPerCluster) + + ReservedSectors + HiddenSectors;
dec ax
dec ax
xor dx,dx
movzx bx,BYTE [BYTE bp+SectsPerCluster]
mul bx
push ax
push dx
; Now calculate the size of the root directory
mov ax,0020h ; Size of dir entry
mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries
mov bx,WORD [BYTE bp+BytesPerSector]
add ax,bx
dec ax
div bx ; Divided by the size of a sector
mov cx,ax
; CX now has the number of root directory sectors
xor dx,dx
movzx ax,BYTE [BYTE bp+NumberOfFats]
mul WORD [BYTE bp+SectorsPerFat]
add ax,WORD [BYTE bp+ReservedSectors]
adc dx,byte 0
add ax,WORD [BYTE bp+HiddenSectors]
adc dx,WORD [BYTE bp+HiddenSectors+2]
add ax,cx
adc dx,byte 0
pop cx
pop bx
add ax,bx
adc dx,cx
xor bx,bx ; We will load it to [ES:0000], ES loaded before function call
movzx cx,BYTE [BYTE bp+SectsPerCluster]
call ReadSectors
ret
; Returns CF = 1 if this is a FAT12 file system
; Otherwise CF = 0 for FAT16
IsFat12:
; Now calculate the size of the root directory
mov ax,0020h ; Size of dir entry
mul WORD [BYTE bp+MaxRootEntries] ; Times the number of entries
mov bx,WORD [BYTE bp+BytesPerSector]
add ax,bx ; Plus (BytesPerSector - 1)
dec ax
div bx ; Divided by the size of a sector
; AX now has the number of root directory sectors
mov bx,ax
; Now we must find our way to the first sector of the root directory
xor ax,ax
xor dx,dx
mov al,BYTE [BYTE bp+NumberOfFats] ; Number of fats
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
add ax,WORD [BYTE bp+HiddenSectors]
adc dx,WORD [BYTE bp+HiddenSectors+2] ; Add the number of hidden sectors
add ax,[BYTE bp+ReservedSectors] ; Add the number of reserved sectors
adc dx,byte 0 ; Add carry bit
add ax,bx
adc dx,byte 0 ; Add carry bit
; DX:AX now has the number of the starting sector of the data area
xor cx,cx
mov bx,WORD [BYTE bp+TotalSectors]
cmp bx,byte 0
jnz IsFat12_2
mov bx,WORD [BYTE bp+TotalSectorsBig]
mov cx,WORD [BYTE bp+TotalSectorsBig+2]
; CX:BX now contains the number of sectors on the volume
IsFat12_2:
sub bx,ax ; Subtract data area start sector
sub cx,dx ; from total sectors of volume
mov ax,bx
mov dx,cx
; DX:AX now contains the number of data sectors on the volume
movzx bx,BYTE [BYTE bp+SectsPerCluster]
div bx
; AX now has the number of clusters on the volume
stc
cmp ax,4085
jb IsFat12_Done
clc
IsFat12_Done:
ret
times 998-($-$$) db 0 ; Pad to 998 bytes
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
dw 0aa55h ; BootSector signature

View file

@ -1,6 +1,6 @@
; BTSECT32.ASM
; FAT32.ASM
; FAT32 Boot Sector
; Copyright (c) 1998, 2000 Brian Palmer
; Copyright (c) 1998, 2000, 2001 Brian Palmer
org 7c00h
@ -12,15 +12,15 @@ start:
jmp short main
nop
OEMName db 'FreeLDR!'
OEMName db 'FrLdr1.0'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
ReservedSectors dw 32
NumberOfFats db 2
MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
MaxRootEntries dw 0 ; Always zero for FAT32 volumes
TotalSectors dw 0 ; Always zero for FAT32 volumes
MediaDescriptor db 0f8h
SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
SectorsPerFat dw 0 ; Always zero for FAT32 volumes
SectorsPerTrack dw 18
NumberOfHeads dw 2
HiddenSectors dd 0
@ -38,7 +38,7 @@ BootDrive db 0
Reserved db 0
ExtendSig db 29h
SerialNumber dd 00000000h
VolumeLabel db 'FreeLoader!'
VolumeLabel db 'NO NAME '
FileSystem db 'FAT32 '
main:
@ -56,12 +56,19 @@ main:
mov [BootDrive],dl ; Save the boot drive
xor ax,ax ; Zero out AX
cmp word [TotalSectors],byte 0x00 ; Check the old 16-bit value of TotalSectors
jnz ErrBoot ; If it is non-zero then exit with an error
cmp word [FSVersion],byte 0x00 ; Check the file system version word
ja ErrBoot ; If it is not zero then exit with an error
; Reset disk controller
int 13h
jnc Continue
jnc LoadExtraBootCode
jmp BadBoot ; Reset failed...
Continue:
LoadExtraBootCode:
; First we have to load our extra boot code at
; sector 14 into memory at [0000:7e00h]
xor dx,dx
@ -73,97 +80,9 @@ Continue:
mov es,bx ; Read sector to [0000:7e00h]
xor bx,bx
call ReadSectors
jnc Continue1
jmp BadBoot
jmp StartSearch
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]
@ -189,15 +108,17 @@ ReadSectors:
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
mov ax,0201h
int 13h ; DISK - READ SECTORS INTO MEMORY
; AL = number of sectors to read, CH = track, CL = sector
; DH = head, DL = drive, ES:BX -> buffer to fill
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
jc BadBoot
pop cx
pop dx
pop ax
jc ReadFail
inc ax ;Increment Sector to Read
jnz NoCarry
inc dx
@ -206,15 +127,13 @@ ReadSectors:
NoCarry:
push bx
mov bx,es
add bx,20h
add bx,byte 20h
mov es,bx
pop bx
; Increment read buffer for next sector
loop ReadSectors ; Read next sector
ReadFail:
ret
ret
@ -275,6 +194,99 @@ filename db 'FREELDR SYS'
; Note: Win2k uses sector 12 for this purpose
StartSearch:
; 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 ContinueSearch ; If not continue, if so BadBoot
jmp ErrBoot
ContinueSearch:
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 StartSearch
FoundFile:
; Display "Loading FreeLoader..." message
mov si,msgLoading ; Loading message
call PutChars ; Display it
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
; Returns the FAT entry for a given cluster number
; On entry EAX has cluster number
; On return EAX has FAT entry for that cluster
@ -288,13 +300,31 @@ GetFatEntry:
div ebx ; FAT Sector Number = EAX / BytesPerSector
movzx ebx,WORD [ReservedSectors]
add eax,ebx ; FAT Sector Number += ReservedSectors
movzx ebx,WORD [HiddenSectors]
mov ebx,DWORD [HiddenSectors]
add eax,ebx ; FAT Sector Number += HiddenSectors
pop ebx
dec ebx
and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
; EAX holds logical FAT sector number
; ECX holds FAT entry offset
; Now we have to check the extended flags
; to see which FAT is the active one
; and use it, or if they are mirrored then
; no worries
movzx ebx,WORD [ExtendedFlags] ; Get extended flags and put into ebx
and bx,0x0f ; Mask off upper 8 bits
jz GetFatEntry2 ; If fat is mirrored then skip fat calcs
cmp bl,[NumberOfFats] ; Compare bl to number of fats
jc GetFatEntry1
jmp ErrBoot ; If bl is bigger than numfats exit with error
GetFatEntry1:
mov edx,eax ; Put logical FAT sector number in edx
mov eax,[SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
mul ebx ; Multiplied by the active FAT index we have in ebx
add eax,edx ; Add the current FAT sector offset
GetFatEntry2:
push ecx
ror eax,16
mov dx,ax
@ -305,9 +335,9 @@ GetFatEntry:
xor bx,bx ; We will load it to [7000:0000h]
mov cx,1
call ReadSectors
jnc GetFatEntry1
jnc GetFatEntry3
jmp BadBoot
GetFatEntry1:
GetFatEntry3:
mov bx,7000h
mov es,bx
pop ecx
@ -341,11 +371,10 @@ ReadCluster:
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
times 998-($-$$) db 0 ; Pad to 998 bytes
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
dw 0aa55h ; BootSector signature

View file

@ -1 +0,0 @@
debug bootsect.bin < install.src

View file

@ -1,2 +0,0 @@
w 100 0 0 1
q

55
freeldr/bootsect/split.c Normal file
View file

@ -0,0 +1,55 @@
#include <stdio.h>
FILE *in;
FILE *out;
FILE *new;
int main(int argc, char *argv[])
{
unsigned char ch;
int cnt;
int split_offset;
if (argc < 5)
{
printf("usage: split infile.bin outfile.bin newfile.bin split_offset\n");
return -1;
}
if ((in = fopen(argv[1], "rb")) == NULL)
{
printf("Couldn't open data file.\n");
return -1;
}
if ((out = fopen(argv[2], "wb")) == NULL)
{
printf("Couldn't open output file.\n");
return -1;
}
if ((new = fopen(argv[3], "wb")) == NULL)
{
printf("Couldn't open new file.\n");
return -1;
}
split_offset = atoi(argv[4]);
for (cnt=0; cnt<split_offset; cnt++)
{
ch = fgetc(in);
fputc(ch, out);
}
ch = fgetc(in);
while (!feof(in))
{
fputc(ch, new);
ch = fgetc(in);
}
fclose(in);
fclose(out);
fclose(new);
return 0;
}

52
freeldr/bootsect/stubit.c Normal file
View file

@ -0,0 +1,52 @@
#include <stdio.h>
FILE *in;
FILE *in2;
FILE *out;
int main(int argc, char *argv[])
{
unsigned char ch;
if (argc < 4)
{
printf("usage: stubit infile1.bin infile2.sys outfile.bin\n");
return -1;
}
if ((in = fopen(argv[1], "rb")) == NULL)
{
printf("Couldn't open data file.\n");
return -1;
}
if ((in2 = fopen(argv[2], "rb")) == NULL)
{
printf("Couldn't open data file.\n");
return -1;
}
if ((out = fopen(argv[3], "wb")) == NULL)
{
printf("Couldn't open output file.\n");
return -1;
}
ch = fgetc(in);
while (!feof(in))
{
fputc(ch, out);
ch = fgetc(in);
}
ch = fgetc(in2);
while (!feof(in2))
{
fputc(ch, out);
ch = fgetc(in2);
}
fclose(in);
fclose(in2);
fclose(out);
return 0;
}

View file

@ -27,7 +27,7 @@ start:
jmp short main
nop
OEMName db 'FreeLDR!'
OEMName db 'MSWIN4.0'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
@ -53,8 +53,8 @@ BootDrive db 0
Reserved db 0
ExtendSig db 29h
SerialNumber dd 00000000h
VolumeLabel db 'FreeLoader!'
FileSystem db 'FAT12 '
VolumeLabel db 'NO NAME '
FileSystem db 'FAT32 '
main:
00007C5A 33C9 xor cx,cx
@ -349,8 +349,8 @@ load_fat_sector:
00008112 660FB74E0E movzx ecx,word [bp+ReservedSectors] ; Add the reserved sectors
00008117 6603C1 add eax,ecx ; To the hidden sectors + the value we computed earlier
0000811A 660FB75E28 movzx ebx,word [bp+ExtendedFlags] ; Get extended flags and put into ebx
0000811F 83E30F and bx,byte +0xf ; Mask off everything but the active fat bits
00008122 7416 jz load_fat_sector_into_memory ; If active fat is first fat skip fat size calcs
0000811F 83E30F and bx,byte +0xf ; Mask off upper 8 bits
00008122 7416 jz load_fat_sector_into_memory ; If fat is mirrored then skip fat calcs
00008124 3A5E10 cmp bl,[bp+NumberOfFats] ; Compare bl to number of fats
00008127 0F83ABFB jnc near print_ntldr_error_message ; If bl is bigger than numfats exit with error
0000812B 52 push dx ; Save dx

View file

@ -1,6 +1,6 @@
#
# FreeLoader
# Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
# Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -25,15 +25,17 @@ export RM = cmd /C del
export CP = cmd /C copy
#FLAGS = -Wall -nostdinc -fno-builtin
FLAGS = -Wall -fno-builtin
FLAGS = -Wall -fno-builtin -DDEBUG
# asmcode.o has to be first in the link line because it contains the startup code
OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
reactos.o tui.o menu.o miscboot.o options.o linux.o multiboot.o arcname.o \
mem.o memory.o
mem.o memory.o debug.o parseini.o
ASM_OBJS = asmcode.o mb.o boot.o mem.o
C_OBJS = freeldr.o stdlib.o fs.a reactos.o tui.o menu.o miscboot.o options.o linux.o \
multiboot.o arcname.o memory.o
multiboot.o arcname.o memory.o debug.o parseini.o
.PHONY : clean
all: freeldr.sys
@ -97,9 +99,15 @@ arcname.o: arcname.c freeldr.h arcname.h stdlib.h Makefile
mem.o: mem.S asmcode.h Makefile
$(CC) $(FLAGS) -o mem.o -c mem.S
memory.o: memory.c asmcode.h memory.h Makefile
memory.o: memory.c memory.h Makefile
$(CC) $(FLAGS) -o memory.o -c memory.c
debug.o: debug.c debug.h Makefile
$(CC) $(FLAGS) -o debug.o -c debug.c
parseini.o: parseini.c parseini.h Makefile
$(CC) $(FLAGS) -o parseini.o -c parseini.c
clean:
$(RM) *.o
$(RM) *.a

View file

@ -24,7 +24,7 @@
#include "stdlib.h"
BOOL DissectArcPath(char *ArcPath, char *BootPath, unsigned int *BootDrive, unsigned int *BootPartition)
BOOL DissectArcPath(char *ArcPath, char *BootPath, PULONG BootDrive, PULONG BootPartition)
{
char *p;

View file

@ -22,8 +22,8 @@
#ifndef __ARCNAME_H
#define __ARCNAME_H
BOOL DissectArcPath(char *ArcPath, char *BootPath, unsigned int *BootDrive, unsigned int *BootPartition);
//BOOL ConvertBiosDriveToArcName()
//BOOL ConvertArcNameToBiosDrive()
BOOL DissectArcPath(char *ArcPath, char *BootPath, PULONG BootDrive, PULONG BootPartition);
//BOOL ConvertBiosDriveToArcName(PUCHAR ArcName, ULONG BiosDriveNumber);
//ULONG ConvertArcNameToBiosDrive(PUCHAR ArcName);
#endif // defined __ARCNAME_H

83
freeldr/freeldr/debug.c Normal file
View file

@ -0,0 +1,83 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "freeldr.h"
#include "debug.h"
#include "stdlib.h"
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY;
void DebugPrint(ULONG Mask, char *format, ...)
{
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char buffer[512];
char *p = buffer;
// Mask out unwanted debug messages
if (!(Mask & DebugPrintMask))
{
return;
}
dataptr++;
while ((c = *(format++)))
{
if (c != '%')
{
*p = c;
p++;
}
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
{
*p = *(ptr++);
p++;
}
break;
case 'c':
*p = (*(dataptr++))&0xff;
p++;
break;
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
{
*p = c;
p++;
}
break;
}
}
*p=0;
print(buffer);
}

57
freeldr/freeldr/debug.h Normal file
View file

@ -0,0 +1,57 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#define DPRINT_WARNING 0x00000001 // OR this with DebugPrintMask to enable debugger messages and other misc stuff
#define DPRINT_MEMORY 0x00000002 // OR this with DebugPrintMask to enable memory management messages
void DebugPrint(ULONG Mask, char *format, ...);
#define BugCheck0(format) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format); \
for (;;); \
}
#define BugCheck1(format, arg1) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1); \
for (;;); \
}
#define BugCheck2(format, arg1, arg2) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1, arg2); \
for (;;); \
}
#define BugCheck3(format, arg1, arg2, arg3) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1, arg2, arg3); \
for (;;); \
}
#endif // defined __DEBUG_H

View file

@ -26,16 +26,17 @@
#include "menu.h"
#include "miscboot.h"
#include "linux.h"
#include "memory.h"
#include "parseini.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
//ULONG BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
ULONG BootPartition = 0; // Boot Partition, 1-4
BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is displayed
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
PUCHAR ScreenBuffer = (PUCHAR)(SCREENBUFFER); // Save buffer for screen contents
int CursorXPos = 0; // Cursor's X Position
int CursorYPos = 0; // Cursor's Y Position
OSTYPE OSList[16];
int nNumOS = 0;
@ -51,12 +52,14 @@ void BootMain(void)
enable_a20();
SaveScreen(pScreenBuffer);
nCursorXPos = wherex();
nCursorYPos = wherey();
SaveScreen(ScreenBuffer);
CursorXPos = wherex();
CursorYPos = wherey();
printf("Loading FreeLoader...\n");
InitMemoryManager((PVOID)0x100000, 0x20000);
if (!ParseIniFile())
{
printf("Press any key to reboot.\n");
@ -68,15 +71,15 @@ void BootMain(void)
hidecursor();
// Draw the backdrop and title box
DrawBackdrop();
bTUILoaded = TRUE;
UserInterfaceUp = TRUE;
if (nNumOS == 0)
{
DrawStatusText(" Press ENTER to reboot");
MessageBox("Error: there were no operating systems listed to boot.\nPress ENTER to reboot.");
MessageBox("Error: there were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
clrscr();
showcursor();
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
return;
}
@ -119,617 +122,7 @@ void BootMain(void)
}
MessageBox("Press any key to reboot.");
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
}
BOOL ParseIniFile(void)
{
int i;
char name[1024];
char value[1024];
FILE Freeldr_Ini; // File handle for freeldr.ini
// Open the boot drive for file access
if(!OpenDiskDrive(BootDrive, 0))
{
printf("Error opening boot drive for file access.\n");
return FALSE;
}
// Try to open freeldr.ini or fail
if(!OpenFile("freeldr.ini", &Freeldr_Ini))
{
printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
return FALSE;
}
// Check and see if freeldr.ini is too big
// if so display a warning
if(GetFileSize(&Freeldr_Ini) > 0x4000)
{
printf("Warning: FREELDR.INI is bigger than 16k.\n");
printf("Only 16k of it will be loaded off the disk.\n");
printf("Press any key to continue.\n");
getch();
}
// Read freeldr.ini off the disk
ReadFile(&Freeldr_Ini, 0x4000, pFreeldrIni);
// Make sure the [FREELOADER] section exists
if(!GetNumSectionItems("FREELOADER"))
{
printf("Section [FREELOADER] not found in FREELDR.INI.\nYou need to re-install FreeLoader.\n");
return FALSE;
}
// Validate the settings in the [FREELOADER] section
for(i=1; i<=GetNumSectionItems("FREELOADER"); i++)
{
ReadSectionSettingByNumber("FREELOADER", i, name, value);
if(!IsValidSetting(name, value))
{
printf("Invalid setting in freeldr.ini.\nName: \"%s\", Value: \"%s\"\n", name, value);
printf("Press any key to continue.\n");
getch();
}
else
SetSetting(name, value);
}
return TRUE;
}
int GetNumSectionItems(char *section)
{
int i;
char str[1024];
char real_section[1024];
int num_items = 0;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return 0;
// Now count how many settings are in this section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
num_items++;
}
return num_items;
}
BOOL ReadSectionSettingByNumber(char *section, int num, char *name, char *value)
{
char str[1024];
char real_section[1024];
int num_items = 0;
int i;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return FALSE;
// Now find the setting we are looking for
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
// Increment setting number
num_items++;
// Check and see if we found the setting
if(num_items == num)
{
for(i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if(str[i] == '=')
{
name[i] = '\0';
strcpy(value, str+i+1);
return TRUE;
}
else
name[i] = str[i];
}
}
}
return FALSE;
}
BOOL ReadSectionSettingByName(char *section, char *valuename, char *name, char *value)
{
char str[1024];
char real_section[1024];
char temp[1024];
int i;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return FALSE;
// Now find the setting we are looking for
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
// Extract the setting name
for(i=0; i<strlen(str); i++)
{
if(str[i] != '=')
temp[i] = str[i];
else
{
temp[i] = '\0';
break;
}
}
// Check and see if we found the setting
if(stricmp(temp, valuename) == 0)
{
for(i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if(str[i] == '=')
{
name[i] = '\0';
strcpy(value, str+i+1);
return TRUE;
}
else
name[i] = str[i];
}
}
}
return FALSE;
}
BOOL IsValidSetting(char *setting, char *value)
{
if(stricmp(setting, "MessageBox") == 0)
return TRUE;
else if(stricmp(setting, "MessageLine") == 0)
return TRUE;
else if(stricmp(setting, "TitleText") == 0)
return TRUE;
else if(stricmp(setting, "StatusBarColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "StatusBarTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropFillStyle") == 0)
{
if(IsValidFillStyle(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "OS") == 0)
return TRUE;
else if(stricmp(setting, "TimeOut") == 0)
return TRUE;
/*else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;*/
return FALSE;
}
void SetSetting(char *setting, char *value)
{
char name[260];
char v[260];
if(stricmp(setting, "TitleText") == 0)
strcpy(szTitleBoxTitleText, value);
else if(stricmp(setting, "StatusBarColor") == 0)
cStatusBarBgColor = TextToColor(value);
else if(stricmp(setting, "StatusBarTextColor") == 0)
cStatusBarFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropTextColor") == 0)
cBackdropFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropColor") == 0)
cBackdropBgColor = TextToColor(value);
else if(stricmp(setting, "BackdropFillStyle") == 0)
cBackdropFillStyle = TextToFillStyle(value);
else if(stricmp(setting, "TitleBoxTextColor") == 0)
cTitleBoxFgColor = TextToColor(value);
else if(stricmp(setting, "TitleBoxColor") == 0)
cTitleBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxTextColor") == 0)
cMessageBoxFgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxColor") == 0)
cMessageBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MenuTextColor") == 0)
cMenuFgColor = TextToColor(value);
else if(stricmp(setting, "MenuColor") == 0)
cMenuBgColor = TextToColor(value);
else if(stricmp(setting, "TextColor") == 0)
cTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedTextColor") == 0)
cSelectedTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedColor") == 0)
cSelectedTextBgColor = TextToColor(value);
else if(stricmp(setting, "OS") == 0)
{
if(nNumOS >= 16)
{
printf("Error: you can only boot to at most 16 different operating systems.\n");
printf("Press any key to continue\n");
getch();
return;
}
if(!GetNumSectionItems(value))
{
printf("Error: OS \"%s\" listed.\n", value);
printf("It does not have it's own [section], or it is empty.\n");
printf("Press any key to continue\n");
getch();
return;
}
strcpy(OSList[nNumOS].name, value);
if (!ReadSectionSettingByName(value, "BootType", name, v))
{
printf("Unknown BootType for OS \"%s\"\n", value);
printf("Press any key to continue\n");
getch();
return;
}
if (stricmp(v, "ReactOS") == 0)
OSList[nNumOS].nOSType = OSTYPE_REACTOS;
else if (stricmp(v, "Linux") == 0)
OSList[nNumOS].nOSType = OSTYPE_LINUX;
else if (stricmp(v, "BootSector") == 0)
OSList[nNumOS].nOSType = OSTYPE_BOOTSECTOR;
else if (stricmp(v, "Partition") == 0)
OSList[nNumOS].nOSType = OSTYPE_PARTITION;
else if (stricmp(v, "Drive") == 0)
OSList[nNumOS].nOSType = OSTYPE_DRIVE;
else
{
printf("Unknown BootType for OS \"%s\"\n", value);
printf("Press any key to continue\n");
getch();
return;
}
nNumOS++;
}
else if(stricmp(setting, "TimeOut") == 0)
nTimeOut = atoi(value);
gotoxy(CursorXPos, CursorYPos);
}

View file

@ -38,12 +38,20 @@
#define WORD unsigned short
#define DWORD unsigned long
#define CHAR char
#define PCHAR char *
#define UCHAR unsigned char
#define PUCHAR unsigned char *
#define WCHAR unsigned short
#define PWCHAR unsigned short *
#define LONG long
#define ULONG unsigned long
#define PULONG unsigned long *
#define PDWORD DWORD *
#define PWORD WORD *
#define VOID void
#define PVOID VOID*
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define OSTYPE_REACTOS 1
#define OSTYPE_LINUX 2
@ -55,16 +63,15 @@ typedef struct
{
char name[260];
int nOSType; // ReactOS or Linux or a bootsector, etc.
} OSTYPE;
} OSTYPE, *POSTYPE;
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 ULONG BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
extern ULONG BootPartition; // Boot Partition, 1-4
extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed
extern 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 PUCHAR ScreenBuffer; // Save buffer for screen contents
extern int CursorXPos; // Cursor's X Position
extern int CursorYPos; // Cursor's Y Position
extern OSTYPE OSList[16]; // The OS list
extern int nNumOS; // Number of OSes listed
@ -72,11 +79,5 @@ 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

View file

@ -25,7 +25,7 @@
#define FS_DO_ERROR(s) \
{ \
if (bTUILoaded) \
if (UserInterfaceUp) \
MessageBox(s); \
else \
{ \

View file

@ -92,9 +92,9 @@ void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line
memcpy((void*)0x90000, bootsector, 512);
memcpy((void*)0x90200, setup, 2048);
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToLinuxBootCode();

View file

@ -19,17 +19,263 @@
#include "freeldr.h"
#include "memory.h"
#include "stdlib.h"
#include "debug.h"
#define MEM_BLOCK_SIZE 256
void InitMemoryManager(void *HeapBaseAddress, unsigned long HeapLength)
typedef struct
{
BOOL MemBlockAllocated; // Is this block allocated or free
ULONG BlocksAllocated; // Block length, in multiples of 256 bytes
} MEMBLOCK, *PMEMBLOCK;
PVOID HeapBaseAddress = NULL;
ULONG HeapLengthInBytes = 0;
ULONG HeapMemBlockCount = 0;
PMEMBLOCK HeapMemBlockArray = NULL;
#ifdef DEBUG
ULONG AllocationCount = 0;
VOID VerifyHeap(VOID);
VOID IncrementAllocationCount(VOID);
VOID DecrementAllocationCount(VOID);
VOID MemAllocTest(VOID);
#endif DEBUG
VOID InitMemoryManager(PVOID BaseAddress, ULONG Length)
{
ULONG MemBlocks;
// Calculate how many memory blocks we have
MemBlocks = (Length / MEM_BLOCK_SIZE);
// Adjust the heap length so we can reserve
// enough storage space for the MEMBLOCK array
Length -= (MemBlocks * sizeof(MEMBLOCK));
// Initialize our tracking variables
HeapBaseAddress = BaseAddress;
HeapLengthInBytes = Length;
HeapMemBlockCount = (HeapLengthInBytes / MEM_BLOCK_SIZE);
HeapMemBlockArray = (PMEMBLOCK)(HeapBaseAddress + HeapLengthInBytes);
// Clear the memory
ZeroMemory(HeapBaseAddress, HeapLengthInBytes);
ZeroMemory(HeapMemBlockArray, (HeapMemBlockCount * sizeof(MEMBLOCK)));
#ifdef DEBUG
DebugPrint(DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount);
//MemAllocTest();
#endif
}
void *malloc(int size)
PVOID AllocateMemory(ULONG NumberOfBytes)
{
return 0;
ULONG BlocksNeeded;
ULONG Idx;
ULONG NumFree;
PVOID MemPointer;
#ifdef DEBUG
VerifyHeap();
#endif DEBUG
// Find out how many blocks it will take to
// satisfy this allocation
BlocksNeeded = ROUND_UP(NumberOfBytes, MEM_BLOCK_SIZE) / MEM_BLOCK_SIZE;
// Now loop through our array of blocks and
// see if we have enough space
for (Idx=0,NumFree=0; Idx<HeapMemBlockCount; Idx++)
{
// Check this block and see if it is already allocated
// If so reset our counter and continue the loop
if (HeapMemBlockArray[Idx].MemBlockAllocated)
{
NumFree = 0;
continue;
}
else
{
// It is free memory so lets increment our count
NumFree++;
}
// If we have found enough blocks to satisfy the request
// then we're done searching
if (NumFree >= BlocksNeeded)
{
break;
}
}
Idx++;
// If we don't have enough available mem
// then return NULL
if (NumFree < BlocksNeeded)
{
return NULL;
}
// Subtract the block count from Idx and we have
// the start block of the memory
Idx -= NumFree;
// Now we know which block to give them
MemPointer = HeapBaseAddress + (Idx * MEM_BLOCK_SIZE);
// Now loop through and mark all the blocks as allocated
for (NumFree=0; NumFree<BlocksNeeded; NumFree++)
{
HeapMemBlockArray[Idx + NumFree].MemBlockAllocated = TRUE;
HeapMemBlockArray[Idx + NumFree].BlocksAllocated = NumFree ? 0 : BlocksNeeded; // Mark only the first block with the count
}
#ifdef DEBUG
IncrementAllocationCount();
DebugPrint(DPRINT_MEMORY, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocationCount: %d\n", NumberOfBytes, BlocksNeeded, Idx, AllocationCount);
#endif DEBUG
// Now return the pointer
return MemPointer;
}
void free(void *memblock)
VOID FreeMemory(PVOID MemBlock)
{
ULONG BlockNumber;
ULONG BlockCount;
ULONG Idx;
#ifdef DEBUG
VerifyHeap();
// Make sure we didn't get a bogus pointer
if ((MemBlock < HeapBaseAddress) || (MemBlock > (HeapBaseAddress + HeapLengthInBytes)))
{
BugCheck1("Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock);
}
#endif DEBUG
// Find out the block number if the first
// block of memory they allocated
BlockNumber = (MemBlock - HeapBaseAddress) / MEM_BLOCK_SIZE;
BlockCount = HeapMemBlockArray[BlockNumber].BlocksAllocated;
#ifdef DEBUG
// Make sure we didn't get a bogus pointer
if ((BlockCount < 1) || (BlockCount > HeapMemBlockCount))
{
BugCheck1("Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray[BlockNumber].BlocksAllocated);
}
#endif
// Loop through our array and mark all the
// blocks as free
for (Idx=BlockNumber; Idx<(BlockNumber + BlockCount); Idx++)
{
HeapMemBlockArray[Idx].MemBlockAllocated = FALSE;
HeapMemBlockArray[Idx].BlocksAllocated = 0;
}
#ifdef DEBUG
DecrementAllocationCount();
DebugPrint(DPRINT_MEMORY, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount, BlockNumber, AllocationCount);
#endif DEBUG
}
#ifdef DEBUG
VOID VerifyHeap(VOID)
{
ULONG Idx;
ULONG Idx2;
ULONG Count;
// Loop through the array and verify that
// everything is kosher
for (Idx=0; Idx<HeapMemBlockCount; Idx++)
{
// Check if this block is allocation
if (HeapMemBlockArray[Idx].MemBlockAllocated)
{
// This is the first block in the run so it
// had better have a length that is within range
if ((HeapMemBlockArray[Idx].BlocksAllocated < 1) || (HeapMemBlockArray[Idx].BlocksAllocated > (HeapMemBlockCount - Idx)))
{
BugCheck1("Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray[Idx].BlocksAllocated);
}
// Now go through and verify that the rest of
// this run has the blocks marked allocated
// with a length of zero but don't check the
// first one because we already did
Count = HeapMemBlockArray[Idx].BlocksAllocated;
for (Idx2=1; Idx2<Count; Idx2++)
{
// Make sure it's allocated
if (HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE)
{
BugCheck0("Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n");
}
// Make sure the length is zero
if (HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0)
{
BugCheck0("Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n");
}
}
// Move on to the next run
Idx += Count;
}
else
{
// Nope, not allocated so make sure the length is zero
if (HeapMemBlockArray[Idx].BlocksAllocated != 0)
{
BugCheck0("Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n");
}
}
}
}
VOID IncrementAllocationCount(VOID)
{
AllocationCount++;
}
VOID DecrementAllocationCount(VOID)
{
AllocationCount--;
}
VOID MemAllocTest(VOID)
{
PVOID MemPtr1;
PVOID MemPtr2;
PVOID MemPtr3;
PVOID MemPtr4;
PVOID MemPtr5;
MemPtr1 = AllocateMemory(4096);
printf("MemPtr1: 0x%x\n", (int)MemPtr1);
getch();
MemPtr2 = AllocateMemory(4096);
printf("MemPtr2: 0x%x\n", (int)MemPtr2);
getch();
MemPtr3 = AllocateMemory(4096);
printf("MemPtr3: 0x%x\n", (int)MemPtr3);
getch();
FreeMemory(MemPtr2);
getch();
MemPtr4 = AllocateMemory(2048);
printf("MemPtr4: 0x%x\n", (int)MemPtr4);
getch();
MemPtr5 = AllocateMemory(4096);
printf("MemPtr5: 0x%x\n", (int)MemPtr5);
getch();
}
#endif DEBUG

View file

@ -24,10 +24,10 @@
#include "multiboot.h"
void InitMemoryManager(void *HeapBaseAddress, unsigned long HeapLength);
VOID InitMemoryManager(PVOID BaseAddress, ULONG Length);
void* malloc(int size);
void free(void *memblock);
PVOID AllocateMemory(ULONG NumberOfBytes);
VOID FreeMemory(PVOID MemBlock);
// These functions are implemented in mem.S
int GetExtendedMemorySize(void); // Returns extended memory size in KB

View file

@ -24,6 +24,7 @@
#include "stdlib.h"
#include "fs.h"
#include "tui.h"
#include "parseini.h"
void LoadAndBootBootSector(int nOSToBoot)
{
@ -43,7 +44,7 @@ void LoadAndBootBootSector(int nOSToBoot)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
@ -52,10 +53,10 @@ void LoadAndBootBootSector(int nOSToBoot)
BootDrive = atoi(value);
BootPartition = 0;
if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", value))
BootPartition = atoi(value);
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootSector", name, value))
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootSector", value))
{
MessageBox("Boot sector file not specified for selected OS!");
return;
@ -89,9 +90,9 @@ void LoadAndBootBootSector(int nOSToBoot)
return;
}
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
@ -115,7 +116,7 @@ void LoadAndBootPartition(int nOSToBoot)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
@ -123,7 +124,7 @@ void LoadAndBootPartition(int nOSToBoot)
BootDrive = atoi(value);
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", value))
{
MessageBox("Boot partition not specified for selected OS!");
return;
@ -175,9 +176,9 @@ void LoadAndBootPartition(int nOSToBoot)
return;
}
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
@ -199,7 +200,7 @@ void LoadAndBootDrive(int nOSToBoot)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
@ -220,9 +221,9 @@ void LoadAndBootDrive(int nOSToBoot)
return;
}
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();

View file

@ -24,6 +24,7 @@
#include "fs.h"
#include "multiboot.h"
#include "tui.h"
#include "parseini.h"
unsigned long next_module_load_base = 0;
@ -145,10 +146,9 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
int GetBootPartition(char *OperatingSystemName)
{
int BootPartitionNumber = -1;
char name[1024];
char value[1024];
if (ReadSectionSettingByName(OperatingSystemName, "BootPartition", name, value))
if (ReadSectionSettingByName(OperatingSystemName, "BootPartition", value))
{
BootPartitionNumber = atoi(value);
}

View file

@ -53,8 +53,6 @@
#define MB_INFO_FLAG_APM_TABLE 0x00000400
#define MB_INFO_FLAG_GRAPHICS_TABLE 0x00000800
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#ifndef ASM
/* Do not include here in boot.S. */

View file

@ -125,9 +125,9 @@ void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
return;
}
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
@ -237,9 +237,9 @@ void DoBootPartitionOptionsMenu(int BootDriveNum)
return;
}
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();

522
freeldr/freeldr/parseini.c Normal file
View file

@ -0,0 +1,522 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "freeldr.h"
#include "parseini.h"
#include "tui.h"
#include "fs.h"
#include "stdlib.h"
#include "memory.h"
PUCHAR FreeLoaderIniFileData = NULL;
ULONG FreeLoaderIniFileSize = 0;
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;
}
// Get the file size & allocate enough memory for it
FreeLoaderIniFileSize = GetFileSize(&Freeldr_Ini);
FreeLoaderIniFileData = AllocateMemory(FreeLoaderIniFileSize);
// If we are out of memory then return FALSE
if (FreeLoaderIniFileData == NULL)
{
printf("Out of memory while loading FREELDR.INI.\n");
return FALSE;
}
// Read freeldr.ini off the disk
ReadFile(&Freeldr_Ini, FreeLoaderIniFileSize, FreeLoaderIniFileData);
// 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;
}
ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset)
{
ULONG Idx;
// Loop through grabbing chars until we hit the end of the
// file or we encounter a new line char
for (Idx=0; (CurrentOffset < FreeLoaderIniFileSize); CurrentOffset++)
{
// If we haven't exceeded our buffer size yet
// then store another char
if (Idx < (BufferSize - 1))
{
Buffer[Idx++] = FreeLoaderIniFileData[CurrentOffset];
}
// Check for new line char
if (FreeLoaderIniFileData[CurrentOffset] == '\n')
{
CurrentOffset++;
break;
}
}
// Terminate the string
Buffer[Idx] = '\0';
// Get rid of newline & linefeed characters (if any)
if((Buffer[strlen(Buffer)-1] == '\n') || (Buffer[strlen(Buffer)-1] == '\r'))
Buffer[strlen(Buffer)-1] = '\0';
if((Buffer[strlen(Buffer)-1] == '\n') || (Buffer[strlen(Buffer)-1] == '\r'))
Buffer[strlen(Buffer)-1] = '\0';
// Send back new offset
return CurrentOffset;
}
ULONG GetOffsetOfFirstLineOfSection(PUCHAR SectionName)
{
char str[1024];
char real_section[1024];
ULONG freeldr_ini_offset;
BOOL SectionFound = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, SectionName);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while (freeldr_ini_offset < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
// Skip comments
if (str[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
continue;
// 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)
{
SectionFound = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if (!SectionFound)
return 0;
return freeldr_ini_offset;
}
ULONG GetNumSectionItems(PUCHAR SectionName)
{
UCHAR str[1024];
ULONG num_items = 0;
ULONG freeldr_ini_offset;
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
// Now count how many settings are in this section
while (freeldr_ini_offset < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
// Skip comments
if (str[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
continue;
// If we hit a new section then we're done
if (str[0] == '[')
break;
num_items++;
}
return num_items;
}
BOOL ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue)
{
UCHAR str[1024];
ULONG num_items = 0;
ULONG i;
ULONG freeldr_ini_offset;
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
// Now find the setting we are looking for
while (freeldr_ini_offset < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
// Skip comments
if (str[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
continue;
// 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 == SettingNumber)
{
for (i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if (str[i] == '=')
{
SettingName[i] = '\0';
strcpy(SettingValue, str+i+1);
return TRUE;
}
else
SettingName[i] = str[i];
}
}
}
return FALSE;
}
BOOL ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue)
{
UCHAR str[1024];
UCHAR temp[1024];
ULONG i;
ULONG freeldr_ini_offset;
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
// Now find the setting we are looking for
while (freeldr_ini_offset < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
// Skip comments
if (str[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
continue;
// If we hit a new section then we're done
if (str[0] == '[')
break;
// Extract the setting name
for (i=0; i<strlen(str); i++)
{
if (str[i] != '=')
temp[i] = str[i];
else
{
temp[i] = '\0';
break;
}
}
// Check and see if we found the setting
if (stricmp(temp, SettingName) == 0)
{
for (i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if (str[i] == '=')
{
strcpy(SettingValue, str+i+1);
return TRUE;
}
}
}
}
return FALSE;
}
BOOL IsValidSetting(char *setting, char *value)
{
if(stricmp(setting, "MessageBox") == 0)
return TRUE;
else if(stricmp(setting, "MessageLine") == 0)
return TRUE;
else if(stricmp(setting, "TitleText") == 0)
return TRUE;
else if(stricmp(setting, "StatusBarColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "StatusBarTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropFillStyle") == 0)
{
if(IsValidFillStyle(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "OS") == 0)
return TRUE;
else if(stricmp(setting, "TimeOut") == 0)
return TRUE;
/*else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;*/
return FALSE;
}
void SetSetting(char *setting, char *value)
{
char v[260];
if(stricmp(setting, "TitleText") == 0)
strcpy(szTitleBoxTitleText, value);
else if(stricmp(setting, "StatusBarColor") == 0)
cStatusBarBgColor = TextToColor(value);
else if(stricmp(setting, "StatusBarTextColor") == 0)
cStatusBarFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropTextColor") == 0)
cBackdropFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropColor") == 0)
cBackdropBgColor = TextToColor(value);
else if(stricmp(setting, "BackdropFillStyle") == 0)
cBackdropFillStyle = TextToFillStyle(value);
else if(stricmp(setting, "TitleBoxTextColor") == 0)
cTitleBoxFgColor = TextToColor(value);
else if(stricmp(setting, "TitleBoxColor") == 0)
cTitleBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxTextColor") == 0)
cMessageBoxFgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxColor") == 0)
cMessageBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MenuTextColor") == 0)
cMenuFgColor = TextToColor(value);
else if(stricmp(setting, "MenuColor") == 0)
cMenuBgColor = TextToColor(value);
else if(stricmp(setting, "TextColor") == 0)
cTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedTextColor") == 0)
cSelectedTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedColor") == 0)
cSelectedTextBgColor = TextToColor(value);
else if(stricmp(setting, "OS") == 0)
{
if(nNumOS >= 16)
{
printf("Error: you can only boot to at most 16 different operating systems.\n");
printf("Press any key to continue\n");
getch();
return;
}
if(!GetNumSectionItems(value))
{
printf("Error: OS \"%s\" listed.\n", value);
printf("It does not have it's own [section], or it is empty.\n");
printf("Press any key to continue\n");
getch();
return;
}
strcpy(OSList[nNumOS].name, value);
if (!ReadSectionSettingByName(value, "BootType", 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);
}

View file

@ -0,0 +1,33 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __PARSEINI_H
#define __PARSEINI_H
BOOL ParseIniFile(void);
ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset); // Gets the next line of text (up to BufferSize) after CurrentOffset and returns the offset of the next line
ULONG GetOffsetOfFirstLineOfSection(PUCHAR SectionName); // Returns the offset of the first line in the section or zero if the section wasn't found
ULONG GetNumSectionItems(PUCHAR SectionName); // returns the number of items in a particular section (i.e. [FREELOADER])
BOOL ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue); // Reads the num'th value from section
BOOL ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue); // Reads the value named name from section
BOOL IsValidSetting(char *setting, char *value);
void SetSetting(char *setting, char *value);
#endif // defined __PARSEINI_H

View file

@ -27,11 +27,12 @@
#include "multiboot.h"
#include "arcname.h"
#include "memory.h"
#include "parseini.h"
BOOL LoadReactOSKernel(char *OperatingSystemName);
BOOL LoadReactOSDrivers(char *OperatingSystemName);
BOOL LoadReactOSKernel(PUCHAR OperatingSystemName);
BOOL LoadReactOSDrivers(PUCHAR OperatingSystemName);
void LoadAndBootReactOS(char *OperatingSystemName)
void LoadAndBootReactOS(PUCHAR OperatingSystemName)
{
FILE file;
char name[1024];
@ -72,7 +73,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
/*
* Make sure the system path is set in the .ini file
*/
if(!ReadSectionSettingByName(OperatingSystemName, "SystemPath", name, value))
if (!ReadSectionSettingByName(OperatingSystemName, "SystemPath", value))
{
MessageBox("System path not specified for selected operating system.");
return;
@ -81,7 +82,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
/*
* Verify system path
*/
if(!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
{
sprintf(MsgBuffer,"Invalid system path: '%s'", value);
MessageBox(MsgBuffer);
@ -98,7 +99,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
/*
* Read the optional kernel parameters (if any)
*/
if (ReadSectionSettingByName(OperatingSystemName, "Options", name, value))
if (ReadSectionSettingByName(OperatingSystemName, "Options", value))
{
strcat(multiboot_kernel_cmdline, " ");
strcat(multiboot_kernel_cmdline, value);
@ -112,7 +113,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
/*
* Find the kernel image name
*/
if(!ReadSectionSettingByName(OperatingSystemName, "Kernel", name, value))
if(!ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
{
MessageBox("Kernel image file not specified for selected operating system.");
return;
@ -149,7 +150,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
* Find the kernel image name
* and try to load the kernel off the disk
*/
if(ReadSectionSettingByName(OperatingSystemName, "Kernel", name, value))
if(ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
{
/*
* Set the name and try to open the PE image
@ -254,7 +255,7 @@ void LoadAndBootReactOS(char *OperatingSystemName)
strcat(name, ".");
//MessageBox(name);
RestoreScreen(pScreenBuffer);
RestoreScreen(ScreenBuffer);
/*
* Now boot the kernel

View file

@ -21,7 +21,7 @@
#define __ROSBOOT_H
void LoadAndBootReactOS(char *OperatingSystemName);
void LoadAndBootReactOS(PUCHAR OperatingSystemName);
#endif // defined __ROSBOOT_H

View file

@ -54,11 +54,15 @@ void *memset(void *dest, int c, size_t count);
char *fgets(char *string, int n, FILE *stream);
int atoi(char *string);
#define ZeroMemory(Destination, Length) memset(Destination, 0, Length)
void print(char *str);
void printf(char *fmt, ...);
void sprintf(char *buffer, char *format, ...);
char *convert_to_ascii(char *buf, int c, ...);
int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
void stop_floppy(void); // Implemented in asmcode.S
int get_heads(int drive); // Implemented in asmcode.S