Added disk cache

Optimized disk reads so it reads a track at a time or 64k if LBA

svn path=/trunk/; revision=2523
This commit is contained in:
Brian Palmer 2002-01-18 05:59:58 +00:00
parent ff0495900e
commit ec2583c6d5
28 changed files with 1523 additions and 371 deletions

View file

@ -16,17 +16,8 @@
# 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 MAKE = make
#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
include rules.mk
# 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 rtl.o fs.a fs.o fat.o \
@ -34,8 +25,8 @@ FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
# mem.o memory.o debug.o parseini.o registry.o import.o
ASM_OBJS = asmcode.o mb.o boot.o mem.o
OBJS = freeldr.o miscboot.o options.o linux.o multiboot.o debug.o parseini.o oslist.o
LIBS = rtl fs ui reactos comm disk mm
LIB_FILES = rtl/rtl.a fs/fs.a ui/ui.a reactos/reactos.a comm/comm.a disk/disk.a mm/mm.a
LIBS = rtl fs ui reactos comm disk mm cache
LIB_FILES = rtl/rtl.a fs/fs.a ui/ui.a reactos/reactos.a comm/comm.a disk/disk.a mm/mm.a cache/cache.a
.PHONY : clean
@ -114,6 +105,9 @@ disk:
mm:
$(MAKE) -C mm
cache:
$(MAKE) -C cache
.PHONY : $(LIBS)
clean:
@ -127,3 +121,4 @@ clean:
$(MAKE) -C ui clean
$(MAKE) -C fs clean
$(MAKE) -C rtl clean
$(MAKE) -C cache clean

29
freeldr/freeldr/cache.h Normal file
View file

