FreeLoader version 1.0!

Supports booting Linux bzImage kernels
No initrd support (yet)
No zImage support (yet)
No ext2 file system support (yet)
Forward slashes '/' as well as backslashes '\' can be used for path names in FAT & ISO-9660
Fixed bug in LBA code where is was only reading one sector even if you asked for more
Fixed bug in FAT code, was also present in ISO-9660 code

svn path=/trunk/; revision=2867
This commit is contained in:
Brian Palmer 2002-04-25 02:48:15 +00:00
parent 8c136a909a
commit a9450f5a72
17 changed files with 499 additions and 114 deletions

View file

@ -71,13 +71,13 @@
[FREELOADER] [FREELOADER]
MessageLine=Welcome to FreeLoader! MessageLine=Welcome to FreeLoader!
MessageLine=Copyright (c) 2001 by Brian Palmer <brianp@sginet.com> MessageLine=Copyright (c) 2002 by Brian Palmer <brianp@sginet.com>
MessageLine= MessageLine=
MessageBox=Edit your FREELDR.INI file to change your boot settings. MessageBox=Edit your FREELDR.INI file to change your boot settings.
OS=ReactOS (HD) OS=ReactOS (HD)
OS=ReactOS (Floppy) OS=ReactOS (Floppy)
;OS=ReactOS (Debug) ;OS=ReactOS (Debug)
;OS=Linux OS=Linux
OS=3« Floppy (A:) OS=3« Floppy (A:)
OS=Microsoft Windows (C:) OS=Microsoft Windows (C:)
OS=Drive D: OS=Drive D:
@ -134,12 +134,12 @@ Driver=\reactos\VFATFS.SYS
;Driver=\DRIVERS\IDE.SYS ;Driver=\DRIVERS\IDE.SYS
;Driver=\DRIVERS\VFATFS.SYS ;Driver=\DRIVERS\VFATFS.SYS
;[Linux] [Linux]
;Name="Linux" Name="Debian Linux 2.2.17"
; Linux boot type not implemented yet BootType=Partition
;BootType=Partition BootDrive=0
;BootDrive=0x80 Kernel=/vmlinuz
;BootPartition=2 CommandLine=root=/dev/sdb1
[3« Floppy (A:)] [3« Floppy (A:)]
Name="3« Floppy (A:)" Name="3« Floppy (A:)"

View file

@ -44,6 +44,6 @@ bin2c.exe: bin2c.c
$(CC) -o bin2c.exe bin2c.c $(CC) -o bin2c.exe bin2c.c
clean: clean:
$(RM) *.bin - $(RM) *.bin
$(RM) *.exe - $(RM) *.exe
$(RM) *.h - $(RM) *.h

View file

@ -1,7 +0,0 @@
cd bootsect
call make.bat
cd..
cd freeldr
make
copy freeldr.sys ..
cd ..

View file

@ -33,6 +33,16 @@ EXTERN(_JumpToBootCode)
/* Set the boot drive */ /* Set the boot drive */
movb (_BootDrive),%dl movb (_BootDrive),%dl
/* Load segment registers */
cli
movw $0x0000,%bx
movw %bx,%ds
movw %bx,%es
movw %bx,%fs
movw %bx,%gs
movw %bx,%ss
movw $0x7C00,%sp
ljmpl $0x0000,$0x7C00 ljmpl $0x0000,$0x7C00
@ -44,4 +54,14 @@ EXTERN(_JumpToLinuxBootCode)
/* Set the boot drive */ /* Set the boot drive */
movb (_BootDrive),%dl movb (_BootDrive),%dl
ljmpl $0x0200,$0x9000 /* Load segment registers */
cli
movw $0x9000,%bx
movw %bx,%ds
movw %bx,%es
movw %bx,%fs
movw %bx,%gs
movw %bx,%ss
movw $0x8FF4,%sp
ljmpl $0x9020,$0x0000

View file

