mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
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:
parent
8c136a909a
commit
a9450f5a72
17 changed files with 499 additions and 114 deletions
|
@ -71,13 +71,13 @@
|
|||
|
||||
[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=
|
||||
MessageBox=Edit your FREELDR.INI file to change your boot settings.
|
||||
OS=ReactOS (HD)
|
||||
OS=ReactOS (Floppy)
|
||||
;OS=ReactOS (Debug)
|
||||
;OS=Linux
|
||||
OS=Linux
|
||||
OS=3« Floppy (A:)
|
||||
OS=Microsoft Windows (C:)
|
||||
OS=Drive D:
|
||||
|
@ -134,12 +134,12 @@ Driver=\reactos\VFATFS.SYS
|
|||
;Driver=\DRIVERS\IDE.SYS
|
||||
;Driver=\DRIVERS\VFATFS.SYS
|
||||
|
||||
;[Linux]
|
||||
;Name="Linux"
|
||||
; Linux boot type not implemented yet
|
||||
;BootType=Partition
|
||||
;BootDrive=0x80
|
||||
;BootPartition=2
|
||||
[Linux]
|
||||
Name="Debian Linux 2.2.17"
|
||||
BootType=Partition
|
||||
BootDrive=0
|
||||
Kernel=/vmlinuz
|
||||
CommandLine=root=/dev/sdb1
|
||||
|
||||
[3« Floppy (A:)]
|
||||
Name="3« Floppy (A:)"
|
||||
|
|
|
@ -44,6 +44,6 @@ bin2c.exe: bin2c.c
|
|||
$(CC) -o bin2c.exe bin2c.c
|
||||
|
||||
clean:
|
||||
$(RM) *.bin
|
||||
$(RM) *.exe
|
||||
$(RM) *.h
|
||||
- $(RM) *.bin
|
||||
- $(RM) *.exe
|
||||
- $(RM) *.h
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
cd bootsect
|
||||
call make.bat
|
||||
cd..
|
||||
cd freeldr
|
||||
make
|
||||
copy freeldr.sys ..
|
||||
cd ..
|
|
@ -33,6 +33,16 @@ EXTERN(_JumpToBootCode)
|
|||
/* Set the boot drive */
|
||||
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
|
||||
|
||||
|
||||
|
@ -44,4 +54,14 @@ EXTERN(_JumpToLinuxBootCode)
|
|||
/* Set the boot drive */
|
||||
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
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
#ifdef DEBUG
|
||||
|
||||
//ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
|
||||
// DPRINT_UI | DPRINT_DISK | DPRINT_CACHE;
|
||||
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
|
||||
DPRINT_UI | DPRINT_DISK;
|
||||
// DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
|
||||
// DPRINT_LINUX;
|
||||
ULONG DebugPrintMask = DPRINT_WARNING | /*DPRINT_FILESYSTEM |
|
||||
DPRINT_CACHE |*/ DPRINT_LINUX;
|
||||
//ULONG DebugPrintMask = DPRINT_INIFILE;
|
||||
|
||||
#define SCREEN 0
|
||||
|
@ -153,6 +154,26 @@ VOID DebugPrintHeader(ULONG Mask)
|
|||
DebugPrintChar(':');
|
||||
DebugPrintChar(' ');
|
||||
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:
|
||||
DebugPrintChar('U');
|
||||
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
|
||||
|
|
|
@ -30,17 +30,22 @@
|
|||
#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_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 DebugPrint(ULONG Mask, char *format, ...);
|
||||
VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length);
|
||||
|
||||
#define DbgPrint(_x_) DebugPrint _x_
|
||||
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); DebugPrint _x_ ; for (;;); }
|
||||
#define DbgPrint(_x_) DebugPrint _x_
|
||||
#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
|
||||
|
||||
#define DbgPrint(_x_)
|
||||
#define BugCheck(_x_)
|
||||
#define DbgDumpBuffer(_x_, _y_, _z_)
|
||||
|
||||
#endif // defined DEBUG
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorC
|
|||
// LBA is easy, nothing to calculate
|
||||
// Just do the read
|
||||
//
|
||||
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
|
||||
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, SectorCount, Buffer))
|
||||
{
|
||||
DiskError("Disk read error.");
|
||||
return FALSE;
|
||||
|
|
|
@ -43,7 +43,7 @@ BOOL DiskIsDriveRemovable(ULONG DriveNumber)
|
|||
|
||||
BOOL DiskIsDriveCdRom(ULONG DriveNumber)
|
||||
{
|
||||
PUCHAR Sector;
|
||||
PUCHAR Sector = (PUCHAR)DISKREADBUFFER;
|
||||
BOOL Result;
|
||||
|
||||
// Hard disks use drive numbers >= 0x80
|
||||
|
@ -51,7 +51,6 @@ BOOL DiskIsDriveCdRom(ULONG DriveNumber)
|
|||
// then return FALSE
|
||||
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
|
||||
{
|
||||
Sector = AllocateMemory(2048);
|
||||
|
||||
if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector))
|
||||
{
|
||||
|
@ -67,8 +66,6 @@ BOOL DiskIsDriveCdRom(ULONG DriveNumber)
|
|||
Sector[4] == '0' &&
|
||||
Sector[5] == '1');
|
||||
|
||||
FreeMemory(Sector);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ VOID BootMain(VOID)
|
|||
}
|
||||
else if (stricmp(SettingValue, "Linux") == 0)
|
||||
{
|
||||
MessageBox("Cannot boot this OS type yet!");
|
||||
LoadAndBootLinux(OperatingSystemSectionNames[SelectedOperatingSystem]);
|
||||
}
|
||||
else if (stricmp(SettingValue, "BootSector") == 0)
|
||||
{
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
|
||||
|
||||
/* 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 ROSLDR_MAJOR_VERSION 0
|
||||
#define ROSLDR_MINOR_VERSION 8
|
||||
#define ROSLDR_MAJOR_VERSION 1
|
||||
#define ROSLDR_MINOR_VERSION 0
|
||||
#define ROSLDR_PATCH_VERSION 0
|
||||
|
||||
#define size_t unsigned int
|
||||
|
|
|
@ -576,9 +576,9 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
|
|||
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++;
|
||||
}
|
||||
|
@ -601,7 +601,7 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
|
|||
//
|
||||
// Advance to the next part of the path
|
||||
//
|
||||
for (; (*FileName != '\\') && (*FileName != '\0'); FileName++)
|
||||
for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
|
||||
{
|
||||
}
|
||||
FileName++;
|
||||
|
@ -654,7 +654,7 @@ ULONG FatGetNumPathParts(PUCHAR Path)
|
|||
|
||||
for (i=0,num=0; i<(int)strlen(Path); i++)
|
||||
{
|
||||
if (Path[i] == '\\')
|
||||
if ((Path[i] == '\\') || (Path[i] == '/'))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
|
@ -681,7 +681,7 @@ VOID FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
|
|||
// and put them in Buffer
|
||||
for (i=0; i<(int)strlen(Path); i++)
|
||||
{
|
||||
if (Path[i] == '\\')
|
||||
if ((Path[i] == '\\') || (Path[i] == '/'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1217,8 +1217,8 @@ BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Bu
|
|||
{
|
||||
*BytesRead += BytesToRead;
|
||||
}
|
||||
BytesToRead -= BytesToRead;
|
||||
FatFileInfo->FilePointer += BytesToRead;
|
||||
BytesToRead -= BytesToRead;
|
||||
Buffer += BytesToRead;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ static ULONG IsoGetNumPathParts(PUCHAR Path)
|
|||
|
||||
for (i=0,num=0; i<(int)strlen(Path); i++)
|
||||
{
|
||||
if (Path[i] == '\\')
|
||||
if ((Path[i] == '\\') || (Path[i] == '/'))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ static VOID IsoGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path)
|
|||
// and put them in Buffer
|
||||
for (i=0; i<(int)strlen(Path); i++)
|
||||
{
|
||||
if (Path[i] == '\\')
|
||||
if ((Path[i] == '\\') || (Path[i] == '/'))
|
||||
{
|
||||
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
|
||||
//
|
||||
while (*FileName == '\\')
|
||||
while ((*FileName == '\\') || (*FileName == '/'))
|
||||
{
|
||||
FileName++;
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ static BOOL IsoLookupFile(PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
|
|||
//
|
||||
// Advance to the next part of the path
|
||||
//
|
||||
for (; (*FileName != '\\') && (*FileName != '\0'); FileName++)
|
||||
for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
|
||||
{
|
||||
}
|
||||
FileName++;
|
||||
|
@ -535,8 +535,8 @@ BOOL IsoReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Bu
|
|||
{
|
||||
*BytesRead += BytesToRead;
|
||||
}
|
||||
BytesToRead -= BytesToRead;
|
||||
IsoFileInfo->FilePointer += BytesToRead;
|
||||
BytesToRead -= BytesToRead;
|
||||
Buffer += BytesToRead;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,77 +25,273 @@
|
|||
#include "fs.h"
|
||||
#include "ui.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;
|
||||
char temp[260];
|
||||
char bootsector[512];
|
||||
char setup[2048];
|
||||
int len;
|
||||
PFILE LinuxKernel = NULL;
|
||||
UCHAR TempString[260];
|
||||
|
||||
BootDrive = DriveNum;
|
||||
BootPartition = Partition;
|
||||
DrawBackdrop();
|
||||
|
||||
// Parse the .ini file section
|
||||
if (!LinuxParseIniSection(OperatingSystemName))
|
||||
{
|
||||
goto LinuxBootFailed;
|
||||
}
|
||||
|
||||
// Open the boot volume
|
||||
if (!OpenDiskDrive(BootDrive, BootPartition))
|
||||
{
|
||||
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);
|
||||
strcat(temp, " not found.");
|
||||
MessageBox(temp);
|
||||
return;
|
||||
sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName);
|
||||
MessageBox(TempString);
|
||||
goto LinuxBootFailed;
|
||||
}
|
||||
|
||||
// Read boot sector
|
||||
if (ReadFile(&file, 512, bootsector) != 512)
|
||||
// Read the boot sector
|
||||
if (!LinuxReadBootSector(LinuxKernel))
|
||||
{
|
||||
MessageBox("Disk Read Error");
|
||||
return;
|
||||
goto LinuxBootFailed;
|
||||
}
|
||||
MessageBox("bootsector loaded");
|
||||
|
||||
// Read setup code
|
||||
if (ReadFile(&file, 2048, setup) != 2048)
|
||||
// Read the setup sector
|
||||
if (!LinuxReadSetupSector(LinuxKernel))
|
||||
{
|
||||
MessageBox("Disk Read Error");
|
||||
return;
|
||||
goto LinuxBootFailed;
|
||||
}
|
||||
MessageBox("setup loaded");
|
||||
|
||||
// Read kernel code
|
||||
len = GetFileSize(&file) - (2048 + 512);
|
||||
//len = 0x200;
|
||||
if (ReadFile(&file, len, (void*)0x100000) != len)
|
||||
// Read the kernel
|
||||
if (!LinuxReadKernel(LinuxKernel))
|
||||
{
|
||||
MessageBox("Disk Read Error");
|
||||
return;
|
||||
}
|
||||
MessageBox("kernel loaded");
|
||||
|
||||
// Check for validity
|
||||
if (*((WORD*)(bootsector + 0x1fe)) != 0xaa55)
|
||||
{
|
||||
MessageBox("Invalid boot sector magic (0xaa55)");
|
||||
return;
|
||||
}
|
||||
if (*((DWORD*)(setup + 2)) != 0x53726448)
|
||||
{
|
||||
MessageBox("Invalid setup magic (\"HdrS\")");
|
||||
return;
|
||||
goto LinuxBootFailed;
|
||||
}
|
||||
|
||||
memcpy((void*)0x90000, bootsector, 512);
|
||||
memcpy((void*)0x90200, setup, 2048);
|
||||
LinuxBootSector->CommandLineMagic = LINUX_COMMAND_LINE_MAGIC;
|
||||
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();
|
||||
gotoxy(CursorXPos, CursorYPos);
|
||||
clrscr();
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,107 @@
|
|||
#ifndef __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 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
|
||||
|
|
|
@ -45,6 +45,7 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
|
|||
if (NumberOfBytes == 0)
|
||||
{
|
||||
DbgPrint((DPRINT_MEMORY, "AllocateMemory() called for 0 bytes. Returning NULL.\n"));
|
||||
MessageBox("Memory allocation failed: AllocateMemory() called for 0 bytes.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
cd bootsect
|
||||
call install.bat
|
||||
cd..
|
||||
copy freeldr.sys a:\FREELDR.SYS
|
||||
copy freeldr.ini a:\FREELDR.INI
|
|
@ -1,25 +1,10 @@
|
|||
FreeLoader notes
|
||||
|
||||
To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code
|
||||
FreeLoader does not currently work with extended partitions.
|
||||
Linux booting support needs to be added.
|
||||
ext2 filesystem support needs to be added.
|
||||
The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails.
|
||||
|
||||
Old 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:
|
||||
Memory layout:
|
||||
|
||||
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
|
||||
0000:1000 - 0000:6FFF: Real mode stack area
|
||||
|
|
Loading…
Reference in a new issue