@ -0,0 +1,29 @@
/*
* 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 __CACHE_H
#define __CACHE_H
BOOL CacheInitializeDrive(ULONG DriveNumber);
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer);
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount);
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease);
#endif // defined __CACHE_H

View file

@ -17,128 +17,23 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
include ../rules.mk
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
#FLAGS = -Wall -nostdinc -fno-builtin
FLAGS = -Wall -fno-builtin -DDEBUG -O3
#FLAGS = -Wall -fno-builtin
# 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 fat.o \
# reactos.o tui.o menu.o miscboot.o options.o linux.o multiboot.o arcname.o \
# mem.o memory.o debug.o parseini.o registry.o import.o
ASM_OBJS = asmcode.o mb.o boot.o mem.o
C_OBJS = freeldr.o stdlib.o fs.a tui.o menu.o miscboot.o options.o linux.o multiboot.o \
reactos/reactos.o reactos/registry.o reactos/reghive.o reactos/hwdetect.o
C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o oslist.o
OBJS = cache.o blocklist.o
.PHONY : clean
all: freeldr.sys
all: cache.a
freeldr.sys: asmcode.a c_code.a
$(LD) -N -Ttext=0x8000 --oformat=binary -s -o f.sys asmcode.a c_code.a
../bootsect/stubit ../bootsect/fatstub.bin f.sys freeldr.sys
cache.a: $(OBJS)
$(LD) -r -o cache.a $(OBJS)
freeldr.exe: asmcode.a c_code.a
$(LD) -o freeldr.exe asmcode.a c_code.a
cache.o: cache.c cm.h
$(CC) $(FLAGS) -o cache.o -c cache.c
asmcode.a: $(ASM_OBJS)
$(LD) -r -o asmcode.a $(ASM_OBJS)
c_code.a: c_code1.a c_code2.a
$(LD) -r -o c_code.a c_code1.a c_code2.a
c_code1.a: $(C_OBJS)
$(LD) -r -o c_code1.a $(C_OBJS)
c_code2.a: $(C_OBJS2)
$(LD) -r -o c_code2.a $(C_OBJS2)
asmcode.o: asmcode.S asmcode.h Makefile
$(CC) $(FLAGS) -o asmcode.o -c asmcode.S
freeldr.o: freeldr.c freeldr.h stdlib.h fs.h reactos/reactos.h tui.h asmcode.h menu.h miscboot.h Makefile
$(CC) $(FLAGS) -o freeldr.o -c freeldr.c
stdlib.o: stdlib.c freeldr.h stdlib.h Makefile
$(CC) $(FLAGS) -o stdlib.o -c stdlib.c
fs.a: fs.o fat.o Makefile
$(LD) -r -o fs.a fs.o fat.o
fs.o: fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile
$(CC) $(FLAGS) -o fs.o -c fs.c
fat.o: fat.c fat.h freeldr.h fs.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o fat.o -c fat.c
reactos/reactos.o: reactos/reactos.c freeldr.h reactos/reactos.h reactos/registry.h reactos/hwdetect.h stdlib.h fs.h tui.h multiboot.h Makefile
$(CC) $(FLAGS) -o reactos/reactos.o -c reactos/reactos.c
multiboot.o: multiboot.c freeldr.h stdlib.h fs.h multiboot.h tui.h Makefile
$(CC) $(FLAGS) -o multiboot.o -c multiboot.c
mb.o: mb.S asmcode.h multiboot.h Makefile
$(CC) $(FLAGS) -o mb.o -c mb.S
tui.o: tui.c freeldr.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o tui.o -c tui.c
menu.o: menu.c freeldr.h stdlib.h tui.h menu.h Makefile
$(CC) $(FLAGS) -o menu.o -c menu.c
boot.o: boot.S asmcode.h Makefile
$(CC) $(FLAGS) -o boot.o -c boot.S
miscboot.o: miscboot.c freeldr.h asmcode.h stdlib.h fs.h tui.h miscboot.h Makefile
$(CC) $(FLAGS) -o miscboot.o -c miscboot.c
options.o: options.c freeldr.h stdlib.h tui.h options.h Makefile
$(CC) $(FLAGS) -o options.o -c options.c
linux.o: linux.c freeldr.h stdlib.h tui.h linux.h Makefile
$(CC) $(FLAGS) -o linux.o -c linux.c
arcname.o: arcname.c freeldr.h arcname.h stdlib.h Makefile
$(CC) $(FLAGS) -o arcname.o -c arcname.c
mem.o: mem.S asmcode.h Makefile
$(CC) $(FLAGS) -o mem.o -c mem.S
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
rs232.o: rs232.c rs232.h Makefile
$(CC) $(FLAGS) -o rs232.o -c rs232.c
portio.o: portio.c portio.h Makefile
$(CC) $(FLAGS) -o portio.o -c portio.c
oslist.o: oslist.c oslist.h Makefile
$(CC) $(FLAGS) -o oslist.o -c oslist.c
reactos/registry.o: reactos/registry.c freeldr.h memory.h reactos/registry.h stdlib.h Makefile
$(CC) $(FLAGS) -o reactos/registry.o -c reactos/registry.c
reactos/reghive.o: reactos/reghive.c freeldr.h reactos/registry.h stdlib.h memory.h Makefile
$(CC) $(FLAGS) -o reactos/reghive.o -c reactos/reghive.c
reactos/hwdetect.o: reactos/hwdetect.c freeldr.h reactos/hwdetect.h Makefile
$(CC) $(FLAGS) -o reactos/hwdetect.o -c reactos/hwdetect.c
blocklist.o: blocklist.c cm.h
$(CC) $(FLAGS) -o blocklist.o -c blocklist.c
clean:
$(RM) *.o
$(RM) *.a
$(RM) *.sys
- $(RM) *.o
- $(RM) *.a

263
freeldr/freeldr/cache/blocklist.c vendored Normal file
View file

@ -0,0 +1,263 @@
/*
* 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 "cm.h"
#include <mm.h>
#include <disk.h>
#include <rtl.h>
#include <debug.h>
#include <asmcode.h>
// Returns a pointer to a CACHE_BLOCK structure
// Adds the block to the cache manager block list
// in cache memory if it isn't already there
PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
{
PCACHE_BLOCK CacheBlock = NULL;
DbgPrint((DPRINT_CACHE, "CacheInternalGetBlockPointer() BlockNumber = %d\n", BlockNumber));
CacheBlock = CacheInternalFindBlock(CacheDrive, BlockNumber);
if (CacheBlock != NULL)
{
DbgPrint((DPRINT_CACHE, "Cache hit! BlockNumber: %d CacheBlock->BlockNumber: %d\n", BlockNumber, CacheBlock->BlockNumber));
return CacheBlock;
}
DbgPrint((DPRINT_CACHE, "Cache miss! BlockNumber: %d\n", BlockNumber));
CacheBlock = CacheInternalAddBlockToCache(CacheDrive, BlockNumber);
// Optimize the block list so it has a LRU structure
CacheInternalOptimizeBlockList(CacheDrive, CacheBlock);
return CacheBlock;
}
PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
{
PCACHE_BLOCK CacheBlock = NULL;
DbgPrint((DPRINT_CACHE, "CacheInternalFindBlock() BlockNumber = %d\n", BlockNumber));
//
// Make sure the block list has entries before I start searching it.
//
if (!RtlListIsEmpty((PLIST_ITEM)CacheDrive->CacheBlockHead))
{
//
// Search the list and find the BIOS drive number
//
CacheBlock = CacheDrive->CacheBlockHead;
while (CacheBlock != NULL)
{
//
// We found the block, so return it
//
if (CacheBlock->BlockNumber == BlockNumber)
{
//
// Increment the blocks access count
//
CacheBlock->AccessCount++;
return CacheBlock;
}
CacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlock);
}
}
return NULL;
}
PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
{
PCACHE_BLOCK CacheBlock = NULL;
DbgPrint((DPRINT_CACHE, "CacheInternalAddBlockToCache() BlockNumber = %d\n", BlockNumber));
// Check the size of the cache so we don't exceed our limits
CacheInternalCheckCacheSizeLimits(CacheDrive);
// We will need to add the block to the
// drive's list of cached blocks. So allocate
// the block memory.
CacheBlock = AllocateMemory(sizeof(CACHE_BLOCK));
if (CacheBlock == NULL)
{
return NULL;
}
// Now initialize the structure and
// allocate room for the block data
RtlZeroMemory(CacheBlock, sizeof(CACHE_BLOCK));
CacheBlock->BlockNumber = BlockNumber;
CacheBlock->BlockData = AllocateMemory(CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
if (CacheBlock->BlockData ==NULL)
{
FreeMemory(CacheBlock);
return NULL;
}
// Now try to read in the block
if (!DiskReadMultipleLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
{
FreeMemory(CacheBlock->BlockData);
FreeMemory(CacheBlock);
return NULL;
}
RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
// Add it to our list of blocks managed by the cache
if (CacheDrive->CacheBlockHead == NULL)
{
CacheDrive->CacheBlockHead = CacheBlock;
}
else
{
RtlListInsertTail((PLIST_ITEM)CacheDrive->CacheBlockHead, (PLIST_ITEM)CacheBlock);
}
// Update the cache data
CacheBlockCount++;
CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
CacheInternalDumpBlockList(CacheDrive);
return CacheBlock;
}
BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
{
PCACHE_BLOCK CacheBlockToFree;
DbgPrint((DPRINT_CACHE, "CacheInternalFreeBlock()\n"));
// Get a pointer to the last item in the block list
// that isn't forced to be in the cache and remove
// it from the list
CacheBlockToFree = (PCACHE_BLOCK)RtlListGetTail((PLIST_ITEM)CacheDrive->CacheBlockHead);
while (CacheBlockToFree != NULL && CacheBlockToFree->LockedInCache == TRUE)
{
CacheBlockToFree = (PCACHE_BLOCK)RtlListGetPrevious((PLIST_ITEM)CacheBlockToFree);
}
// No blocks left in cache that can be freed
// so just return
if (CacheBlockToFree == NULL)
{
return FALSE;
}
//
// If we are freeing the head of the list then update it's pointer
//
if (CacheBlockToFree == CacheDrive->CacheBlockHead)
{
CacheDrive->CacheBlockHead = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlockToFree);
}
RtlListRemoveEntry((PLIST_ITEM)CacheBlockToFree);
// Free the block memory and the block structure
FreeMemory(CacheBlockToFree->BlockData);
FreeMemory(CacheBlockToFree);
// Update the cache data
CacheBlockCount--;
CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
return TRUE;
}
VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive)
{
ULONG NewCacheSize;
DbgPrint((DPRINT_CACHE, "CacheInternalCheckCacheSizeLimits()\n"));
// Calculate the size of the cache if we added a block
NewCacheSize = (CacheBlockCount + 1) * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
// Check the new size against the cache size limit
if (NewCacheSize > CacheSizeLimit)
{
CacheInternalFreeBlock(CacheDrive);
CacheInternalDumpBlockList(CacheDrive);
}
}
VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive)
{
PCACHE_BLOCK CacheBlock;
DbgPrint((DPRINT_CACHE, "Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber));
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheDrive->LbaSupported ? "TRUE" : "FALSE"));
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheDrive->DriveGeometry.Cylinders));
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheDrive->DriveGeometry.Heads));
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheDrive->DriveGeometry.Sectors));
DbgPrint((DPRINT_CACHE, "BytesPerSector: %d.\n", CacheDrive->DriveGeometry.BytesPerSector));
DbgPrint((DPRINT_CACHE, "BlockSize: %d.\n", CacheDrive->BlockSize));
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d.\n", CacheSizeLimit));
DbgPrint((DPRINT_CACHE, "CacheSizeCurrent: %d.\n", CacheSizeCurrent));
DbgPrint((DPRINT_CACHE, "CacheBlockCount: %d.\n", CacheBlockCount));
DbgPrint((DPRINT_CACHE, "Dumping %d cache blocks.\n", RtlListCountEntries((PLIST_ITEM)CacheDrive->CacheBlockHead)));
CacheBlock = CacheDrive->CacheBlockHead;
while (CacheBlock != NULL)
{
DbgPrint((DPRINT_CACHE, "Cache Block: CacheBlock: 0x%x\n", CacheBlock));
DbgPrint((DPRINT_CACHE, "Cache Block: Block Number: %d\n", CacheBlock->BlockNumber));
DbgPrint((DPRINT_CACHE, "Cache Block: Access Count: %d\n", CacheBlock->AccessCount));
DbgPrint((DPRINT_CACHE, "Cache Block: Block Data: 0x%x\n", CacheBlock->BlockData));
DbgPrint((DPRINT_CACHE, "Cache Block: Locked In Cache: %d\n", CacheBlock->LockedInCache));
if (CacheBlock->BlockData == NULL)
{
BugCheck((DPRINT_CACHE, "What the heck?!?\n"));
}
CacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlock);
}
}
VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock)
{
DbgPrint((DPRINT_CACHE, "CacheInternalOptimizeBlockList()\n"));
// Don't do this if this block is already at the head of the list
if (CacheBlock != CacheDrive->CacheBlockHead)
{
// Remove this item from the block list
RtlListRemoveEntry((PLIST_ITEM)CacheBlock);
// Re-insert it at the head of the list
RtlListInsertHead((PLIST_ITEM)CacheDrive->CacheBlockHead, (PLIST_ITEM)CacheBlock);
// Update the head pointer
CacheDrive->CacheBlockHead = CacheBlock;
}
}

323
freeldr/freeldr/cache/cache.c vendored Normal file
View file

@ -0,0 +1,323 @@
/*
* 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 "cm.h"
#include <mm.h>
#include <disk.h>
#include <rtl.h>
#include <debug.h>
///////////////////////////////////////////////////////////////////////////////////////
//
// Internal data
//
///////////////////////////////////////////////////////////////////////////////////////
CACHE_DRIVE CacheManagerDrive;
BOOL CacheManagerInitialized = FALSE;
ULONG CacheBlockCount = 0;
ULONG CacheSizeLimit = 0;
ULONG CacheSizeCurrent = 0;
BOOL CacheInitializeDrive(ULONG DriveNumber)
{
PCACHE_BLOCK NextCacheBlock;
// If we already have a cache for this drive then
// by all means lets keep it
if (CacheManagerInitialized && DriveNumber == CacheManagerDrive.DriveNumber)
{
return TRUE;
}
//
// If we have already been initialized then free
// the old data
//
if (CacheManagerInitialized)
{
CacheManagerInitialized = FALSE;
DbgPrint((DPRINT_CACHE, "CacheBlockCount: %d\n", CacheBlockCount));
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d\n", CacheSizeLimit));
DbgPrint((DPRINT_CACHE, "CacheSizeCurrent: %d\n", CacheSizeCurrent));
//
// Loop through and free the cache blocks
//
while (CacheManagerDrive.CacheBlockHead != NULL)
{
NextCacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheManagerDrive.CacheBlockHead);
FreeMemory(CacheManagerDrive.CacheBlockHead->BlockData);
FreeMemory(CacheManagerDrive.CacheBlockHead);
CacheManagerDrive.CacheBlockHead = NextCacheBlock;
}
}
// Initialize the structure
RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
CacheManagerDrive.DriveNumber = DriveNumber;
CacheManagerDrive.LbaSupported = BiosInt13ExtensionsSupported(DriveNumber);
if (!DiskGetDriveGeometry(DriveNumber, &CacheManagerDrive.DriveGeometry))
{
return FALSE;
}
// If LBA is supported then the block size will be 128 sectors (64k)
// If not then the block size is the size of one track
if (CacheManagerDrive.LbaSupported)
{
CacheManagerDrive.BlockSize = 128;
}
else
{
CacheManagerDrive.BlockSize = CacheManagerDrive.DriveGeometry.Sectors;
}
CacheBlockCount = 0;
CacheSizeLimit = GetSystemMemorySize() / 8;
CacheSizeCurrent = 0;
if (CacheSizeLimit < (64 * 1024))
{
CacheSizeLimit = (64 * 1024);
}
CacheManagerInitialized = TRUE;
DbgPrint((DPRINT_CACHE, "Initializing BIOS drive 0x%x.\n", DriveNumber));
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheManagerDrive.LbaSupported ? "TRUE" : "FALSE"));
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheManagerDrive.DriveGeometry.Cylinders));
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheManagerDrive.DriveGeometry.Heads));
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheManagerDrive.DriveGeometry.Sectors));
DbgPrint((DPRINT_CACHE, "BytesPerSector: %d.\n", CacheManagerDrive.DriveGeometry.BytesPerSector));
DbgPrint((DPRINT_CACHE, "BlockSize: %d.\n", CacheManagerDrive.BlockSize));
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d.\n", CacheSizeLimit));
return TRUE;
}
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer)
{
PCACHE_BLOCK CacheBlock;
ULONG StartBlock;
ULONG SectorOffsetInStartBlock;
ULONG CopyLengthInStartBlock;
ULONG EndBlock;
ULONG SectorOffsetInEndBlock;
ULONG BlockCount;
ULONG Idx;
DbgPrint((DPRINT_CACHE, "CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer));
// If we aren't initialized yet then they can't do this
if (CacheManagerInitialized == FALSE)
{
return FALSE;
}
//
// Caculate which blocks we must cache
//
StartBlock = StartSector / CacheManagerDrive.BlockSize;
SectorOffsetInStartBlock = StartSector % CacheManagerDrive.BlockSize;
CopyLengthInStartBlock = (SectorCount > (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock)) ? (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock) : SectorCount;
EndBlock = (StartSector + (SectorCount - 1)) / CacheManagerDrive.BlockSize;
SectorOffsetInEndBlock = (StartSector + SectorCount) % CacheManagerDrive.BlockSize;
BlockCount = (EndBlock - StartBlock) + 1;
DbgPrint((DPRINT_CACHE, "StartBlock: %d SectorOffsetInStartBlock: %d CopyLengthInStartBlock: %d EndBlock: %d SectorOffsetInEndBlock: %d BlockCount: %d\n", StartBlock, SectorOffsetInStartBlock, CopyLengthInStartBlock, EndBlock, SectorOffsetInEndBlock, BlockCount));
//
// Read the first block into the buffer
//
if (BlockCount > 0)
{
//
// Get cache block pointer (this forces the disk sectors into the cache memory)
//
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, StartBlock);
if (CacheBlock == NULL)
{
return FALSE;
}
//
// Copy the portion requested into the buffer
//
RtlCopyMemory(Buffer,
(CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)),
(CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector));
DbgPrint((DPRINT_CACHE, "1 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, (CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)), (CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)));
//
// Update the buffer address
//
Buffer += (CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector);
//
// Update the block count
//
BlockCount--;
}
//
// Loop through the middle blocks and read them into the buffer
//
for (Idx=StartBlock+1; BlockCount>1; Idx++)
{
//
// Get cache block pointer (this forces the disk sectors into the cache memory)
//
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
if (CacheBlock == NULL)
{
return FALSE;
}
//
// Copy the portion requested into the buffer
//
RtlCopyMemory(Buffer,
CacheBlock->BlockData,
CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector);
DbgPrint((DPRINT_CACHE, "2 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector));
//
// Update the buffer address
//
Buffer += CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector;
//
// Update the block count
//
BlockCount--;
}
//
// Read the last block into the buffer
//
if (BlockCount > 0)
{
//
// Get cache block pointer (this forces the disk sectors into the cache memory)
//
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, EndBlock);
if (CacheBlock == NULL)
{
return FALSE;
}
//
// Copy the portion requested into the buffer
//
RtlCopyMemory(Buffer,
CacheBlock->BlockData,
SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector);
DbgPrint((DPRINT_CACHE, "3 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector));
//
// Update the buffer address
//
Buffer += SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector;
//
// Update the block count
//
BlockCount--;
}
return TRUE;
}
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount)
{
PCACHE_BLOCK CacheBlock;
ULONG StartBlock;
ULONG EndBlock;
ULONG BlockCount;
ULONG Idx;
DbgPrint((DPRINT_CACHE, "CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount));
// If we aren't initialized yet then they can't do this
if (CacheManagerInitialized == FALSE)
{
return FALSE;
}
//
// Caculate which blocks we must cache
//
StartBlock = StartSector / CacheManagerDrive.BlockSize;
EndBlock = (StartSector + SectorCount) / CacheManagerDrive.BlockSize;
BlockCount = (EndBlock - StartBlock) + 1;
//
// Loop through and cache them
//
for (Idx=StartBlock; Idx<(StartBlock+BlockCount); Idx++)
{
//
// Get cache block pointer (this forces the disk sectors into the cache memory)
//
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
if (CacheBlock == NULL)
{
return FALSE;
}
//
// Lock the sectors into the cache
//
CacheBlock->LockedInCache = TRUE;
}
return TRUE;
}
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease)
{
ULONG AmountReleased;
DbgPrint((DPRINT_CACHE, "CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease));
// If we aren't initialized yet then they can't do this
if (CacheManagerInitialized == FALSE)
{
return FALSE;
}
// Loop through and try to free the requested amount of memory
for (AmountReleased=0; AmountReleased<MinimumAmountToRelease; )
{
// Try to free a block
// If this fails then break out of the loop
if (!CacheInternalFreeBlock(&CacheManagerDrive))
{
break;
}
// It succeeded so increment the amount of memory we have freed
AmountReleased += CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector;
}
// Return status
return (AmountReleased >= MinimumAmountToRelease);
}

93
freeldr/freeldr/cache/cm.h vendored Normal file
View file

@ -0,0 +1,93 @@
/*
* 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 <rtl.h>
#include <disk.h>
#ifndef __CM_H
#define __CM_H
///////////////////////////////////////////////////////////////////////////////////////
//
// This structure describes a cached block element. The disk is divided up into
// cache blocks. For disks which LBA is not supported each block is the size of
// one track. This will force the cache manager to make track sized reads, and
// therefore maximizes throughput. For disks which support LBA the block size
// is 64k because they have no cylinder, head, or sector boundaries.
//
///////////////////////////////////////////////////////////////////////////////////////
typedef struct
{
LIST_ITEM ListEntry; // Doubly linked list synchronization member
ULONG BlockNumber; // Track index for CHS, 64k block index for LBA
BOOL LockedInCache; // Indicates that this block is locked in cache memory
ULONG AccessCount; // Access count for this block
PVOID BlockData; // Pointer to block data
} CACHE_BLOCK, *PCACHE_BLOCK;
///////////////////////////////////////////////////////////////////////////////////////
//
// This structure describes a cached drive. It contains the BIOS drive number
// and indicates whether or not LBA is supported. If LBA is not supported then
// the drive's geometry is described here.
//
///////////////////////////////////////////////////////////////////////////////////////
typedef struct
{
ULONG DriveNumber;
BOOL LbaSupported;
GEOMETRY DriveGeometry;
ULONG BlockSize; // Block size (in sectors)
PCACHE_BLOCK CacheBlockHead;
} CACHE_DRIVE, *PCACHE_DRIVE;
///////////////////////////////////////////////////////////////////////////////////////
//
// Internal data
//
///////////////////////////////////////////////////////////////////////////////////////
extern CACHE_DRIVE CacheManagerDrive;
extern BOOL CacheManagerInitialized;
extern ULONG CacheBlockCount;
extern ULONG CacheSizeLimit;
extern ULONG CacheSizeCurrent;
///////////////////////////////////////////////////////////////////////////////////////
//
// Internal functions
//
///////////////////////////////////////////////////////////////////////////////////////
PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Returns a pointer to a CACHE_BLOCK structure given a block number
PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Searches the block list for a particular block
PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Adds a block to the cache's block list
BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive); // Removes a block from the cache's block list & frees the memory
VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive); // Checks the cache size limits to see if we can add a new block, if not calls CacheInternalFreeBlock()
VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive); // Dumps the list of cached blocks to the debug output port
VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock); // Moves the specified block to the head of the list
#endif // defined __CM_H

View file

@ -17,14 +17,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
include ../rules.mk
OBJS = rs232.o portio.o

View file

@ -24,7 +24,9 @@
#ifdef DEBUG
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | DPRINT_UI | DPRINT_DISK;
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
DPRINT_UI | DPRINT_DISK | DPRINT_CACHE;
//ULONG DebugPrintMask = DPRINT_CACHE;
#define SCREEN 0
#define RS232 1
@ -43,6 +45,8 @@ ULONG DebugPort = BOCHS;
ULONG ComPort = COM1;
ULONG BaudRate = 19200;
BOOL DebugStartOfLine = TRUE;
VOID DebugInit(VOID)
{
if (DebugPort == RS232)
@ -53,6 +57,11 @@ VOID DebugInit(VOID)
VOID DebugPrintChar(UCHAR Character)
{
if (Character == '\n')
{
DebugStartOfLine = TRUE;
}
if (DebugPort == RS232)
{
Rs232PortPutByte(Character);
@ -71,6 +80,90 @@ VOID DebugPrintChar(UCHAR Character)
}
}
VOID DebugPrintHeader(ULONG Mask)
{
switch (Mask)
{
case DPRINT_WARNING:
DebugPrintChar('W');
DebugPrintChar('A');
DebugPrintChar('R');
DebugPrintChar('N');
DebugPrintChar('I');
DebugPrintChar('N');
DebugPrintChar('G');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_MEMORY:
DebugPrintChar('M');
DebugPrintChar('E');
DebugPrintChar('M');
DebugPrintChar('O');
DebugPrintChar('R');
DebugPrintChar('Y');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_FILESYSTEM:
DebugPrintChar('F');
DebugPrintChar('I');
DebugPrintChar('L');
DebugPrintChar('E');
DebugPrintChar('S');
DebugPrintChar('Y');
DebugPrintChar('S');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_INIFILE:
DebugPrintChar('I');
DebugPrintChar('N');
DebugPrintChar('I');
DebugPrintChar('F');
DebugPrintChar('I');
DebugPrintChar('L');
DebugPrintChar('E');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_UI:
DebugPrintChar('U');
DebugPrintChar('I');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_DISK:
DebugPrintChar('D');
DebugPrintChar('I');
DebugPrintChar('S');
DebugPrintChar('K');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
case DPRINT_CACHE:
DebugPrintChar('C');
DebugPrintChar('A');
DebugPrintChar('C');
DebugPrintChar('H');
DebugPrintChar('E');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
default:
DebugPrintChar('U');
DebugPrintChar('N');
DebugPrintChar('K');
DebugPrintChar('N');
DebugPrintChar('O');
DebugPrintChar('W');
DebugPrintChar('N');
DebugPrintChar(':');
DebugPrintChar(' ');
break;
}
}
VOID DebugPrint(ULONG Mask, char *format, ...)
{
int *dataptr = (int *) &format;
@ -82,6 +175,13 @@ VOID DebugPrint(ULONG Mask, char *format, ...)
return;
}
// Print the header if we have started a new line
if (DebugStartOfLine)
{
DebugPrintHeader(Mask);
DebugStartOfLine = FALSE;
}
dataptr++;
while ((c = *(format++)))

View file

@ -29,6 +29,7 @@
#define DPRINT_INIFILE 0x00000008 // OR this with DebugPrintMask to enable .ini file 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_CACHE 0x00000040 // OR this with DebugPrintMask to enable cache messages
VOID DebugInit(VOID);
VOID DebugPrint(ULONG Mask, char *format, ...);

View file

@ -51,9 +51,10 @@ int get_sectors(int drive); // Implemented in asmcode.S
// FreeLoader Disk Functions
//
///////////////////////////////////////////////////////////////////////////////////////
VOID DiskSetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector);
VOID DiskSetVolumeProperties(ULONG HiddenSectors);
BOOL DiskReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOL DiskReadLogicalSector(ULONG SectorNumber, PVOID Buffer);
VOID DiskError(PUCHAR ErrorString);
BOOL DiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry);
BOOL DiskSetDriveGeometry(ULONG DriveNumber, ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector);
BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer);
#endif // defined __DISK_H

View file

@ -17,16 +17,9 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
include ../rules.mk
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
OBJS = disk.o
OBJS = disk.o geometry.o
.PHONY : clean
@ -38,6 +31,9 @@ disk.a: $(OBJS)
disk.o: disk.c ../disk.h
$(CC) $(FLAGS) -o disk.o -c disk.c
geometry.o: geometry.c ../disk.h
$(CC) $(FLAGS) -o geometry.o -c geometry.c
clean:
- $(RM) *.o
- $(RM) *.a

View file

@ -26,14 +26,6 @@
#include <debug.h>
/////////////////////////////////////////////////////////////////////////////////////////////
// DATA
/////////////////////////////////////////////////////////////////////////////////////////////
GEOMETRY DriveGeometry;
ULONG VolumeHiddenSectors;
ULONG CurrentlyOpenDriveNumber;
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
@ -54,122 +46,30 @@ VOID DiskError(PUCHAR ErrorString)
}
}
VOID DiskSetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
DriveGeometry.Cylinders = Cylinders;
DriveGeometry.Heads = Heads;
DriveGeometry.Sectors = Sectors;
DriveGeometry.BytesPerSector = BytesPerSector;
ULONG PhysicalSector;
ULONG PhysicalHead;
ULONG PhysicalTrack;
GEOMETRY DriveGeometry;
ULONG NumberOfSectorsToRead;
DbgPrint((DPRINT_DISK, "DriveGeometry.Cylinders: %d\n", DriveGeometry.Cylinders));
DbgPrint((DPRINT_DISK, "DriveGeometry.Heads: %d\n", DriveGeometry.Heads));
DbgPrint((DPRINT_DISK, "DriveGeometry.Sectors: %d\n", DriveGeometry.Sectors));
DbgPrint((DPRINT_DISK, "DriveGeometry.BytesPerSector: %d\n", DriveGeometry.BytesPerSector));
}
VOID DiskSetVolumeProperties(ULONG HiddenSectors)
{
VolumeHiddenSectors = HiddenSectors;
}
BOOL DiskReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
/*BOOL bRetVal;
int PhysicalSector;
int PhysicalHead;
int PhysicalTrack;
int nNum;
nSect += nHiddenSectors;
while (nNumberOfSectors)
{
PhysicalSector = 1 + (nSect % nSectorsPerTrack);
PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
if (PhysicalSector > 1)
{
if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1)))
nNum = (nSectorsPerTrack - (PhysicalSector - 1));
else
nNum = nNumberOfSectors;
}
else
{
if (nNumberOfSectors >= nSectorsPerTrack)
nNum = nSectorsPerTrack;
else
nNum = nNumberOfSectors;
}
bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
if (!bRetVal)
{
FS_DO_ERROR("Disk Error");
return FALSE;
}
pBuffer += (nNum * 512);
nNumberOfSectors -= nNum;
nSect += nNum;
}*/
ULONG CurrentSector;
PVOID RealBuffer = Buffer;
for (CurrentSector=SectorNumber; CurrentSector<(SectorNumber + SectorCount); CurrentSector++)
{
if (!DiskReadLogicalSector(CurrentSector, RealBuffer) )
{
return FALSE;
}
RealBuffer += DriveGeometry.BytesPerSector;
}
return TRUE;
}
BOOL DiskReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
{
ULONG PhysicalSector;
ULONG PhysicalHead;
ULONG PhysicalTrack;
DbgPrint((DPRINT_DISK, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber, Buffer));
SectorNumber += VolumeHiddenSectors;
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
if (PhysicalHead >= DriveGeometry.Heads)
{
BugCheck((DPRINT_DISK, "PhysicalHead >= DriveGeometry.Heads\nPhysicalHead = %d\nDriveGeometry.Heads = %d\n", PhysicalHead, DriveGeometry.Heads));
}
if (PhysicalTrack >= DriveGeometry.Cylinders)
{
BugCheck((DPRINT_DISK, "PhysicalTrack >= DriveGeometry.Cylinders\nPhysicalTrack = %d\nDriveGeometry.Cylinders = %d\n", PhysicalTrack, DriveGeometry.Cylinders));
}
if (PhysicalSector > DriveGeometry.Sectors)
{
BugCheck((DPRINT_DISK, "PhysicalSector > DriveGeometry.Sectors\nPhysicalSector = %d\nDriveGeometry.Sectors = %d\n", PhysicalSector, DriveGeometry.Sectors));
}
DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
//
// Check to see if it is a fixed disk drive
// If so then check to see if Int13 extensions work
// If they do then use them, otherwise default back to BIOS calls
//
if ((CurrentlyOpenDriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber)) && (SectorNumber > (DriveGeometry.Cylinders * DriveGeometry.Heads * DriveGeometry.Sectors)))
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
{
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", CurrentlyOpenDriveNumber, BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber) ? "TRUE" : "FALSE"));
if ( !BiosInt13ReadExtended(CurrentlyOpenDriveNumber, SectorNumber, 1, Buffer) )
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
//
// LBA is easy, nothing to calculate
// Just do the read
//
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
{
DiskError("Disk read error.");
return FALSE;
@ -177,7 +77,141 @@ BOOL DiskReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
}
else
{
if ( !BiosInt13Read(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer) )
//
// Get the drive geometry
//
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
{
return FALSE;
}
while (SectorCount)
{
//
// Calculate the physical disk offsets
//
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
//
// Calculate how many sectors we are supposed to read
//
if (PhysicalSector > 1)
{
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
else
NumberOfSectorsToRead = SectorCount;
}
else
{
if (SectorCount >= DriveGeometry.Sectors)
NumberOfSectorsToRead = DriveGeometry.Sectors;
else
NumberOfSectorsToRead = SectorCount;
}
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead));
//
// Make sure the read is within the geometry boundaries
//
if ((PhysicalHead >= DriveGeometry.Heads) ||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
(PhysicalSector > DriveGeometry.Sectors))
{
DiskError("Disk read exceeds drive geometry limits.");
return FALSE;
}
//
// Perform the read
//
if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer))
{
DiskError("Disk read error.");
return FALSE;
}
Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
SectorCount -= NumberOfSectorsToRead;
SectorNumber += NumberOfSectorsToRead;
}
}
return TRUE;
}
BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer)
{
ULONG PhysicalSector;
ULONG PhysicalHead;
ULONG PhysicalTrack;
GEOMETRY DriveGeometry;
DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
//
// Check to see if it is a fixed disk drive
// If so then check to see if Int13 extensions work
// If they do then use them, otherwise default back to BIOS calls
//
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
{
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
//
// LBA is easy, nothing to calculate
// Just do the read
//
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
{
DiskError("Disk read error.");
return FALSE;
}
}
else
{
//
// Get the drive geometry
//
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
{
return FALSE;
}
//
// Calculate the physical disk offsets
//
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
//
// Make sure the read is within the geometry boundaries
//
if ((PhysicalHead >= DriveGeometry.Heads) ||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
(PhysicalSector > DriveGeometry.Sectors))
{
DiskError("Disk read exceeds drive geometry limits.");
return FALSE;
}
//
// Perform the read
//
if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer))
{
DiskError("Disk read error.");
return FALSE;

View file

@ -0,0 +1,126 @@
/*
* 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.
*/
#include <freeldr.h>
#include <disk.h>
#include <rtl.h>
#include <mm.h>
typedef struct
{
LIST_ITEM ListEntry;
ULONG DriveNumber;
GEOMETRY DriveGeometry;
} DRIVE_GEOMETRY, *PDRIVE_GEOMETRY;
PDRIVE_GEOMETRY DriveGeometryListHead = NULL;
BOOL DiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry)
{
PDRIVE_GEOMETRY DriveGeometryListEntry;
//
// Search the drive geometry list for the requested drive
//
DriveGeometryListEntry = DriveGeometryListHead;
while (DriveGeometryListEntry != NULL)
{
//
// Check to see if this is the drive we want
//
if (DriveGeometryListEntry->DriveNumber == DriveNumber)
{
//
// Yep - return the information
//
RtlCopyMemory(DriveGeometry, &DriveGeometryListEntry->DriveGeometry, sizeof(GEOMETRY));
return TRUE;
}
//
// Nope, get next item
//
DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry);
}
DiskError("Drive geometry unknown.");
return FALSE;
}
BOOL DiskSetDriveGeometry(ULONG DriveNumber, ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
{
PDRIVE_GEOMETRY DriveGeometryListEntry;
//
// Search the drive geometry list for the requested drive
//
DriveGeometryListEntry = DriveGeometryListHead;
while (DriveGeometryListEntry != NULL)
{
//
// Check to see if this is the drive
//
if (DriveGeometryListEntry->DriveNumber == DriveNumber)
{
//
// Yes, we already have this drive's geometry information
// so just return
//
return TRUE;
}
//
// Nope, get next item
//
DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry);
}
//
// If we get here then this is a new drive and we have
// to add it's information to our list
//
DriveGeometryListEntry = (PDRIVE_GEOMETRY)AllocateMemory(sizeof(DRIVE_GEOMETRY));
if (DriveGeometryListEntry == NULL)
{
return FALSE;
}
RtlZeroMemory(DriveGeometryListEntry, sizeof(DRIVE_GEOMETRY));
DriveGeometryListEntry->DriveNumber = DriveNumber;
DriveGeometryListEntry->DriveGeometry.Cylinders = Cylinders;
DriveGeometryListEntry->DriveGeometry.Heads = Heads;
DriveGeometryListEntry->DriveGeometry.Sectors = Sectors;
DriveGeometryListEntry->DriveGeometry.BytesPerSector = BytesPerSector;
if (DriveGeometryListHead == NULL)
{
DriveGeometryListHead = DriveGeometryListEntry;
}
else
{
RtlListInsertTail((PLIST_ITEM)DriveGeometryListHead, (PLIST_ITEM)DriveGeometryListEntry);
}
return TRUE;
}