@ -25,9 +25,10 @@
#ifdef DEBUG #ifdef DEBUG
//ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | //ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
// DPRINT_UI | DPRINT_DISK | DPRINT_CACHE; // DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | // DPRINT_LINUX;
DPRINT_UI | DPRINT_DISK; ULONG DebugPrintMask = DPRINT_WARNING | /*DPRINT_FILESYSTEM |
DPRINT_CACHE |*/ DPRINT_LINUX;
//ULONG DebugPrintMask = DPRINT_INIFILE; //ULONG DebugPrintMask = DPRINT_INIFILE;
#define SCREEN 0 #define SCREEN 0
@ -153,6 +154,26 @@ VOID DebugPrintHeader(ULONG Mask)
DebugPrintChar(':'); DebugPrintChar(':');
DebugPrintChar(' '); DebugPrintChar(' ');
break; break;
case DPRINT_REACTOS:
DebugPrintChar('R');
DebugPrintChar('E');
DebugPrintChar('A');
DebugPrintChar('C');
DebugPrintChar('T');
DebugPrintChar('O');
DebugPrintChar('S');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_LINUX:
DebugPrintChar('L');
DebugPrintChar('I');
DebugPrintChar('N');
DebugPrintChar('U');
DebugPrintChar('X');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
default: default:
DebugPrintChar('U'); DebugPrintChar('U');
DebugPrintChar('N'); DebugPrintChar('N');
@ -235,4 +256,77 @@ VOID DebugPrint(ULONG Mask, char *format, ...)
} }
VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length)
{
PUCHAR BufPtr = (PUCHAR)Buffer;
ULONG Idx;
ULONG Idx2;
// Mask out unwanted debug messages
if (!(Mask & DebugPrintMask))
{
return;
}
DebugStartOfLine = FALSE; // We don't want line headers
DebugPrint(Mask, "Dumping buffer at 0x%x with length of %d bytes:\n", Buffer, Length);
for (Idx=0; Idx<Length; )
{
DebugStartOfLine = FALSE; // We don't want line headers
if (Idx < 0x0010)
{
DebugPrint(Mask, "000%x:\t", Idx);
}
else if (Idx < 0x0100)
{
DebugPrint(Mask, "00%x:\t", Idx);
}
else if (Idx < 0x1000)
{
DebugPrint(Mask, "0%x:\t", Idx);
}
else
{
DebugPrint(Mask, "%x:\t", Idx);
}
for (Idx2=0; Idx2<16; Idx2++,Idx++)
{
if (BufPtr[Idx] < 0x10)
{
DebugPrint(Mask, "0");
}
DebugPrint(Mask, "%x", BufPtr[Idx]);
if (Idx2 == 7)
{
DebugPrint(Mask, "-");
}
else
{
DebugPrint(Mask, " ");
}
}
Idx -= 16;
DebugPrint(Mask, " ");
for (Idx2=0; Idx2<16; Idx2++,Idx++)
{
if ((BufPtr[Idx] > 20) && (BufPtr[Idx] < 0x80))
{
DebugPrint(Mask, "%c", BufPtr[Idx]);
}
else
{
DebugPrint(Mask, ".");
}
}
DebugPrint(Mask, "\n");
}
}
#endif // defined DEBUG #endif // defined DEBUG

View file

@ -30,17 +30,22 @@
#define DPRINT_UI 0x00000010 // OR this with DebugPrintMask to enable user interface messages #define DPRINT_UI 0x00000010 // OR this with DebugPrintMask to enable user interface messages
#define DPRINT_DISK 0x00000020 // OR this with DebugPrintMask to enable disk messages #define DPRINT_DISK 0x00000020 // OR this with DebugPrintMask to enable disk messages
#define DPRINT_CACHE 0x00000040 // OR this with DebugPrintMask to enable cache messages #define DPRINT_CACHE 0x00000040 // OR this with DebugPrintMask to enable cache messages
#define DPRINT_REACTOS 0x00000080 // OR this with DebugPrintMask to enable ReactOS messages
#define DPRINT_LINUX 0x00000100 // OR this with DebugPrintMask to enable Linux messages
VOID DebugInit(VOID); VOID DebugInit(VOID);
VOID DebugPrint(ULONG Mask, char *format, ...); VOID DebugPrint(ULONG Mask, char *format, ...);
VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length);
#define DbgPrint(_x_) DebugPrint _x_ #define DbgPrint(_x_) DebugPrint _x_
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); DebugPrint _x_ ; for (;;); } #define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); DebugPrint _x_ ; for (;;); }
#define DbgDumpBuffer(_x_, _y_, _z_) DebugDumpBuffer(_x_, _y_, _z_)
#else #else
#define DbgPrint(_x_) #define DbgPrint(_x_)
#define BugCheck(_x_) #define BugCheck(_x_)
#define DbgDumpBuffer(_x_, _y_, _z_)
#endif // defined DEBUG #endif // defined DEBUG

