Added BIOS drive mapping functionality

svn path=/trunk/; revision=3284
This commit is contained in:
Brian Palmer 2002-07-22 03:44:08 +00:00
parent c747481470
commit 1aa76f94bd
15 changed files with 525 additions and 100 deletions

View file

@ -53,6 +53,7 @@
; BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive
; BootDrive - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk
; BootPartition - sets the boot partition
; DriveMap - maps a BIOS drive number to another (i.e. DriveMap=hd1,hd0 maps harddisk1 to harddisk0 or DriveMap=fd1,fd0)
; [BootSector OSType] Section Commands:
;

View file

@ -1,7 +1,10 @@
Changes in v1.6 (7/21/2002) (brianp)
- Added BIOS drive mapping functionality
Changes in v1.5 (7/13/2002)
- If symbols are available then pass them to the OS as multiboot modules
- Added separate configuration for a SETUPLDR version
Changes in v1.4 (6/27/2002)

View file

@ -112,7 +112,8 @@ else
#############################################
# COMPILER COMMAND LINE OPTIONS
#
COMPILER_OPTIONS = -Wall -nostdlib -fno-builtin -O1 -MD
COMPILER_OPTIONS = -Wall -nostdlib -nostdinc -fno-builtin -O1 -MD
# FreeLoader does not use any of the standard libraries, includes, or built-in functions
#############################################
# COMPILER DEFINES
@ -180,9 +181,10 @@ ARCH_OBJS = fathelp.o \
linux.o \
mb.o \
mem.o \
diskint13.o \
biosdisk.o \
rtlcode.o \
biosvid.o
biosvid.o \
drvmap.o
RTL_OBJS = memory.o \
print.o \
@ -234,6 +236,7 @@ FREELDR_OBJS= freeldr.o \
debug.o \
oslist.o \
bootmgr.o \
drivemap.o \
version.o
#############################################

View file

@ -0,0 +1,132 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
.text
.code16
#define ASM
#include <arch.h>
EXTERN(_DriveMapInt13HandlerStart)
Int13Handler:
pushw %bp
movw %sp,%bp
pushw %ax
pushw %cx
pushw %si
cld
/* Get callers flags from stack */
movw 0x06(%bp),%ax
movw %ax,%cs:(CallersFlags - Int13Handler)
/* Save the drive number they passed in */
movb %dl,%cs:(PassedInDriveNumber - Int13Handler)
/* Now we need to perform the mapping */
xorw %cx,%cx
movw $(Int13HandlerMapCount - Int13Handler),%si
/* Get the count of drives in the map list */
movb %cs:(%si),%cl
incw %si
/* If the map list is empty then just call the old int 13h handler */
cmpb $0,%cl
jz CallOldInt13Handler
GetMappedDriveNumberLoop:
/* Get the next drive number in the list */
lodsw %cs:(%si),%ax
/* Check to see if it's the one they are calling int 13h for */
cmpb %al,%dl
/* If not get the next one */
jne GetMappedDriveNumberLoopNext
/* If we get here then we have found a mapped drive */
/* Send new drive number on to the old int 13h handler */
movb %ah,%dl
/* Call BIOS Int 13 Handler */
jmp CallOldInt13Handler
GetMappedDriveNumberLoopNext:
loop GetMappedDriveNumberLoop
CallOldInt13Handler:
/* Restore the registers we changed off the stack */
popw %si
popw %cx
popw %ax
/* Put flags onto stack */
pushw %cs:(CallersFlags - Int13Handler)
/* Call old int 13h handler with new drive number */
.byte 0x9a /* lcall */
EXTERN(_DriveMapOldInt13HandlerAddress)
.word 0
.word 0
/* Update the callers flags with the values the BIOS returned */
pushw %ax
pushf
popw %ax
movw %ax,0x06(%bp)
popw %ax
/* Restore the callers drive number */
movb %cs:(PassedInDriveNumber - Int13Handler),%dl
popw %bp
iret
CallersFlags:
.word 0
PassedInDriveNumber:
.byte 0
EXTERN(_DriveMapInt13HandlerMapList)
Int13HandlerMapCount:
.byte 0
Int13HandlerDrive1:
.byte 0
Int13HandlerDriveNew1:
.byte 0
Int13HandlerDrive2:
.byte 0
Int13HandlerDriveNew2:
.byte 0
Int13HandlerDrive3:
.byte 0
Int13HandlerDriveNew3:
.byte 0
Int13HandlerDrive4:
.byte 0
Int13HandlerDriveNew4:
.byte 0
EXTERN(_DriveMapInt13HandlerEnd)

View file