View file

@ -29,6 +29,7 @@
#include "parseini.h"
#include "debug.h"
#include "oslist.h"
#include "cache.h"
// Variable BootDrive moved to asmcode.S
//ULONG BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
@ -104,19 +105,7 @@ VOID BootMain(VOID)
//
// Find all the message box settings and run them
//
for (Idx=0; Idx<GetNumSectionItems(SectionId); Idx++)
{
ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
if (stricmp(SettingName, "MessageBox") == 0)
{
MessageBox(SettingValue);
}
else if (stricmp(SettingName, "MessageLine") == 0)
{
MessageLine(SettingValue);
}
}
ShowMessageBoxesInSection("FreeLoader");
for (;;)
{

View file

@ -17,14 +17,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
include ../rules.mk
OBJS = fs.o fat.o

View file

@ -26,6 +26,7 @@
#include <asmcode.h>
#include <mm.h>
#include <debug.h>
#include <cache.h>
PFAT_BOOTSECTOR FatVolumeBootSector = NULL;
@ -37,11 +38,13 @@ ULONG SectorsPerFat; // Sectors per FAT table
ULONG RootDirSectors; // Number of sectors of the root directory (fat32)
ULONG FatType = 0; // FAT12, FAT16, or FAT32
ULONG FatDriveNumber = 0;
BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTrack, ULONG VolumeStartSector, ULONG FatFileSystemType)
{
FatType = FatFileSystemType;
FatDriveNumber = DriveNumber;
//
// Free any memory previously allocated
@ -153,8 +156,13 @@ BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTr
return FALSE;
}
DiskSetDriveGeometry(get_cylinders(DriveNumber), get_heads(DriveNumber), get_sectors(DriveNumber), FatVolumeBootSector->BytesPerSector);
DiskSetVolumeProperties(FatVolumeBootSector->HiddenSectors);
//
// Set the drive geometry
//
if (!DiskSetDriveGeometry(DriveNumber, get_cylinders(DriveNumber), get_heads(DriveNumber), get_sectors(DriveNumber), FatVolumeBootSector->BytesPerSector))
{
return FALSE;
}
//
// Check the FAT cluster size
@ -206,6 +214,27 @@ BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTr
}
}
//
// Initialize the disk cache for this drive
//
if (!CacheInitializeDrive(DriveNumber))
{
return FALSE;
}
//
// Force the FAT sectors into the cache
// as long as it is FAT12 or FAT16. FAT32 can
// have a multi-megabyte FAT so we don't want that.
//
if (FatType != FAT32)
{
if (!CacheForceDiskSectorsIntoCache(DriveNumber, FatVolumeBootSector->HiddenSectors + FatVolumeBootSector->ReservedSectors, FatVolumeBootSector->SectorsPerFat))
{
return FALSE;
}
}
return TRUE;
}
@ -268,7 +297,7 @@ PVOID FatBufferDirectory(UINT32 DirectoryStartCluster, PUINT32 EntryCountPointer
RootDirectoryStartSector = FatVolumeBootSector->ReservedSectors + (FatVolumeBootSector->NumberOfFats * FatVolumeBootSector->SectorsPerFat);
RootDirectorySectorCount = FatVolumeBootSector->RootDirEntries / 32;
if (!DiskReadMultipleLogicalSectors(RootDirectoryStartSector, RootDirectorySectorCount, DirectoryBuffer))
if (!FatReadVolumeSectors(FatDriveNumber, RootDirectoryStartSector, RootDirectorySectorCount, DirectoryBuffer))
{
FreeMemory(DirectoryBuffer);
return NULL;
@ -449,10 +478,25 @@ BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, UINT32 EntryCount, P
FatFileInfoPointer->FileSize = DirEntry->Size;
FatFileInfoPointer->FilePointer = 0;
DbgPrint((DPRINT_FILESYSTEM, "MSDOS Directory Entry:\n"));
DbgPrint((DPRINT_FILESYSTEM, "FileName[11] = %c%c%c%c%c%c%c%c%c%c%c\n", DirEntry->FileName[0], DirEntry->FileName[1], DirEntry->FileName[2], DirEntry->FileName[3], DirEntry->FileName[4], DirEntry->FileName[5], DirEntry->FileName[6], DirEntry->FileName[7], DirEntry->FileName[8], DirEntry->FileName[9], DirEntry->FileName[10]));
DbgPrint((DPRINT_FILESYSTEM, "Attr = 0x%x\n", DirEntry->Attr));
DbgPrint((DPRINT_FILESYSTEM, "ReservedNT = 0x%x\n", DirEntry->ReservedNT));
DbgPrint((DPRINT_FILESYSTEM, "TimeInTenths = %d\n", DirEntry->TimeInTenths));
DbgPrint((DPRINT_FILESYSTEM, "CreateTime = %d\n", DirEntry->CreateTime));
DbgPrint((DPRINT_FILESYSTEM, "CreateDate = %d\n", DirEntry->CreateDate));
DbgPrint((DPRINT_FILESYSTEM, "LastAccessDate = %d\n", DirEntry->LastAccessDate));
DbgPrint((DPRINT_FILESYSTEM, "ClusterHigh = 0x%x\n", DirEntry->ClusterHigh));
DbgPrint((DPRINT_FILESYSTEM, "Time = %d\n", DirEntry->Time));
DbgPrint((DPRINT_FILESYSTEM, "Date = %d\n", DirEntry->Date));
DbgPrint((DPRINT_FILESYSTEM, "ClusterLow = 0x%x\n", DirEntry->ClusterLow));
DbgPrint((DPRINT_FILESYSTEM, "Size = %d\n", DirEntry->Size));
//
// Get the cluster chain
//
StartCluster = ((UINT32)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
DbgPrint((DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", StartCluster));
FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(StartCluster);
//
@ -676,20 +720,20 @@ void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry)
* FatGetFatEntry()
* returns the Fat entry for a given cluster number
*/
DWORD FatGetFatEntry(DWORD nCluster)
BOOL FatGetFatEntry(UINT32 Cluster, PUINT32 ClusterPointer)
{
DWORD fat = 0;
int FatOffset;
int ThisFatSecNum;
int ThisFatEntOffset;
DbgPrint((DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", nCluster));
DbgPrint((DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster));
switch(FatType)
{
case FAT12:
FatOffset = nCluster + (nCluster / 2);
FatOffset = Cluster + (Cluster / 2);
ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
@ -699,21 +743,21 @@ DWORD FatGetFatEntry(DWORD nCluster)
if (ThisFatEntOffset == (FatVolumeBootSector->BytesPerSector - 1))
{
if (!DiskReadMultipleLogicalSectors(ThisFatSecNum, 2, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 2, (PVOID)DISKREADBUFFER))
{
return NULL;
return FALSE;
}
}
else
{
if (!DiskReadLogicalSector(ThisFatSecNum, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)DISKREADBUFFER))
{
return NULL;
return FALSE;
}
}
fat = *((WORD *) (DISKREADBUFFER + ThisFatEntOffset));
if (nCluster & 0x0001)
if (Cluster & 0x0001)
fat = fat >> 4; /* Cluster number is ODD */
else
fat = fat & 0x0FFF; /* Cluster number is EVEN */
@ -722,13 +766,13 @@ DWORD FatGetFatEntry(DWORD nCluster)
case FAT16:
FatOffset = (nCluster * 2);
FatOffset = (Cluster * 2);
ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
if (!DiskReadLogicalSector(ThisFatSecNum, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)DISKREADBUFFER))
{
return NULL;
return FALSE;
}
fat = *((WORD *) (DISKREADBUFFER + ThisFatEntOffset));
@ -737,13 +781,14 @@ DWORD FatGetFatEntry(DWORD nCluster)
case FAT32:
FatOffset = (nCluster * 4);
ThisFatSecNum = FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
FatOffset = (Cluster * 4);
ThisFatSecNum = (Fat32VolumeBootSector->ExtendedFlags & 0x80) ? ((Fat32VolumeBootSector->ExtendedFlags & 0x0f) * Fat32VolumeBootSector->SectorsPerFatBig) : 0; // Get the active fat sector offset
ThisFatSecNum += FatVolumeBootSector->ReservedSectors + (FatOffset / FatVolumeBootSector->BytesPerSector);
ThisFatEntOffset = (FatOffset % FatVolumeBootSector->BytesPerSector);
if (!DiskReadLogicalSector(ThisFatSecNum, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)DISKREADBUFFER))
{
return NULL;
return FALSE;
}
// Get the fat entry
@ -755,7 +800,9 @@ DWORD FatGetFatEntry(DWORD nCluster)
DbgPrint((DPRINT_FILESYSTEM, "FAT entry is 0x%x.\n", fat));
return fat;
*ClusterPointer = fat;
return TRUE;
}
/*
@ -813,7 +860,10 @@ UINT32 FatCountClustersInChain(UINT32 StartCluster)
//
// Get next cluster
//
StartCluster = FatGetFatEntry(StartCluster);
if (!FatGetFatEntry(StartCluster, &StartCluster))
{
return 0;
}
}
DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() ClusterCount = %d\n", ClusterCount));
@ -867,7 +917,11 @@ PUINT32 FatGetClusterChainArray(UINT32 StartCluster)
//
// Get next cluster
//
StartCluster = FatGetFatEntry(StartCluster);
if (!FatGetFatEntry(StartCluster, &StartCluster))
{
FreeMemory(ArrayPointer);
return NULL;
}
}
return ArrayPointer;
@ -886,7 +940,7 @@ BOOL FatReadCluster(ULONG ClusterNumber, PVOID Buffer)
DbgPrint((DPRINT_FILESYSTEM, "FatReadCluster() ClusterNumber = %d Buffer = 0x%x ClusterStartSector = %d\n", ClusterNumber, Buffer, ClusterStartSector));
if (!DiskReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
{
return FALSE;
}
@ -909,7 +963,7 @@ BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID
while (NumberOfClusters > 0)
{
DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
//
// Calculate starting sector for cluster
//
@ -918,7 +972,7 @@ BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID
//
// Read cluster into memory
//
if (!DiskReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
{
return FALSE;
}
@ -938,7 +992,10 @@ BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID
//
// Get next cluster
//
StartClusterNumber = FatGetFatEntry(StartClusterNumber);
if (!FatGetFatEntry(StartClusterNumber, &StartClusterNumber))
{
return FALSE;
}
//
// If end of chain then break out of our cluster reading loop
@ -966,7 +1023,7 @@ BOOL FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Leng
ClusterStartSector = ((ClusterNumber - 2) * FatVolumeBootSector->SectorsPerCluster) + DataSectorStart;
if (!DiskReadMultipleLogicalSectors(ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, FatVolumeBootSector->SectorsPerCluster, (PVOID)DISKREADBUFFER))
{
return FALSE;
}
@ -1162,3 +1219,8 @@ ULONG FatGetFilePointer(FILE *FileHandle)
return FatFileHandle->FilePointer;
}
BOOL FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
//return DiskReadMultipleLogicalSectors(DriveNumber, SectorNumber + FatVolumeBootSector->HiddenSectors, SectorCount, Buffer);
return CacheReadDiskSectors(DriveNumber, SectorNumber + FatVolumeBootSector->HiddenSectors, SectorCount, Buffer);
}

View file

@ -121,6 +121,7 @@ typedef struct
ULONG FileSize; // File size
ULONG FilePointer; // File pointer
PUINT32 FileFatChain; // File fat chain array
ULONG DriveNumber;
} FAT_FILE_INFO, * PFAT_FILE_INFO;
@ -132,7 +133,7 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
ULONG FatGetNumPathParts(PUCHAR Path);
VOID FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path);
void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry);
DWORD FatGetFatEntry(DWORD nCluster);
BOOL FatGetFatEntry(UINT32 Cluster, PUINT32 ClusterPointer);
FILE* FatOpenFile(PUCHAR FileName);
UINT32 FatCountClustersInChain(UINT32 StartCluster);
PUINT32 FatGetClusterChainArray(UINT32 StartCluster);
@ -143,22 +144,7 @@ BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Bu
ULONG FatGetFileSize(FILE *FileHandle);
VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
ULONG FatGetFilePointer(FILE *FileHandle);
/*BOOL FatLookupFile(char *file, PFAT_STRUCT pFatStruct);
int FatGetNumPathParts(char *name);
BOOL FatGetFirstNameFromPath(char *buffer, char *name);
void FatParseFileName(char *buffer, char *name);
DWORD FatGetFatEntry(DWORD nCluster);
int FatReadCluster(DWORD nCluster, char *cBuffer);
int FatRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer);
int Fatfseek(PFAT_STRUCT pFatStruct, DWORD offset);
FILE* FatOpenFile(PUCHAR FileName);
BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
ULONG FatGetFileSize(FILE *FileHandle);
VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
ULONG FatGetFilePointer(FILE *FileHandle);*/
BOOL FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
#define EOF -1

View file

@ -28,6 +28,7 @@ VOID InitMemoryManager(PVOID BaseAddress, ULONG Length);
PVOID AllocateMemory(ULONG NumberOfBytes);
VOID FreeMemory(PVOID MemBlock);
ULONG GetSystemMemorySize(VOID); // Returns the amount of total usuable memory available to the memory manager
// These functions are implemented in mem.S
int GetExtendedMemorySize(void); // Returns extended memory size in KB
@ -35,4 +36,20 @@ int GetConventionalMemorySize(void); // Returns conventional memory size in K
int GetBiosMemoryMap(memory_map_t *mem_map); // Fills mem_map structure with BIOS memory map and returns length of memory map
//BOOL MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength);
//PVOID MmAllocateMemory(ULONG MemorySize);
//VOID MmFreeMemory(PVOID MemoryPointer);
//PVOID MmAllocateLowMemory(ULONG MemorySize);
//VOID MmFreeLowMemory(PVOID MemoryPointer);
//PVOID MmAllocateMemoryFrom1Mb(ULONG MemorySize);
#endif // defined __MEMORY_H

View file

@ -17,14 +17,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
include ../rules.mk
OBJS = mm.o

View file

@ -270,7 +270,8 @@ VOID DumpMemoryAllocMap(VOID)
{
if ((Idx % 32) == 0)
{
DbgPrint((DPRINT_MEMORY, "\n%x:\t", (Idx * 256)));
DbgPrint((DPRINT_MEMORY, "\n"));
DbgPrint((DPRINT_MEMORY, "%x:\t", (Idx * 256)));
}
else if ((Idx % 4) == 0)
{
@ -331,3 +332,9 @@ VOID MemAllocTest(VOID)
getch();
}
#endif // DEBUG
// Returns the amount of total usuable memory available to the memory manager
ULONG GetSystemMemorySize(VOID)
{
return HeapLengthInBytes;
}

View file

@ -17,14 +17,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
include ../rules.mk
OBJS = reactos.o arcname.o hwdetect.o reghive.o registry.o

View file

@ -84,6 +84,14 @@ void showcursor(void); // Implemented in asmcode.S
int wherex(void); // Implemented in asmcode.S
int wherey(void); // Implemented in asmcode.S
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
///////////////////////////////////////////////////////////////////////////////////////
//
// Screen Output Functions
@ -93,14 +101,34 @@ void print(char *str);
void printf(char *fmt, ...);
void sprintf(char *buffer, char *format, ...);
///////////////////////////////////////////////////////////////////////////////////////
//
// List Functions
//
///////////////////////////////////////////////////////////////////////////////////////
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
typedef struct _LIST_ITEM
{
struct _LIST_ITEM* ListPrev;
struct _LIST_ITEM* ListNext;
} LIST_ITEM, *PLIST_ITEM;
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
VOID RtlListInitializeHead(PLIST_ITEM ListHead); // Initializes a doubly linked list
VOID RtlListInsertHead(PLIST_ITEM ListHead, PLIST_ITEM Entry); // Inserts an entry at the head of the list
VOID RtlListInsertTail(PLIST_ITEM ListHead, PLIST_ITEM Entry); // Inserts an entry at the tail of the list
PLIST_ITEM RtlListRemoveHead(PLIST_ITEM ListHead); // Removes the entry at the head of the list
PLIST_ITEM RtlListRemoveTail(PLIST_ITEM ListHead); // Removes the entry at the tail of the list
PLIST_ITEM RtlListGetHead(PLIST_ITEM ListHead); // Returns the entry at the head of the list
PLIST_ITEM RtlListGetTail(PLIST_ITEM ListHead); // Returns the entry at the tail of the list
BOOL RtlListIsEmpty(PLIST_ITEM ListHead); // Indicates whether a doubly linked list is empty
ULONG RtlListCountEntries(PLIST_ITEM ListHead); // Counts the entries in a doubly linked list
PLIST_ITEM RtlListGetPrevious(PLIST_ITEM ListEntry); // Returns the previous item in the list
PLIST_ITEM RtlListGetNext(PLIST_ITEM ListEntry); // Returns the next item in the list
PLIST_ITEM RtlListRemoveEntry(PLIST_ITEM ListEntry); // Removes the entry from the list
VOID RtlListInsertEntry(PLIST_ITEM InsertAfter, PLIST_ITEM ListEntry); // Inserts a new list entry right after the specified one
VOID RtlListMoveEntryPrevious(PLIST_ITEM ListEntry); // Moves the list entry to before the previous entry
VOID RtlListMoveEntryNext(PLIST_ITEM ListEntry); // Moves the list entry to after the next entry
#endif // defined __STDLIB_H

View file

@ -17,16 +17,9 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
include ../rules.mk
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
OBJS = memory.o print.o stdlib.o string.o
OBJS = memory.o print.o stdlib.o string.o list.o
.PHONY : clean
@ -47,6 +40,9 @@ stdlib.o: stdlib.c ../rtl.h
string.o: string.c ../rtl.h
$(CC) $(FLAGS) -o string.o -c string.c
list.o: list.c ../rtl.h
$(CC) $(FLAGS) -o list.o -c list.c
clean:
- $(RM) *.o
- $(RM) *.a

175
freeldr/freeldr/rtl/list.c Normal file
View file

@ -0,0 +1,175 @@
/*
* 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 <rtl.h>
VOID RtlListInitializeHead(PLIST_ITEM ListHead)
{
ListHead->ListPrev = NULL;
ListHead->ListNext = NULL;
}
VOID RtlListInsertHead(PLIST_ITEM ListHead, PLIST_ITEM Entry)
{
ListHead = RtlListGetHead(ListHead);
ListHead->ListPrev = Entry;
Entry->ListNext = ListHead;
Entry->ListPrev = NULL;
}
VOID RtlListInsertTail(PLIST_ITEM ListHead, PLIST_ITEM Entry)
{
ListHead = RtlListGetTail(ListHead);
ListHead->ListNext = Entry;
Entry->ListNext = NULL;
Entry->ListPrev = ListHead;
}
PLIST_ITEM RtlListRemoveHead(PLIST_ITEM ListHead)
{
PLIST_ITEM OldListHead = RtlListGetHead(ListHead);
ListHead = ListHead->ListNext;
ListHead->ListPrev = NULL;
return OldListHead;
}
PLIST_ITEM RtlListRemoveTail(PLIST_ITEM ListHead)
{
PLIST_ITEM ListTail;
ListTail = RtlListGetTail(ListHead);
ListHead = ListTail->ListPrev;
ListHead->ListNext = NULL;
return ListTail;
}
PLIST_ITEM RtlListGetHead(PLIST_ITEM ListHead)
{
while (ListHead->ListPrev != NULL)
{
ListHead = ListHead->ListPrev;
}
return ListHead;
}
PLIST_ITEM RtlListGetTail(PLIST_ITEM ListHead)
{
while (ListHead->ListNext != NULL)
{
ListHead = ListHead->ListNext;
}
return ListHead;
}
BOOL RtlListIsEmpty(PLIST_ITEM ListHead)
{
if (ListHead == NULL)
{
return TRUE;
}
return (ListHead->ListNext == NULL);
}
ULONG RtlListCountEntries(PLIST_ITEM ListHead)
{
ULONG Count = 0;
while (ListHead != NULL)
{
Count++;
ListHead = ListHead->ListNext;
}
return Count;
}
PLIST_ITEM RtlListGetPrevious(PLIST_ITEM ListEntry)
{
return ListEntry->ListPrev;
}
PLIST_ITEM RtlListGetNext(PLIST_ITEM ListEntry)
{
return ListEntry->ListNext;
}
PLIST_ITEM RtlListRemoveEntry(PLIST_ITEM ListEntry)
{
PLIST_ITEM ListNext = RtlListGetNext(ListEntry);
PLIST_ITEM ListPrev = RtlListGetPrevious(ListEntry);
if (ListPrev != NULL)
{
ListPrev->ListNext = ListNext;
}
if (ListNext != NULL)
{
ListNext->ListPrev = ListPrev;
}
return ListNext;
}
VOID RtlListInsertEntry(PLIST_ITEM InsertAfter, PLIST_ITEM ListEntry)
{
PLIST_ITEM ListNext = RtlListGetNext(InsertAfter);
InsertAfter->ListNext = ListEntry;
ListEntry->ListPrev = InsertAfter;
ListEntry->ListNext = ListNext;
}
VOID RtlListMoveEntryPrevious(PLIST_ITEM ListEntry)
{
PLIST_ITEM ListPrev = RtlListGetPrevious(ListEntry);
if (ListPrev == NULL)
{
return;
}
//
// Move the previous entry after this one
//
RtlListRemoveEntry(ListPrev);
RtlListInsertEntry(ListEntry, ListPrev);
}
VOID RtlListMoveEntryNext(PLIST_ITEM ListEntry)
{
PLIST_ITEM ListNext = RtlListGetNext(ListEntry);
if (ListNext == NULL)
{
return;
}
//
// Move this entry after the next entry
//
RtlListRemoveEntry(ListEntry);
RtlListInsertEntry(ListNext, ListEntry);
}

32
freeldr/freeldr/rules.mk Normal file
View file

@ -0,0 +1,32 @@
#
# 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.
#
CC = gcc
LD = ld
AR = ar
RM = cmd /C del
CP = cmd /C copy
MAKE = make
# For a release build uncomment this line
FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -O3
# For a debug build uncomment this line
#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -DDEBUG -O3

View file

@ -57,6 +57,8 @@ BOOL IsValidFillStyle(char *fill);
char TextToFillStyle(char *fill);
// Draws the progress bar showing nPos percent filled
void DrawProgressBar(int nPos);
// Displays all the message boxes in a given section
void ShowMessageBoxesInSection(PUCHAR SectionName);
/*
* Combines the foreground and background colors into a single attribute byte

View file

@ -17,14 +17,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
include ../rules.mk
OBJS = tui.o menu.o

View file

@ -495,7 +495,7 @@ void MessageBox(char *text)
if (!UserInterfaceUp)
{
printf("%s", text);
printf("%s%s", szMessageBoxLineText, text);
printf("Press any key.\n");
getch();
return;
@ -716,3 +716,40 @@ void DrawProgressBar(int nPos)
UpdateDateTime();
}
void ShowMessageBoxesInSection(PUCHAR SectionName)
{
ULONG Idx;
UCHAR SettingName[80];
UCHAR SettingValue[80];
ULONG SectionId;
if (!OpenSection(SectionName, &SectionId))
{
sprintf(SettingName, "Section %s not found in freeldr.ini.\n", SectionName);
MessageBox(SettingName);
return;
}
//
// Find all the message box settings and run them
//
for (Idx=0; Idx<GetNumSectionItems(SectionId); Idx++)
{
ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
if (stricmp(SettingName, "MessageBox") == 0)
{
MessageBox(SettingValue);
}
else if (stricmp(SettingName, "MessageLine") == 0)
{
MessageLine(SettingValue);
}
}
//
// Zero out message line text
//
strcpy(szMessageBoxLineText, "");
}