View file

@ -73,7 +73,7 @@ BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorC
// LBA is easy, nothing to calculate // LBA is easy, nothing to calculate
// Just do the read // Just do the read
// //
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer)) if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, SectorCount, Buffer))
{ {
DiskError("Disk read error."); DiskError("Disk read error.");
return FALSE; return FALSE;

View file

@ -43,7 +43,7 @@ BOOL DiskIsDriveRemovable(ULONG DriveNumber)
BOOL DiskIsDriveCdRom(ULONG DriveNumber) BOOL DiskIsDriveCdRom(ULONG DriveNumber)
{ {
PUCHAR Sector; PUCHAR Sector = (PUCHAR)DISKREADBUFFER;
BOOL Result; BOOL Result;
// Hard disks use drive numbers >= 0x80 // Hard disks use drive numbers >= 0x80
@ -51,7 +51,6 @@ BOOL DiskIsDriveCdRom(ULONG DriveNumber)
// then return FALSE // then return FALSE
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber))) if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
{ {
Sector = AllocateMemory(2048);
if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector)) if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector))
{ {
@ -67,8 +66,6 @@ BOOL DiskIsDriveCdRom(ULONG DriveNumber)
Sector[4] == '0' && Sector[4] == '0' &&
Sector[5] == '1'); Sector[5] == '1');
FreeMemory(Sector);
return Result; return Result;
} }

View file