@ -31,6 +31,7 @@
#include <oslist.h>
#include <video.h>
#include <bootmgr.h>
#include <drivemap.h>
VOID RunBootManager(VOID)
{
@ -115,6 +116,9 @@ VOID RunBootManager(VOID)
continue;
}
// Install the drive mapper according to this sections drive mappings
DriveMapMapDrivesInSection(OperatingSystemSectionNames[SelectedOperatingSystem]);
if (stricmp(SettingValue, "ReactOS") == 0)
{
LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]);

View file

@ -32,6 +32,7 @@
///////////////////////////////////////////////////////////////////////////////////////
CACHE_DRIVE CacheManagerDrive;
BOOL CacheManagerInitialized = FALSE;
BOOL CacheManagerDataInvalid = FALSE;
ULONG CacheBlockCount = 0;
ULONG CacheSizeLimit = 0;
ULONG CacheSizeCurrent = 0;
@ -45,11 +46,14 @@ BOOL CacheInitializeDrive(ULONG DriveNumber)
// drive, in which case we'll invalidate the cache
if ((CacheManagerInitialized == TRUE) &&
(DriveNumber == CacheManagerDrive.DriveNumber) &&
(DriveNumber >= 0x80))
(DriveNumber >= 0x80) &&
(CacheManagerDataInvalid != TRUE))
{
return TRUE;
}
CacheManagerDataInvalid = FALSE;
//
// If we have already been initialized then free
// the old data
@ -120,6 +124,11 @@ BOOL CacheInitializeDrive(ULONG DriveNumber)
return TRUE;
}
VOID CacheInvalidateCacheData(VOID)
{
CacheManagerDataInvalid = TRUE;
}
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer)
{
PCACHE_BLOCK CacheBlock;

View file

@ -27,28 +27,20 @@
//#define DEBUG_ULTRA
//#define DEBUG_INIFILE
//#define DEBUG_REACTOS
//#define DEBUG_CUSTOM
#define DEBUG_NONE
#define DEBUG_CUSTOM
//#define DEBUG_NONE
#ifdef DEBUG_ULTRA
#if defined (DEBUG_ULTRA)
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
DPRINT_LINUX;
#endif
#ifdef DEBUG_INIFILE
DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
DPRINT_LINUX;
#elif defined (DEBUG_INIFILE)
ULONG DebugPrintMask = DPRINT_INIFILE;
#endif
#ifdef DEBUG_REACTOS
#elif defined (DEBUG_REACTOS)
ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
#endif
#ifdef DEBUG_CUSTOM
ULONG DebugPrintMask = 0;
#endif
#ifdef DEBUG_NONE
#elif defined (DEBUG_CUSTOM)
ULONG DebugPrintMask = DPRINT_WARNING;
#else //#elif defined (DEBUG_NONE)
ULONG DebugPrintMask = 0;
#endif
@ -253,7 +245,13 @@ VOID DebugPrint(ULONG Mask, char *format, ...)
}
else
{
switch (c = *(format++))
c = *(format++);
if (c == 'l')
{
c = *(format++);
}
switch (c)
{
case 'd': case 'u': case 'x':

219
freeldr/freeldr/drivemap.c Normal file
View file

@ -0,0 +1,219 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 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 <drivemap.h>
#include <rtl.h>
#include <inifile.h>
#include <cache.h>
#include <ui.h>
#include <debug.h>
BOOL DriveMapInstalled = FALSE; // Tells us if we have already installed our drive map int 13h handler code
ULONG OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler
ULONG DriveMapHandlerAddress = 0; // Linear address of our drive map handler
ULONG DriveMapHandlerSegOff = 0; // Segment:offset style address of our drive map handler
VOID DriveMapMapDrivesInSection(PUCHAR SectionName)
{
UCHAR SettingName[80];
UCHAR SettingValue[80];
UCHAR ErrorText[260];
UCHAR Drive1[80];
UCHAR Drive2[80];
ULONG SectionId;
ULONG SectionItemCount;
ULONG Index;
ULONG Index2;
DRIVE_MAP_LIST DriveMapList;
RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST));
if (!IniOpenSection(SectionName, &SectionId))
{
return;
}
// Get the number of items in this section
SectionItemCount = IniGetNumSectionItems(SectionId);
// Loop through each one and check if its a DriveMap= setting
for (Index=0; Index<SectionItemCount; Index++)
{
// Get the next setting from the .ini file section
if (IniReadSettingByNumber(SectionId, Index, SettingName, 80, SettingValue, 80))
{
if (stricmp(SettingName, "DriveMap") == 0)
{
// Make sure we haven't exceeded the drive map max count
if (DriveMapList.DriveMapCount >= 4)
{
sprintf(ErrorText, "Max DriveMap count exceeded in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
UiMessageBox(ErrorText);
continue;
}
RtlZeroMemory(Drive1, 80);
RtlZeroMemory(Drive2, 80);
strcpy(Drive1, SettingValue);
// Parse the setting value and separate a string "hd0,hd1"
// into two strings "hd0" and "hd1"
for (Index2=0; Index2<strlen(Drive1); Index2++)
{
// Check if this character is the separater character (comma - ',')
if (Drive1[Index2] == ',')
{
Drive1[Index2] = '\0';
strcpy(Drive2, &Drive1[Index2+1]);
break;
}
}
// Make sure we got good values before we add them to the map
if (!DriveMapIsValidDriveString(Drive1) || !DriveMapIsValidDriveString(Drive2))
{
sprintf(ErrorText, "Error in DriveMap setting in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
UiMessageBox(ErrorText);
continue;
}
// Add them to the map
DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)] = DriveMapGetBiosDriveNumber(Drive1);
DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)+1] = DriveMapGetBiosDriveNumber(Drive2);
DriveMapList.DriveMapCount++;
DbgPrint((DPRINT_WARNING, "Mapping BIOS drive 0x%x to drive 0x%x\n", DriveMapGetBiosDriveNumber(Drive1), DriveMapGetBiosDriveNumber(Drive2)));
}
}
}
if (DriveMapList.DriveMapCount)
{
DbgPrint((DPRINT_WARNING, "Installing Int13 drive map for %d drives.\n", DriveMapList.DriveMapCount));
DriveMapInstallInt13Handler(&DriveMapList);
}
else
{
DbgPrint((DPRINT_WARNING, "Removing any previously installed Int13 drive map.\n"));
DriveMapRemoveInt13Handler();
}
}
BOOL DriveMapIsValidDriveString(PUCHAR DriveString)
{
ULONG Index;
// Now verify that the user has given us appropriate strings
if ((strlen(DriveString) < 3) ||
((DriveString[0] != 'f') && (DriveString[0] != 'F') && (DriveString[0] != 'h') && (DriveString[0] != 'H')) ||
((DriveString[1] != 'd') && (DriveString[1] != 'D')))
{
return FALSE;
}
// Now verify that the user has given us appropriate numbers
// Make sure that only numeric characters were given
for (Index=2; Index<strlen(DriveString); Index++)
{
if (DriveString[Index] < '0' || DriveString[Index] > '9')
{
return FALSE;
}
}
// Now make sure that they are not outrageous values (i.e. hd90874)
if ((atoi(&DriveString[2]) < 0) || (atoi(&DriveString[2]) > 0xff))
{
return FALSE;
}
return TRUE;
}
ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName)
{
ULONG BiosDriveNumber = 0;
// Convert the drive number string into a number
// 'hd1' = 1
BiosDriveNumber = atoi(&DeviceName[2]);
// If it's a hard disk then set the high bit
if ((DeviceName[0] == 'h' || DeviceName[0] == 'H') &&
(DeviceName[1] == 'd' || DeviceName[1] == 'D'))
{
BiosDriveNumber |= 0x80;
}
return BiosDriveNumber;
}
VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap)
{
PDWORD RealModeIVT = (PULONG)0x00000000;
PWORD BiosLowMemorySize = (PWORD)0x00000413;
if (!DriveMapInstalled)
{
// Get the old INT 13h handler address from the vector table
OldInt13HandlerAddress = RealModeIVT[0x13];
// Decrease the size of low memory
(*BiosLowMemorySize)--;
// Get linear address for drive map handler
DriveMapHandlerAddress = (ULONG)(*BiosLowMemorySize) << 10;
// Convert to segment:offset style address
DriveMapHandlerSegOff = (DriveMapHandlerAddress << 12) & 0xffff0000;
}
// Copy the drive map structure to the proper place
RtlCopyMemory(&DriveMapInt13HandlerMapList, DriveMap, sizeof(DRIVE_MAP_LIST));
// Set the address of the BIOS INT 13h handler
DriveMapOldInt13HandlerAddress = OldInt13HandlerAddress;
// Copy the code to our reserved area
RtlCopyMemory((PVOID)DriveMapHandlerAddress, &DriveMapInt13HandlerStart, ((ULONG)&DriveMapInt13HandlerEnd - (ULONG)&DriveMapInt13HandlerStart));
// Update the IVT
RealModeIVT[0x13] = DriveMapHandlerSegOff;
//CacheInvalidateCacheData();
DriveMapInstalled = TRUE;
}
VOID DriveMapRemoveInt13Handler(VOID)
{
PDWORD RealModeIVT = (PULONG)0x00000000;
PWORD BiosLowMemorySize = (PWORD)0x00000413;
if (DriveMapInstalled)
{
// Get the old INT 13h handler address from the vector table
RealModeIVT[0x13] = OldInt13HandlerAddress;
// Increase the size of low memory
(*BiosLowMemorySize)++;
DriveMapInstalled = FALSE;
}
}

