diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile index 890a09f62e5..85544895108 100644 --- a/freeldr/freeldr/Makefile +++ b/freeldr/freeldr/Makefile @@ -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 diff --git a/freeldr/freeldr/cache.h b/freeldr/freeldr/cache.h new file mode 100644 index 00000000000..b72ed0599e9 --- /dev/null +++ b/freeldr/freeldr/cache.h @@ -0,0 +1,29 @@ +/* + * FreeLoader + * Copyright (C) 2001 Brian Palmer + * + * 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 diff --git a/freeldr/freeldr/cache/Makefile b/freeldr/freeldr/cache/Makefile index 9db62776a42..2c9d903da9f 100644 --- a/freeldr/freeldr/cache/Makefile +++ b/freeldr/freeldr/cache/Makefile @@ -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 diff --git a/freeldr/freeldr/cache/blocklist.c b/freeldr/freeldr/cache/blocklist.c new file mode 100644 index 00000000000..9b341a97869 --- /dev/null +++ b/freeldr/freeldr/cache/blocklist.c @@ -0,0 +1,263 @@ +/* + * FreeLoader + * Copyright (C) 2001 Brian Palmer + * + * 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 +#include "cm.h" +#include +#include +#include +#include +#include + +// 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; + } +} diff --git a/freeldr/freeldr/cache/cache.c b/freeldr/freeldr/cache/cache.c new file mode 100644 index 00000000000..b69df8c2666 --- /dev/null +++ b/freeldr/freeldr/cache/cache.c @@ -0,0 +1,323 @@ +/* + * FreeLoader + * Copyright (C) 2001 Brian Palmer + * + * 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 +#include "cm.h" +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// +// +// 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); +} diff --git a/freeldr/freeldr/cache/cm.h b/freeldr/freeldr/cache/cm.h new file mode 100644 index 00000000000..c02c86e987a --- /dev/null +++ b/freeldr/freeldr/cache/cm.h @@ -0,0 +1,93 @@ +/* + * FreeLoader + * Copyright (C) 2001 Brian Palmer + * + * 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 +#include +#include + +#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 diff --git a/freeldr/freeldr/comm/Makefile b/freeldr/freeldr/comm/Makefile index 436862c1249..f8c5945c600 100644 --- a/freeldr/freeldr/comm/Makefile +++ b/freeldr/freeldr/comm/Makefile @@ -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 diff --git a/freeldr/freeldr/debug.c b/freeldr/freeldr/debug.c index e781870d7b3..697bb37fb97 100644 --- a/freeldr/freeldr/debug.c +++ b/freeldr/freeldr/debug.c @@ -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++))) diff --git a/freeldr/freeldr/debug.h b/freeldr/freeldr/debug.h index 1bbafbff0a6..76430765b20 100644 --- a/freeldr/freeldr/debug.h +++ b/freeldr/freeldr/debug.h @@ -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, ...); diff --git a/freeldr/freeldr/disk.h b/freeldr/freeldr/disk.h index 9902cae0dc8..76f3807e8d0 100644 --- a/freeldr/freeldr/disk.h +++ b/freeldr/freeldr/disk.h @@ -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 diff --git a/freeldr/freeldr/disk/Makefile b/freeldr/freeldr/disk/Makefile index d3707c10edc..7621e27a04f 100644 --- a/freeldr/freeldr/disk/Makefile +++ b/freeldr/freeldr/disk/Makefile @@ -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 diff --git a/freeldr/freeldr/disk/disk.c b/freeldr/freeldr/disk/disk.c index 7f521630ccb..d41f3de8b9d 100644 --- a/freeldr/freeldr/disk/disk.c +++ b/freeldr/freeldr/disk/disk.c @@ -26,14 +26,6 @@ #include -///////////////////////////////////////////////////////////////////////////////////////////// -// 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; diff --git a/freeldr/freeldr/disk/geometry.c b/freeldr/freeldr/disk/geometry.c new file mode 100644 index 00000000000..10ef9b9f55c --- /dev/null +++ b/freeldr/freeldr/disk/geometry.c @@ -0,0 +1,126 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000, 2001 Brian Palmer + * + * 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 +#include +#include +#include + + +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; +} diff --git a/freeldr/freeldr/freeldr.c b/freeldr/freeldr/freeldr.c index 70c18d629d8..c8b92a1b566 100644 --- a/freeldr/freeldr/freeldr.c +++ b/freeldr/freeldr/freeldr.c @@ -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 #include #include +#include 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); +} diff --git a/freeldr/freeldr/fs/fat.h b/freeldr/freeldr/fs/fat.h index bb8976ca89c..78e468e3a53 100644 --- a/freeldr/freeldr/fs/fat.h +++ b/freeldr/freeldr/fs/fat.h @@ -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 diff --git a/freeldr/freeldr/mm.h b/freeldr/freeldr/mm.h index 778035f6cea..77c3132634b 100644 --- a/freeldr/freeldr/mm.h +++ b/freeldr/freeldr/mm.h @@ -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 diff --git a/freeldr/freeldr/mm/Makefile b/freeldr/freeldr/mm/Makefile index 20399ba3777..c92a8da38cf 100644 --- a/freeldr/freeldr/mm/Makefile +++ b/freeldr/freeldr/mm/Makefile @@ -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 diff --git a/freeldr/freeldr/mm/mm.c b/freeldr/freeldr/mm/mm.c index 2abd69d1e38..7a652843d5f 100644 --- a/freeldr/freeldr/mm/mm.c +++ b/freeldr/freeldr/mm/mm.c @@ -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; +} diff --git a/freeldr/freeldr/reactos/Makefile b/freeldr/freeldr/reactos/Makefile index b724fe38d82..2972f75f885 100644 --- a/freeldr/freeldr/reactos/Makefile +++ b/freeldr/freeldr/reactos/Makefile @@ -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 diff --git a/freeldr/freeldr/rtl.h b/freeldr/freeldr/rtl.h index 1fd6bab5484..bdde86502c3 100644 --- a/freeldr/freeldr/rtl.h +++ b/freeldr/freeldr/rtl.h @@ -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 diff --git a/freeldr/freeldr/rtl/Makefile b/freeldr/freeldr/rtl/Makefile index 3a5ab94b3cc..135979103ff 100644 --- a/freeldr/freeldr/rtl/Makefile +++ b/freeldr/freeldr/rtl/Makefile @@ -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 diff --git a/freeldr/freeldr/rtl/list.c b/freeldr/freeldr/rtl/list.c new file mode 100644 index 00000000000..4c812b0c1c2 --- /dev/null +++ b/freeldr/freeldr/rtl/list.c @@ -0,0 +1,175 @@ +/* + * FreeLoader + * Copyright (C) 2001 Brian Palmer + * + * 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 + +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); +} diff --git a/freeldr/freeldr/rules.mk b/freeldr/freeldr/rules.mk new file mode 100644 index 00000000000..cf35b9f45ae --- /dev/null +++ b/freeldr/freeldr/rules.mk @@ -0,0 +1,32 @@ +# +# FreeLoader +# Copyright (C) 1999, 2000, 2001 Brian Palmer +# +# 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 diff --git a/freeldr/freeldr/ui.h b/freeldr/freeldr/ui.h index 0a92d35f439..53b0652b6c5 100644 --- a/freeldr/freeldr/ui.h +++ b/freeldr/freeldr/ui.h @@ -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 diff --git a/freeldr/freeldr/ui/Makefile b/freeldr/freeldr/ui/Makefile index 7a2258cc446..b51a2b8a41e 100644 --- a/freeldr/freeldr/ui/Makefile +++ b/freeldr/freeldr/ui/Makefile @@ -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 diff --git a/freeldr/freeldr/ui/tui.c b/freeldr/freeldr/ui/tui.c index 1d444719a78..f0a18bf43e1 100644 --- a/freeldr/freeldr/ui/tui.c +++ b/freeldr/freeldr/ui/tui.c @@ -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