Added disk cache
authorBrian Palmer <brianp@sginet.com>
Fri, 18 Jan 2002 05:59:58 +0000 (05:59 +0000)
committerBrian Palmer <brianp@sginet.com>
Fri, 18 Jan 2002 05:59:58 +0000 (05:59 +0000)
Optimized disk reads so it reads a track at a time or 64k if LBA

svn path=/trunk/; revision=2523

28 files changed:
freeldr/freeldr/Makefile
freeldr/freeldr/cache.h [new file with mode: 0644]
freeldr/freeldr/cache/Makefile
freeldr/freeldr/cache/blocklist.c [new file with mode: 0644]
freeldr/freeldr/cache/cache.c [new file with mode: 0644]
freeldr/freeldr/cache/cm.h [new file with mode: 0644]
freeldr/freeldr/comm/Makefile
freeldr/freeldr/debug.c
freeldr/freeldr/debug.h
freeldr/freeldr/disk.h
freeldr/freeldr/disk/Makefile
freeldr/freeldr/disk/disk.c
freeldr/freeldr/disk/geometry.c [new file with mode: 0644]
freeldr/freeldr/freeldr.c
freeldr/freeldr/fs/Makefile
freeldr/freeldr/fs/fat.c
freeldr/freeldr/fs/fat.h
freeldr/freeldr/mm.h
freeldr/freeldr/mm/Makefile
freeldr/freeldr/mm/mm.c
freeldr/freeldr/reactos/Makefile
freeldr/freeldr/rtl.h
freeldr/freeldr/rtl/Makefile
freeldr/freeldr/rtl/list.c [new file with mode: 0644]
freeldr/freeldr/rules.mk [new file with mode: 0644]
freeldr/freeldr/ui.h
freeldr/freeldr/ui/Makefile
freeldr/freeldr/ui/tui.c

index 890a09f..8554489 100644 (file)
 #  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 (file)
index 0000000..b72ed05
--- /dev/null
@@ -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
index 9db6277..2c9d903 100644 (file)
 #  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
-
-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 
-
-freeldr.exe:   asmcode.a c_code.a
-       $(LD) -o freeldr.exe asmcode.a c_code.a
-
-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
+all: cache.a
 
-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
+cache.a:       $(OBJS)
+       $(LD) -r -o cache.a $(OBJS)
 
-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
+cache.o:       cache.c cm.h
+       $(CC) $(FLAGS) -o cache.o -c cache.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 (file)
index 0000000..9b341a9
--- /dev/null
@@ -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;
+       }
+}
diff --git a/freeldr/freeldr/cache/cache.c b/freeldr/freeldr/cache/cache.c
new file mode 100644 (file)
index 0000000..b69df8c
--- /dev/null
@@ -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);
+}
diff --git a/freeldr/freeldr/cache/cm.h b/freeldr/freeldr/cache/cm.h
new file mode 100644 (file)
index 0000000..c02c86e
--- /dev/null
@@ -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
index 436862c..f8c5945 100644 (file)
 #  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
 
index e781870..697bb37 100644 (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++)))
index 1bbafbf..7643076 100644 (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, ...);
index 9902cae..76f3807 100644 (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
index d3707c1..7621e27 100644 (file)
 #  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
index 7f52163..d41f3de 100644 (file)
 #include <debug.h>
 
 
-/////////////////////////////////////////////////////////////////////////////////////////////
-// DATA
-/////////////////////////////////////////////////////////////////////////////////////////////
-
-GEOMETRY       DriveGeometry;
-ULONG          VolumeHiddenSectors;
-ULONG          CurrentlyOpenDriveNumber;
-
 /////////////////////////////////////////////////////////////////////////////////////////////
 // FUNCTIONS
 /////////////////////////////////////////////////////////////////////////////////////////////
@@ -54,122 +46,131 @@ 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;
-
-       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));
-}
+       ULONG           PhysicalSector;
+       ULONG           PhysicalHead;
+       ULONG           PhysicalTrack;
+       GEOMETRY        DriveGeometry;
+       ULONG           NumberOfSectorsToRead;
 
-VOID DiskSetVolumeProperties(ULONG HiddenSectors)
-{
-       VolumeHiddenSectors = HiddenSectors;
-}
+       DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
 
-BOOL DiskReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
-{
-       /*BOOL  bRetVal;
-       int             PhysicalSector;
-       int             PhysicalHead;
-       int             PhysicalTrack;
-       int             nNum;
-
-       nSect += nHiddenSectors;
-
-       while (nNumberOfSectors)
+       //
+       // 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)))
        {
-               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;
-               }
+               DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
 
-               bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
-
-               if (!bRetVal)
+               //
+               // LBA is easy, nothing to calculate
+               // Just do the read
+               //
+               if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
                {
-                       FS_DO_ERROR("Disk Error");
+                       DiskError("Disk read error.");
                        return FALSE;
                }
-
-               pBuffer += (nNum * 512);
-               nNumberOfSectors -= nNum;
-               nSect += nNum;
-       }*/
-
-       ULONG   CurrentSector;
-       PVOID   RealBuffer = Buffer;
-
-       for (CurrentSector=SectorNumber; CurrentSector<(SectorNumber + SectorCount); CurrentSector++)
+       }
+       else
        {
-               if (!DiskReadLogicalSector(CurrentSector, RealBuffer) )
+               //
+               // Get the drive geometry
+               //
+               if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
                {
                        return FALSE;
                }
 
-               RealBuffer += DriveGeometry.BytesPerSector;
+               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 SectorNumber, PVOID Buffer)
+BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer)
 {
-       ULONG   PhysicalSector;
-       ULONG   PhysicalHead;
-       ULONG   PhysicalTrack;
-
-       DbgPrint((DPRINT_DISK, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber, Buffer));
+       ULONG           PhysicalSector;
+       ULONG           PhysicalHead;
+       ULONG           PhysicalTrack;
+       GEOMETRY        DriveGeometry;
 
-       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 +178,40 @@ 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;
+               }
+
+               //
+               // 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 (file)
index 0000000..10ef9b9
--- /dev/null
@@ -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;
+}
index 70c18d6..c8b92a1 100644 (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 (;;)
        {
index d0af045..5989166 100644 (file)
 #  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
 
index 0468a0e..3cb8335 100644 (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);
+}
index bb8976c..78e468e 100644 (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
index 778035f..77c3132 100644 (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
index 20399ba..c92a8da 100644 (file)
 #  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
 
index 2abd69d..7a65284 100644 (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;
+}
index b724fe3..2972f75 100644 (file)
 #  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
 
index 1fd6bab..bdde865 100644 (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
index 3a5ab94..1359791 100644 (file)
 #  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 (file)
index 0000000..4c812b0
--- /dev/null
@@ -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);
+}
diff --git a/freeldr/freeldr/rules.mk b/freeldr/freeldr/rules.mk
new file mode 100644 (file)
index 0000000..cf35b9f
--- /dev/null
@@ -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
index 0a92d35..53b0652 100644 (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
index 7a2258c..b51a2b8 100644 (file)
 #  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
 
index 1d44471..f0a18bf 100644 (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, "");
+}