View file

@ -19,17 +19,9 @@
#include <freeldr.h>
#include <rtl.h>
#include <fs.h>
#include <reactos.h>
#include <ui.h>
#include <arch.h>
#include <miscboot.h>
#include <linux.h>
#include <mm.h>
#include <inifile.h>
#include <debug.h>
#include <oslist.h>
#include <video.h>
#include <bootmgr.h>
// Variable BootDrive moved to asmcode.S

View file

@ -22,6 +22,7 @@
#define __CACHE_H
BOOL CacheInitializeDrive(ULONG DriveNumber);
VOID CacheInvalidateCacheData(VOID);
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer);
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount);
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease);

View file

@ -0,0 +1,43 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 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 __DRIVEMAP_H
#define __DRIVEMAP_H
typedef struct
{
BYTE DriveMapCount; // Count of drives currently mapped
BYTE DriveMap[8]; // Map of BIOS drives
} PACKED DRIVE_MAP_LIST, *PDRIVE_MAP_LIST;
VOID DriveMapMapDrivesInSection(PUCHAR SectionName);
BOOL DriveMapIsValidDriveString(PUCHAR DriveString); // Checks the drive string ("hd0") for validity
ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName); // Returns a BIOS drive number for any given device name (e.g. 0x80 for 'hd0')
VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap); // Installs the int 13h handler for the drive mapper
VOID DriveMapRemoveInt13Handler(VOID); // Removes a previously installed int 13h drive map handler
extern PVOID DriveMapInt13HandlerStart;
extern PVOID DriveMapInt13HandlerEnd;
extern ULONG DriveMapOldInt13HandlerAddress;
extern DRIVE_MAP_LIST DriveMapInt13HandlerMapList;
#endif // #defined __DRIVEMAP_H