@ -131,7 +131,7 @@ VOID BootMain(VOID)
} }
else if (stricmp(SettingValue, "Linux") == 0) else if (stricmp(SettingValue, "Linux") == 0)
{ {
MessageBox("Cannot boot this OS type yet!"); LoadAndBootLinux(OperatingSystemSectionNames[SelectedOperatingSystem]);
} }
else if (stricmp(SettingValue, "BootSector") == 0) else if (stricmp(SettingValue, "BootSector") == 0)
{ {

View file

@ -22,11 +22,11 @@
/* just some stuff */ /* just some stuff */
#define VERSION "FreeLoader v0.9" #define VERSION "FreeLoader v1.0"
#define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>" #define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>"
#define ROSLDR_MAJOR_VERSION 0 #define ROSLDR_MAJOR_VERSION 1
#define ROSLDR_MINOR_VERSION 8 #define ROSLDR_MINOR_VERSION 0
#define ROSLDR_PATCH_VERSION 0 #define ROSLDR_PATCH_VERSION 0
#define size_t unsigned int #define size_t unsigned int

View file

@ -576,9 +576,9 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
memset(FatFileInfoPointer, 0, sizeof(FAT_FILE_INFO)); memset(FatFileInfoPointer, 0, sizeof(FAT_FILE_INFO));
// //
// Check and see if the first character is '\' and remove it if so // Check and see if the first character is '\' or '/' and remove it if so
// //
while (*FileName == '\\') while ((*FileName == '\\') || (*FileName == '/'))
{ {
FileName++; FileName++;
} }
@ -601,7 +601,7 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
// //
// Advance to the next part of the path // Advance to the next part of the path
// //
for (; (*FileName != '\\') && (*FileName != '\0'); FileName++) for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
{ {
} }
FileName++; FileName++;
@ -654,7 +654,7 @@ ULONG FatGetNumPathParts(PUCHAR Path)
for (i=0,num=0; i<(int)strlen(Path); i++) for (i=0,num=0; i<(int)strlen(Path); i++)
{ {
if (Path[i] == '\\') if ((Path[i] == '\\') || (Path[i] == '/'))
{ {
num++; num++;
} }
@ -681,7 +681,7 @@ VOID FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
// and put them in Buffer // and put them in Buffer
for (i=0; i<(int)strlen(Path); i++) for (i=0; i<(int)strlen(Path); i++)
{ {
if (Path[i] == '\\') if ((Path[i] == '\\') || (Path[i] == '/'))
{ {
break; break;
} }
@ -1217,8 +1217,8 @@ BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Bu
{ {
*BytesRead += BytesToRead; *BytesRead += BytesToRead;
} }
BytesToRead -= BytesToRead;
FatFileInfo->FilePointer += BytesToRead; FatFileInfo->FilePointer += BytesToRead;
BytesToRead -= BytesToRead;
Buffer += BytesToRead; Buffer += BytesToRead;
} }

View file

@ -186,7 +186,7 @@ static ULONG IsoGetNumPathParts(PUCHAR Path)
for (i=0,num=0; i<(int)strlen(Path); i++) for (i=0,num=0; i<(int)strlen(Path); i++)
{ {
if (Path[i] == '\\') if ((Path[i] == '\\') || (Path[i] == '/'))
{ {
num++; num++;
} }
@ -215,7 +215,7 @@ static VOID IsoGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
// and put them in Buffer // and put them in Buffer
for (i=0; i<(int)strlen(Path); i++) for (i=0; i<(int)strlen(Path); i++)
{ {
if (Path[i] == '\\') if ((Path[i] == '\\') || (Path[i] == '/'))
{ {
break; break;
} }
@ -257,7 +257,7 @@ static BOOL IsoLookupFile(PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
// //
// Check and see if the first character is '\' and remove it if so // Check and see if the first character is '\' and remove it if so
// //
while (*FileName == '\\') while ((*FileName == '\\') || (*FileName == '/'))
{ {
FileName++; FileName++;
} }
@ -283,7 +283,7 @@ static BOOL IsoLookupFile(PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
// //
// Advance to the next part of the path // Advance to the next part of the path
// //
for (; (*FileName != '\\') && (*FileName != '\0'); FileName++) for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
{ {
} }
FileName++; FileName++;
@ -535,8 +535,8 @@ BOOL IsoReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Bu
{ {
*BytesRead += BytesToRead; *BytesRead += BytesToRead;
} }
BytesToRead -= BytesToRead;
IsoFileInfo->FilePointer += BytesToRead; IsoFileInfo->FilePointer += BytesToRead;
BytesToRead -= BytesToRead;
Buffer += BytesToRead; Buffer += BytesToRead;
} }

View file

@ -25,77 +25,273 @@
#include "fs.h" #include "fs.h"
#include "ui.h" #include "ui.h"
#include "linux.h" #include "linux.h"
#include "debug.h"
#include "mm.h"
#include "inifile.h"
void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line) PLINUX_BOOTSECTOR LinuxBootSector = NULL;
PLINUX_SETUPSECTOR LinuxSetupSector = NULL;
ULONG SetupSectorSize = 0;
BOOL BigZImageKernel = TRUE;
ULONG LinuxKernelSize = 0;
UCHAR LinuxKernelName[260];
UCHAR LinuxInitrdName[260];
BOOL LinuxHasInitrd = FALSE;
UCHAR LinuxCommandLine[260] = "";
ULONG LinuxCommandLineSize = 0;
VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
{ {
/*FILE file; PFILE LinuxKernel = NULL;
char temp[260]; UCHAR TempString[260];
char bootsector[512];
char setup[2048];
int len;
BootDrive = DriveNum; DrawBackdrop();
BootPartition = Partition;
// Parse the .ini file section
if (!LinuxParseIniSection(OperatingSystemName))
{
goto LinuxBootFailed;
}
// Open the boot volume
if (!OpenDiskDrive(BootDrive, BootPartition)) if (!OpenDiskDrive(BootDrive, BootPartition))
{ {
MessageBox("Failed to open boot drive."); MessageBox("Failed to open boot drive.");
return; goto LinuxBootFailed;
} }
if (!OpenFile(vmlinuz, &file)) // Open the kernel
LinuxKernel = OpenFile(LinuxKernelName);
if (LinuxKernel == NULL)
{ {
strcpy(temp, vmlinuz); sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName);
strcat(temp, " not found."); MessageBox(TempString);
MessageBox(temp); goto LinuxBootFailed;
return;
} }
// Read boot sector // Read the boot sector
if (ReadFile(&file, 512, bootsector) != 512) if (!LinuxReadBootSector(LinuxKernel))
{ {
MessageBox("Disk Read Error"); goto LinuxBootFailed;
return;
} }
MessageBox("bootsector loaded");
// Read setup code // Read the setup sector
if (ReadFile(&file, 2048, setup) != 2048) if (!LinuxReadSetupSector(LinuxKernel))
{ {
MessageBox("Disk Read Error"); goto LinuxBootFailed;
return;
} }
MessageBox("setup loaded");
// Read kernel code // Read the kernel
len = GetFileSize(&file) - (2048 + 512); if (!LinuxReadKernel(LinuxKernel))
//len = 0x200;
if (ReadFile(&file, len, (void*)0x100000) != len)
{ {
MessageBox("Disk Read Error"); goto LinuxBootFailed;
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); LinuxBootSector->CommandLineMagic = LINUX_COMMAND_LINE_MAGIC;
memcpy((void*)0x90200, setup, 2048); LinuxBootSector->CommandLineOffset = 0x9000;
LinuxSetupSector->TypeOfLoader = LINUX_LOADER_TYPE_FREELOADER;
RtlCopyMemory((PVOID)0x90000, LinuxBootSector, 512);
RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize);
RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize);
RestoreScreen(ScreenBuffer);
showcursor(); showcursor();
gotoxy(CursorXPos, CursorYPos); clrscr();
stop_floppy(); stop_floppy();
JumpToLinuxBootCode();*/ JumpToLinuxBootCode();
LinuxBootFailed:
if (LinuxKernel != NULL)
{
CloseFile(LinuxKernel);
}
if (LinuxBootSector != NULL)
{
FreeMemory(LinuxBootSector);
}
if (LinuxSetupSector != NULL)
{
FreeMemory(LinuxSetupSector);
}
LinuxBootSector = NULL;
LinuxSetupSector = NULL;
SetupSectorSize = 0;
BigZImageKernel = TRUE;
LinuxKernelSize = 0;
LinuxHasInitrd = FALSE;
strcpy(LinuxCommandLine, "");
LinuxCommandLineSize = 0;
}
BOOL LinuxParseIniSection(PUCHAR OperatingSystemName)
{
UCHAR SettingName[260];
UCHAR SettingValue[260];
ULONG SectionId;
// Find all the message box settings and run them
ShowMessageBoxesInSection(OperatingSystemName);
// Try to open the operating system section in the .ini file
if (!IniOpenSection(OperatingSystemName, &SectionId))
{
sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", OperatingSystemName);
MessageBox(SettingName);
return FALSE;
}
if (!IniReadSettingByName(SectionId, "BootDrive", SettingValue, 260))
{
MessageBox("Boot drive not specified for selected OS!");
return FALSE;
}
BootDrive = atoi(SettingValue);
BootPartition = 0;
if (IniReadSettingByName(SectionId, "BootPartition", SettingValue, 260))
{
BootPartition = atoi(SettingValue);
}
// Get the kernel name
if (!IniReadSettingByName(SectionId, "Kernel", LinuxKernelName, 260))
{
MessageBox("Linux kernel filename not specified for selected OS!");
return FALSE;
}
// Get the initrd name
if (IniReadSettingByName(SectionId, "Initrd", LinuxInitrdName, 260))
{
LinuxHasInitrd = TRUE;
}
// Get the command line
if (IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLine, 260))
{
LinuxCommandLineSize = strlen(LinuxCommandLine) + 1;
}
return TRUE;
}
BOOL LinuxReadBootSector(PFILE LinuxKernelFile)
{
// Allocate memory for boot sector
LinuxBootSector = (PLINUX_BOOTSECTOR)AllocateMemory(512);
if (LinuxBootSector == NULL)
{
return FALSE;
}
// Read linux boot sector
SetFilePointer(LinuxKernelFile, 0);
if (!ReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
{
return FALSE;
}
// Check for validity
if (LinuxBootSector->BootFlag != LINUX_BOOT_SECTOR_MAGIC)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return FALSE;
}
DbgDumpBuffer(DPRINT_LINUX, LinuxBootSector, 512);
DbgPrint((DPRINT_LINUX, "SetupSectors: %d\n", LinuxBootSector->SetupSectors));
DbgPrint((DPRINT_LINUX, "RootFlags: 0x%x\n", LinuxBootSector->RootFlags));
DbgPrint((DPRINT_LINUX, "SystemSize: 0x%x\n", LinuxBootSector->SystemSize));
DbgPrint((DPRINT_LINUX, "SwapDevice: 0x%x\n", LinuxBootSector->SwapDevice));
DbgPrint((DPRINT_LINUX, "RamSize: 0x%x\n", LinuxBootSector->RamSize));
DbgPrint((DPRINT_LINUX, "VideoMode: 0x%x\n", LinuxBootSector->VideoMode));
DbgPrint((DPRINT_LINUX, "RootDevice: 0x%x\n", LinuxBootSector->RootDevice));
DbgPrint((DPRINT_LINUX, "BootFlag: 0x%x\n", LinuxBootSector->BootFlag));
return TRUE;
}
BOOL LinuxReadSetupSector(PFILE LinuxKernelFile)
{
SetupSectorSize = 512 * LinuxBootSector->SetupSectors;
// Allocate memory for setup sectors
LinuxSetupSector = (PLINUX_SETUPSECTOR)AllocateMemory(SetupSectorSize);
if (LinuxSetupSector == NULL)
{
return FALSE;
}
// Read linux setup sectors
SetFilePointer(LinuxKernelFile, 512);
if (!ReadFile(LinuxKernelFile, SetupSectorSize, NULL, LinuxSetupSector))
{
return FALSE;
}
// Check for validity
if (LinuxSetupSector->SetupHeaderSignature != LINUX_SETUP_HEADER_ID)
{
MessageBox("Invalid setup magic (HdrS)");
return FALSE;
}
DbgDumpBuffer(DPRINT_LINUX, LinuxSetupSector, SetupSectorSize);
DbgPrint((DPRINT_LINUX, "SetupHeaderSignature: 0x%x (HdrS)\n", LinuxSetupSector->SetupHeaderSignature));
DbgPrint((DPRINT_LINUX, "Version: 0x%x\n", LinuxSetupSector->Version));
DbgPrint((DPRINT_LINUX, "RealModeSwitch: 0x%x\n", LinuxSetupSector->RealModeSwitch));
DbgPrint((DPRINT_LINUX, "SetupSeg: 0x%x\n", LinuxSetupSector->SetupSeg));
DbgPrint((DPRINT_LINUX, "StartSystemSeg: 0x%x\n", LinuxSetupSector->StartSystemSeg));
DbgPrint((DPRINT_LINUX, "KernelVersion: 0x%x\n", LinuxSetupSector->KernelVersion));
DbgPrint((DPRINT_LINUX, "TypeOfLoader: 0x%x\n", LinuxSetupSector->TypeOfLoader));
DbgPrint((DPRINT_LINUX, "LoadFlags: 0x%x\n", LinuxSetupSector->LoadFlags));
DbgPrint((DPRINT_LINUX, "SetupMoveSize: 0x%x\n", LinuxSetupSector->SetupMoveSize));
DbgPrint((DPRINT_LINUX, "Code32Start: 0x%x\n", LinuxSetupSector->Code32Start));
DbgPrint((DPRINT_LINUX, "RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress));
DbgPrint((DPRINT_LINUX, "RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize));
DbgPrint((DPRINT_LINUX, "BootSectKludgeOffset: 0x%x\n", LinuxSetupSector->BootSectKludgeOffset));
DbgPrint((DPRINT_LINUX, "BootSectKludgeSegment: 0x%x\n", LinuxSetupSector->BootSectKludgeSegment));
DbgPrint((DPRINT_LINUX, "HeapEnd: 0x%x\n", LinuxSetupSector->HeapEnd));
return TRUE;
}
BOOL LinuxReadKernel(PFILE LinuxKernelFile)
{
PVOID LoadAddress = (PVOID)LINUX_KERNEL_LOAD_ADDRESS;
ULONG BytesLoaded;
UCHAR StatusText[260];
sprintf(StatusText, " Loading %s", LinuxKernelName);
DrawStatusText(StatusText);
DrawProgressBar(0);
// Calc kernel size
LinuxKernelSize = GetFileSize(LinuxKernelFile) - (512 + SetupSectorSize);
// Read linux kernel to 0x100000 (1mb)
SetFilePointer(LinuxKernelFile, 512 + SetupSectorSize);
for (BytesLoaded=0; BytesLoaded<LinuxKernelSize; )
{
if (!ReadFile(LinuxKernelFile, 0x4000, NULL, LoadAddress))
{
return FALSE;
}
BytesLoaded += 0x4000;
LoadAddress += 0x4000;
DrawProgressBar( (BytesLoaded * 100) / LinuxKernelSize );
}
return TRUE;
} }

View file

@ -20,8 +20,107 @@
#ifndef __LINUX_H #ifndef __LINUX_H
#define __LINUX_H #define __LINUX_H
#define LINUX_LOADER_TYPE_LILO 0x01
#define LINUX_LOADER_TYPE_LOADLIN 0x11
#define LINUX_LOADER_TYPE_BOOTSECT 0x21
#define LINUX_LOADER_TYPE_SYSLINUX 0x31
#define LINUX_LOADER_TYPE_ETHERBOOT 0x41
#define LINUX_LOADER_TYPE_FREELOADER 0x81
#define LINUX_COMMAND_LINE_MAGIC 0xA33F
#define LINUX_SETUP_HEADER_ID 0x53726448 // 'HdrS'
#define LINUX_BOOT_SECTOR_MAGIC 0xAA55
#define LINUX_KERNEL_LOAD_ADDRESS 0x100000
typedef struct
{
BYTE BootCode1[0x20];
WORD CommandLineMagic;
WORD CommandLineOffset;
BYTE BootCode2[0x1CD];
BYTE SetupSectors;
WORD RootFlags;
WORD SystemSize;
WORD SwapDevice;
WORD RamSize;
WORD VideoMode;
WORD RootDevice;
WORD BootFlag; // 0xAA55
} PACKED LINUX_BOOTSECTOR, *PLINUX_BOOTSECTOR;
typedef struct
{
BYTE JumpInstruction[2];
DWORD SetupHeaderSignature; // Signature for SETUP-header
WORD Version; // Version number of header format
WORD RealModeSwitch; // Default switch
WORD SetupSeg; // SETUPSEG
WORD StartSystemSeg;
WORD KernelVersion; // Offset to kernel version string
BYTE TypeOfLoader; // Loader ID
// =0, old one (LILO, Loadlin,
// Bootlin, SYSLX, bootsect...)
// else it is set by the loader:
// 0xTV: T=0 for LILO
// T=1 for Loadlin
// T=2 for bootsect-loader
// T=3 for SYSLX
// T=4 for ETHERBOOT
// V = version
BYTE LoadFlags; // flags, unused bits must be zero (RFU)
// LOADED_HIGH = 1
// bit within loadflags,
// if set, then the kernel is loaded high
// CAN_USE_HEAP = 0x80
// if set, the loader also has set heap_end_ptr
// to tell how much space behind setup.S
// can be used for heap purposes.
// Only the loader knows what is free!
WORD SetupMoveSize; // size to move, when we (setup) are not
// loaded at 0x90000. We will move ourselves
// to 0x90000 then just before jumping into
// the kernel. However, only the loader
// know how much of data behind us also needs
// to be loaded.
DWORD Code32Start; // here loaders can put a different
// start address for 32-bit code.
//
// 0x1000 = default for zImage
//
// 0x100000 = default for big kernel
DWORD RamdiskAddress; // address of loaded ramdisk image
// Here the loader (or kernel generator) puts
// the 32-bit address were it loaded the image.
DWORD RamdiskSize; // its size in bytes
WORD BootSectKludgeOffset;
WORD BootSectKludgeSegment;
WORD HeapEnd; // space from here (exclusive) down to
// end of setup code can be used by setup
// for local heap purposes.
} PACKED LINUX_SETUPSECTOR, *PLINUX_SETUPSECTOR;
void JumpToLinuxBootCode(void); // Implemented in boot.S void JumpToLinuxBootCode(void); // Implemented in boot.S
void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line); VOID LoadAndBootLinux(PUCHAR OperatingSystemName);
BOOL LinuxParseIniSection(PUCHAR OperatingSystemName);
BOOL LinuxReadBootSector(PFILE LinuxKernelFile);
BOOL LinuxReadSetupSector(PFILE LinuxKernelFile);
BOOL LinuxReadKernel(PFILE LinuxKernelFile);
#endif // defined __LINUX_H #endif // defined __LINUX_H

View file

@ -45,6 +45,7 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
if (NumberOfBytes == 0) if (NumberOfBytes == 0)
{ {
DbgPrint((DPRINT_MEMORY, "AllocateMemory() called for 0 bytes. Returning NULL.\n")); DbgPrint((DPRINT_MEMORY, "AllocateMemory() called for 0 bytes. Returning NULL.\n"));
MessageBox("Memory allocation failed: AllocateMemory() called for 0 bytes.");
return NULL; return NULL;
} }

View file

@ -1,5 +0,0 @@
cd bootsect
call install.bat
cd..
copy freeldr.sys a:\FREELDR.SYS
copy freeldr.ini a:\FREELDR.INI

View file

@ -1,25 +1,10 @@
FreeLoader notes FreeLoader notes
To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code 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. ext2 filesystem support needs to be added.
The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails. The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails.
Old memory layout: 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
New memory layout:
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data 0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
0000:1000 - 0000:6FFF: Real mode stack area 0000:1000 - 0000:6FFF: Real mode stack area