View file

@ -22,7 +22,7 @@
/* just some stuff */
#define VERSION "FreeLoader v1.5"
#define VERSION "FreeLoader v1.6"
#define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>"
#define AUTHOR_EMAIL "<brianp@sginet.com>"
#define BY_AUTHOR "by Brian Palmer"
@ -35,7 +35,7 @@
// If you add major functionality then you increment the major version and zero the minor & patch versions
//
#define FREELOADER_MAJOR_VERSION 1
#define FREELOADER_MINOR_VERSION 5
#define FREELOADER_MINOR_VERSION 6
#define FREELOADER_PATCH_VERSION 0

View file

@ -112,7 +112,7 @@ BOOL MmInitializeMemoryManager(VOID)
if (PageLookupTableAddress == 0)
{
// If we get here then we probably couldn't
// find a contigous chunk of memory big
// find a contiguous chunk of memory big
// enough to hold the page lookup table
printf("Error initializing memory manager!\n");
return FALSE;

View file

@ -32,90 +32,110 @@ void print(char *str)
/*
* printf() - prints formatted text to stdout
* from:
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1996 Erich Boleyn <erich@uruk.org>
* originally from GRUB
*/
void printf(char *format, ... )
{
int *dataptr = (int *) &format;
char c, *ptr, str[16];
int *dataptr = (int *) &format;
char c, *ptr, str[16];
dataptr++;
dataptr++;
while ((c = *(format++)))
{
if (c != '%')
putchar(c);
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
while ((c = *(format++)))
{
if (c != '%')
{
putchar(c);
}
else
{
c = *(format++);
if (c == 'l')
{
c = *(format++);
}
ptr = str;
switch (c)
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
while (*ptr)
putchar(*(ptr++));
break;
ptr = str;
case 'c': putchar((*(dataptr++))&0xff); break;
while (*ptr)
{
putchar(*(ptr++));
}
break;
case 's':
ptr = (char *)(*(dataptr++));
case 'c': putchar((*(dataptr++))&0xff); break;
while ((c = *(ptr++)))
putchar(c);
break;
}
}
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
{
putchar(c);
}
break;
}
}
}
}
void sprintf(char *buffer, char *format, ... )
{
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char *p = buffer;
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char *p = buffer;
dataptr++;
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;
while ((c = *(format++)))
{
if (c != '%')
{
*p = c;
p++;
}
else
{
c = *(format++);
if (c == 'l')
{
c = *(format++);
}
ptr = str;
switch (c)
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
while (*ptr)
{
*p = *(ptr++);
p++;
}
break;
ptr = str;
case 'c':
*p = (*(dataptr++))&0xff;
p++;
break;
while (*ptr)
{
*p = *(ptr++);
p++;
}
break;
case 's':
ptr = (char *)(*(dataptr++));
case 'c':
*p = (*(dataptr++))&0xff;
p++;
break;
while ((c = *(ptr++)))
{
*p = c;
p++;
}
break;
}
}
*p=0;
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
{
*p = c;
p++;
}
break;
}
}
}
*p=0;
}