mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Added disk cache
Optimized disk reads so it reads a track at a time or 64k if LBA svn path=/trunk/; revision=2523
This commit is contained in:
parent
ff0495900e
commit
ec2583c6d5
28 changed files with 1523 additions and 371 deletions
|
@ -16,17 +16,8 @@
|
|||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
export MAKE = make
|
||||
|
||||
#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
|
||||
FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
|
||||
include rules.mk
|
||||
|
||||
# asmcode.o has to be first in the link line because it contains the startup code
|
||||
#OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o rtl.o fs.a fs.o fat.o \
|
||||
|
@ -34,8 +25,8 @@ FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -DDEBUG -O3
|
|||
# mem.o memory.o debug.o parseini.o registry.o import.o
|
||||
ASM_OBJS = asmcode.o mb.o boot.o mem.o
|
||||
OBJS = freeldr.o miscboot.o options.o linux.o multiboot.o debug.o parseini.o oslist.o
|
||||
LIBS = rtl fs ui reactos comm disk mm
|
||||
LIB_FILES = rtl/rtl.a fs/fs.a ui/ui.a reactos/reactos.a comm/comm.a disk/disk.a mm/mm.a
|
||||
LIBS = rtl fs ui reactos comm disk mm cache
|
||||
LIB_FILES = rtl/rtl.a fs/fs.a ui/ui.a reactos/reactos.a comm/comm.a disk/disk.a mm/mm.a cache/cache.a
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
|
@ -114,6 +105,9 @@ disk:
|
|||
mm:
|
||||
$(MAKE) -C mm
|
||||
|
||||
cache:
|
||||
$(MAKE) -C cache
|
||||
|
||||
.PHONY : $(LIBS)
|
||||
|
||||
clean:
|
||||
|
@ -127,3 +121,4 @@ clean:
|
|||
$(MAKE) -C ui clean
|
||||
$(MAKE) -C fs clean
|
||||
$(MAKE) -C rtl clean
|
||||
$(MAKE) -C cache clean
|
||||
|
|
29
freeldr/freeldr/cache.h
Normal file
29
freeldr/freeldr/cache.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CACHE_H
|
||||
#define __CACHE_H
|
||||
|
||||
BOOL CacheInitializeDrive(ULONG DriveNumber);
|
||||
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer);
|
||||
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount);
|
||||
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease);
|
||||
|
||||
#endif // defined __CACHE_H
|
127
freeldr/freeldr/cache/Makefile
vendored
127
freeldr/freeldr/cache/Makefile
vendored
|
@ -17,128 +17,23 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
include ../rules.mk
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
#FLAGS = -Wall -nostdinc -fno-builtin
|
||||
FLAGS = -Wall -fno-builtin -DDEBUG -O3
|
||||
#FLAGS = -Wall -fno-builtin
|
||||
|
||||
# asmcode.o has to be first in the link line because it contains the startup code
|
||||
#OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fat.o \
|
||||
# reactos.o tui.o menu.o miscboot.o options.o linux.o multiboot.o arcname.o \
|
||||
# mem.o memory.o debug.o parseini.o registry.o import.o
|
||||
ASM_OBJS = asmcode.o mb.o boot.o mem.o
|
||||
C_OBJS = freeldr.o stdlib.o fs.a tui.o menu.o miscboot.o options.o linux.o multiboot.o \
|
||||
reactos/reactos.o reactos/registry.o reactos/reghive.o reactos/hwdetect.o
|
||||
C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o oslist.o
|
||||
OBJS = cache.o blocklist.o
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
all: freeldr.sys
|
||||
all: cache.a
|
||||
|
||||
freeldr.sys: asmcode.a c_code.a
|
||||
$(LD) -N -Ttext=0x8000 --oformat=binary -s -o f.sys asmcode.a c_code.a
|
||||
../bootsect/stubit ../bootsect/fatstub.bin f.sys freeldr.sys
|
||||
cache.a: $(OBJS)
|
||||
$(LD) -r -o cache.a $(OBJS)
|
||||
|
||||
freeldr.exe: asmcode.a c_code.a
|
||||
$(LD) -o freeldr.exe asmcode.a c_code.a
|
||||
cache.o: cache.c cm.h
|
||||
$(CC) $(FLAGS) -o cache.o -c cache.c
|
||||
|
||||
asmcode.a: $(ASM_OBJS)
|
||||
$(LD) -r -o asmcode.a $(ASM_OBJS)
|
||||
|
||||
c_code.a: c_code1.a c_code2.a
|
||||
$(LD) -r -o c_code.a c_code1.a c_code2.a
|
||||
|
||||
c_code1.a: $(C_OBJS)
|
||||
$(LD) -r -o c_code1.a $(C_OBJS)
|
||||
|
||||
c_code2.a: $(C_OBJS2)
|
||||
$(LD) -r -o c_code2.a $(C_OBJS2)
|
||||
|
||||
asmcode.o: asmcode.S asmcode.h Makefile
|
||||
$(CC) $(FLAGS) -o asmcode.o -c asmcode.S
|
||||
|
||||
freeldr.o: freeldr.c freeldr.h stdlib.h fs.h reactos/reactos.h tui.h asmcode.h menu.h miscboot.h Makefile
|
||||
$(CC) $(FLAGS) -o freeldr.o -c freeldr.c
|
||||
|
||||
stdlib.o: stdlib.c freeldr.h stdlib.h Makefile
|
||||
$(CC) $(FLAGS) -o stdlib.o -c stdlib.c
|
||||
|
||||
fs.a: fs.o fat.o Makefile
|
||||
$(LD) -r -o fs.a fs.o fat.o
|
||||
|
||||
fs.o: fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile
|
||||
$(CC) $(FLAGS) -o fs.o -c fs.c
|
||||
|
||||
fat.o: fat.c fat.h freeldr.h fs.h stdlib.h tui.h Makefile
|
||||
$(CC) $(FLAGS) -o fat.o -c fat.c
|
||||
|
||||
reactos/reactos.o: reactos/reactos.c freeldr.h reactos/reactos.h reactos/registry.h reactos/hwdetect.h stdlib.h fs.h tui.h multiboot.h Makefile
|
||||
$(CC) $(FLAGS) -o reactos/reactos.o -c reactos/reactos.c
|
||||
|
||||
multiboot.o: multiboot.c freeldr.h stdlib.h fs.h multiboot.h tui.h Makefile
|
||||
$(CC) $(FLAGS) -o multiboot.o -c multiboot.c
|
||||
|
||||
mb.o: mb.S asmcode.h multiboot.h Makefile
|
||||
$(CC) $(FLAGS) -o mb.o -c mb.S
|
||||
|
||||
tui.o: tui.c freeldr.h stdlib.h tui.h Makefile
|
||||
$(CC) $(FLAGS) -o tui.o -c tui.c
|
||||
|
||||
menu.o: menu.c freeldr.h stdlib.h tui.h menu.h Makefile
|
||||
$(CC) $(FLAGS) -o menu.o -c menu.c
|
||||
|
||||
boot.o: boot.S asmcode.h Makefile
|
||||
$(CC) $(FLAGS) -o boot.o -c boot.S
|
||||
|
||||
miscboot.o: miscboot.c freeldr.h asmcode.h stdlib.h fs.h tui.h miscboot.h Makefile
|
||||
$(CC) $(FLAGS) -o miscboot.o -c miscboot.c
|
||||
|
||||
options.o: options.c freeldr.h stdlib.h tui.h options.h Makefile
|
||||
$(CC) $(FLAGS) -o options.o -c options.c
|
||||
|
||||
linux.o: linux.c freeldr.h stdlib.h tui.h linux.h Makefile
|
||||
$(CC) $(FLAGS) -o linux.o -c linux.c
|
||||
|
||||
arcname.o: arcname.c freeldr.h arcname.h stdlib.h Makefile
|
||||
$(CC) $(FLAGS) -o arcname.o -c arcname.c
|
||||
|
||||
mem.o: mem.S asmcode.h Makefile
|
||||
$(CC) $(FLAGS) -o mem.o -c mem.S
|
||||
|
||||
memory.o: memory.c memory.h Makefile
|
||||
$(CC) $(FLAGS) -o memory.o -c memory.c
|
||||
|
||||
debug.o: debug.c debug.h Makefile
|
||||
$(CC) $(FLAGS) -o debug.o -c debug.c
|
||||
|
||||
parseini.o: parseini.c parseini.h Makefile
|
||||
$(CC) $(FLAGS) -o parseini.o -c parseini.c
|
||||
|
||||
rs232.o: rs232.c rs232.h Makefile
|
||||
$(CC) $(FLAGS) -o rs232.o -c rs232.c
|
||||
|
||||
portio.o: portio.c portio.h Makefile
|
||||
$(CC) $(FLAGS) -o portio.o -c portio.c
|
||||
|
||||
oslist.o: oslist.c oslist.h Makefile
|
||||
$(CC) $(FLAGS) -o oslist.o -c oslist.c
|
||||
|
||||
reactos/registry.o: reactos/registry.c freeldr.h memory.h reactos/registry.h stdlib.h Makefile
|
||||
$(CC) $(FLAGS) -o reactos/registry.o -c reactos/registry.c
|
||||
|
||||
reactos/reghive.o: reactos/reghive.c freeldr.h reactos/registry.h stdlib.h memory.h Makefile
|
||||
$(CC) $(FLAGS) -o reactos/reghive.o -c reactos/reghive.c
|
||||
|
||||
reactos/hwdetect.o: reactos/hwdetect.c freeldr.h reactos/hwdetect.h Makefile
|
||||
$(CC) $(FLAGS) -o reactos/hwdetect.o -c reactos/hwdetect.c
|
||||
blocklist.o: blocklist.c cm.h
|
||||
$(CC) $(FLAGS) -o blocklist.o -c blocklist.c
|
||||
|
||||
clean:
|
||||
$(RM) *.o
|
||||
$(RM) *.a
|
||||
$(RM) *.sys
|
||||
- $(RM) *.o
|
||||
- $(RM) *.a
|
||||
|
|
263
freeldr/freeldr/cache/blocklist.c
vendored
Normal file
263
freeldr/freeldr/cache/blocklist.c
vendored
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <freeldr.h>
|
||||
#include "cm.h"
|
||||
#include <mm.h>
|
||||
#include <disk.h>
|
||||
#include <rtl.h>
|
||||
#include <debug.h>
|
||||
#include <asmcode.h>
|
||||
|
||||
// Returns a pointer to a CACHE_BLOCK structure
|
||||
// Adds the block to the cache manager block list
|
||||
// in cache memory if it isn't already there
|
||||
PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock = NULL;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalGetBlockPointer() BlockNumber = %d\n", BlockNumber));
|
||||
|
||||
CacheBlock = CacheInternalFindBlock(CacheDrive, BlockNumber);
|
||||
|
||||
if (CacheBlock != NULL)
|
||||
{
|
||||
DbgPrint((DPRINT_CACHE, "Cache hit! BlockNumber: %d CacheBlock->BlockNumber: %d\n", BlockNumber, CacheBlock->BlockNumber));
|
||||
|
||||
return CacheBlock;
|
||||
}
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "Cache miss! BlockNumber: %d\n", BlockNumber));
|
||||
|
||||
CacheBlock = CacheInternalAddBlockToCache(CacheDrive, BlockNumber);
|
||||
|
||||
// Optimize the block list so it has a LRU structure
|
||||
CacheInternalOptimizeBlockList(CacheDrive, CacheBlock);
|
||||
|
||||
return CacheBlock;
|
||||
}
|
||||
|
||||
PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock = NULL;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalFindBlock() BlockNumber = %d\n", BlockNumber));
|
||||
|
||||
//
|
||||
// Make sure the block list has entries before I start searching it.
|
||||
//
|
||||
if (!RtlListIsEmpty((PLIST_ITEM)CacheDrive->CacheBlockHead))
|
||||
{
|
||||
//
|
||||
// Search the list and find the BIOS drive number
|
||||
//
|
||||
CacheBlock = CacheDrive->CacheBlockHead;
|
||||
|
||||
while (CacheBlock != NULL)
|
||||
{
|
||||
//
|
||||
// We found the block, so return it
|
||||
//
|
||||
if (CacheBlock->BlockNumber == BlockNumber)
|
||||
{
|
||||
//
|
||||
// Increment the blocks access count
|
||||
//
|
||||
CacheBlock->AccessCount++;
|
||||
|
||||
return CacheBlock;
|
||||
}
|
||||
|
||||
CacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock = NULL;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalAddBlockToCache() BlockNumber = %d\n", BlockNumber));
|
||||
|
||||
// Check the size of the cache so we don't exceed our limits
|
||||
CacheInternalCheckCacheSizeLimits(CacheDrive);
|
||||
|
||||
// We will need to add the block to the
|
||||
// drive's list of cached blocks. So allocate
|
||||
// the block memory.
|
||||
CacheBlock = AllocateMemory(sizeof(CACHE_BLOCK));
|
||||
if (CacheBlock == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Now initialize the structure and
|
||||
// allocate room for the block data
|
||||
RtlZeroMemory(CacheBlock, sizeof(CACHE_BLOCK));
|
||||
CacheBlock->BlockNumber = BlockNumber;
|
||||
CacheBlock->BlockData = AllocateMemory(CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
|
||||
if (CacheBlock->BlockData ==NULL)
|
||||
{
|
||||
FreeMemory(CacheBlock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Now try to read in the block
|
||||
if (!DiskReadMultipleLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
|
||||
{
|
||||
FreeMemory(CacheBlock->BlockData);
|
||||
FreeMemory(CacheBlock);
|
||||
return NULL;
|
||||
}
|
||||
RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
|
||||
|
||||
// Add it to our list of blocks managed by the cache
|
||||
if (CacheDrive->CacheBlockHead == NULL)
|
||||
{
|
||||
CacheDrive->CacheBlockHead = CacheBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlListInsertTail((PLIST_ITEM)CacheDrive->CacheBlockHead, (PLIST_ITEM)CacheBlock);
|
||||
}
|
||||
|
||||
// Update the cache data
|
||||
CacheBlockCount++;
|
||||
CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
|
||||
|
||||
CacheInternalDumpBlockList(CacheDrive);
|
||||
|
||||
return CacheBlock;
|
||||
}
|
||||
|
||||
BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlockToFree;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalFreeBlock()\n"));
|
||||
|
||||
// Get a pointer to the last item in the block list
|
||||
// that isn't forced to be in the cache and remove
|
||||
// it from the list
|
||||
CacheBlockToFree = (PCACHE_BLOCK)RtlListGetTail((PLIST_ITEM)CacheDrive->CacheBlockHead);
|
||||
while (CacheBlockToFree != NULL && CacheBlockToFree->LockedInCache == TRUE)
|
||||
{
|
||||
CacheBlockToFree = (PCACHE_BLOCK)RtlListGetPrevious((PLIST_ITEM)CacheBlockToFree);
|
||||
}
|
||||
|
||||
// No blocks left in cache that can be freed
|
||||
// so just return
|
||||
if (CacheBlockToFree == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// If we are freeing the head of the list then update it's pointer
|
||||
//
|
||||
if (CacheBlockToFree == CacheDrive->CacheBlockHead)
|
||||
{
|
||||
CacheDrive->CacheBlockHead = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlockToFree);
|
||||
}
|
||||
|
||||
RtlListRemoveEntry((PLIST_ITEM)CacheBlockToFree);
|
||||
|
||||
// Free the block memory and the block structure
|
||||
FreeMemory(CacheBlockToFree->BlockData);
|
||||
FreeMemory(CacheBlockToFree);
|
||||
|
||||
// Update the cache data
|
||||
CacheBlockCount--;
|
||||
CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive)
|
||||
{
|
||||
ULONG NewCacheSize;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalCheckCacheSizeLimits()\n"));
|
||||
|
||||
// Calculate the size of the cache if we added a block
|
||||
NewCacheSize = (CacheBlockCount + 1) * (CacheDrive->BlockSize * CacheDrive->DriveGeometry.BytesPerSector);
|
||||
|
||||
// Check the new size against the cache size limit
|
||||
if (NewCacheSize > CacheSizeLimit)
|
||||
{
|
||||
CacheInternalFreeBlock(CacheDrive);
|
||||
CacheInternalDumpBlockList(CacheDrive);
|
||||
}
|
||||
}
|
||||
|
||||
VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber));
|
||||
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheDrive->LbaSupported ? "TRUE" : "FALSE"));
|
||||
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheDrive->DriveGeometry.Cylinders));
|
||||
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheDrive->DriveGeometry.Heads));
|
||||
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheDrive->DriveGeometry.Sectors));
|
||||
DbgPrint((DPRINT_CACHE, "BytesPerSector: %d.\n", CacheDrive->DriveGeometry.BytesPerSector));
|
||||
DbgPrint((DPRINT_CACHE, "BlockSize: %d.\n", CacheDrive->BlockSize));
|
||||
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d.\n", CacheSizeLimit));
|
||||
DbgPrint((DPRINT_CACHE, "CacheSizeCurrent: %d.\n", CacheSizeCurrent));
|
||||
DbgPrint((DPRINT_CACHE, "CacheBlockCount: %d.\n", CacheBlockCount));
|
||||
DbgPrint((DPRINT_CACHE, "Dumping %d cache blocks.\n", RtlListCountEntries((PLIST_ITEM)CacheDrive->CacheBlockHead)));
|
||||
|
||||
CacheBlock = CacheDrive->CacheBlockHead;
|
||||
while (CacheBlock != NULL)
|
||||
{
|
||||
DbgPrint((DPRINT_CACHE, "Cache Block: CacheBlock: 0x%x\n", CacheBlock));
|
||||
DbgPrint((DPRINT_CACHE, "Cache Block: Block Number: %d\n", CacheBlock->BlockNumber));
|
||||
DbgPrint((DPRINT_CACHE, "Cache Block: Access Count: %d\n", CacheBlock->AccessCount));
|
||||
DbgPrint((DPRINT_CACHE, "Cache Block: Block Data: 0x%x\n", CacheBlock->BlockData));
|
||||
DbgPrint((DPRINT_CACHE, "Cache Block: Locked In Cache: %d\n", CacheBlock->LockedInCache));
|
||||
|
||||
if (CacheBlock->BlockData == NULL)
|
||||
{
|
||||
BugCheck((DPRINT_CACHE, "What the heck?!?\n"));
|
||||
}
|
||||
|
||||
CacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheBlock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock)
|
||||
{
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheInternalOptimizeBlockList()\n"));
|
||||
|
||||
// Don't do this if this block is already at the head of the list
|
||||
if (CacheBlock != CacheDrive->CacheBlockHead)
|
||||
{
|
||||
// Remove this item from the block list
|
||||
RtlListRemoveEntry((PLIST_ITEM)CacheBlock);
|
||||
|
||||
// Re-insert it at the head of the list
|
||||
RtlListInsertHead((PLIST_ITEM)CacheDrive->CacheBlockHead, (PLIST_ITEM)CacheBlock);
|
||||
|
||||
// Update the head pointer
|
||||
CacheDrive->CacheBlockHead = CacheBlock;
|
||||
}
|
||||
}
|
323
freeldr/freeldr/cache/cache.c
vendored
Normal file
323
freeldr/freeldr/cache/cache.c
vendored
Normal file
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <freeldr.h>
|
||||
#include "cm.h"
|
||||
#include <mm.h>
|
||||
#include <disk.h>
|
||||
#include <rtl.h>
|
||||
#include <debug.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Internal data
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
CACHE_DRIVE CacheManagerDrive;
|
||||
BOOL CacheManagerInitialized = FALSE;
|
||||
ULONG CacheBlockCount = 0;
|
||||
ULONG CacheSizeLimit = 0;
|
||||
ULONG CacheSizeCurrent = 0;
|
||||
|
||||
BOOL CacheInitializeDrive(ULONG DriveNumber)
|
||||
{
|
||||
PCACHE_BLOCK NextCacheBlock;
|
||||
|
||||
// If we already have a cache for this drive then
|
||||
// by all means lets keep it
|
||||
if (CacheManagerInitialized && DriveNumber == CacheManagerDrive.DriveNumber)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// If we have already been initialized then free
|
||||
// the old data
|
||||
//
|
||||
if (CacheManagerInitialized)
|
||||
{
|
||||
CacheManagerInitialized = FALSE;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheBlockCount: %d\n", CacheBlockCount));
|
||||
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d\n", CacheSizeLimit));
|
||||
DbgPrint((DPRINT_CACHE, "CacheSizeCurrent: %d\n", CacheSizeCurrent));
|
||||
//
|
||||
// Loop through and free the cache blocks
|
||||
//
|
||||
while (CacheManagerDrive.CacheBlockHead != NULL)
|
||||
{
|
||||
NextCacheBlock = (PCACHE_BLOCK)RtlListGetNext((PLIST_ITEM)CacheManagerDrive.CacheBlockHead);
|
||||
|
||||
FreeMemory(CacheManagerDrive.CacheBlockHead->BlockData);
|
||||
FreeMemory(CacheManagerDrive.CacheBlockHead);
|
||||
|
||||
CacheManagerDrive.CacheBlockHead = NextCacheBlock;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the structure
|
||||
RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
|
||||
CacheManagerDrive.DriveNumber = DriveNumber;
|
||||
CacheManagerDrive.LbaSupported = BiosInt13ExtensionsSupported(DriveNumber);
|
||||
if (!DiskGetDriveGeometry(DriveNumber, &CacheManagerDrive.DriveGeometry))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If LBA is supported then the block size will be 128 sectors (64k)
|
||||
// If not then the block size is the size of one track
|
||||
if (CacheManagerDrive.LbaSupported)
|
||||
{
|
||||
CacheManagerDrive.BlockSize = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
CacheManagerDrive.BlockSize = CacheManagerDrive.DriveGeometry.Sectors;
|
||||
}
|
||||
|
||||
CacheBlockCount = 0;
|
||||
CacheSizeLimit = GetSystemMemorySize() / 8;
|
||||
CacheSizeCurrent = 0;
|
||||
if (CacheSizeLimit < (64 * 1024))
|
||||
{
|
||||
CacheSizeLimit = (64 * 1024);
|
||||
}
|
||||
|
||||
CacheManagerInitialized = TRUE;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "Initializing BIOS drive 0x%x.\n", DriveNumber));
|
||||
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheManagerDrive.LbaSupported ? "TRUE" : "FALSE"));
|
||||
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheManagerDrive.DriveGeometry.Cylinders));
|
||||
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheManagerDrive.DriveGeometry.Heads));
|
||||
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheManagerDrive.DriveGeometry.Sectors));
|
||||
DbgPrint((DPRINT_CACHE, "BytesPerSector: %d.\n", CacheManagerDrive.DriveGeometry.BytesPerSector));
|
||||
DbgPrint((DPRINT_CACHE, "BlockSize: %d.\n", CacheManagerDrive.BlockSize));
|
||||
DbgPrint((DPRINT_CACHE, "CacheSizeLimit: %d.\n", CacheSizeLimit));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock;
|
||||
ULONG StartBlock;
|
||||
ULONG SectorOffsetInStartBlock;
|
||||
ULONG CopyLengthInStartBlock;
|
||||
ULONG EndBlock;
|
||||
ULONG SectorOffsetInEndBlock;
|
||||
ULONG BlockCount;
|
||||
ULONG Idx;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer));
|
||||
|
||||
// If we aren't initialized yet then they can't do this
|
||||
if (CacheManagerInitialized == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Caculate which blocks we must cache
|
||||
//
|
||||
StartBlock = StartSector / CacheManagerDrive.BlockSize;
|
||||
SectorOffsetInStartBlock = StartSector % CacheManagerDrive.BlockSize;
|
||||
CopyLengthInStartBlock = (SectorCount > (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock)) ? (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock) : SectorCount;
|
||||
EndBlock = (StartSector + (SectorCount - 1)) / CacheManagerDrive.BlockSize;
|
||||
SectorOffsetInEndBlock = (StartSector + SectorCount) % CacheManagerDrive.BlockSize;
|
||||
BlockCount = (EndBlock - StartBlock) + 1;
|
||||
DbgPrint((DPRINT_CACHE, "StartBlock: %d SectorOffsetInStartBlock: %d CopyLengthInStartBlock: %d EndBlock: %d SectorOffsetInEndBlock: %d BlockCount: %d\n", StartBlock, SectorOffsetInStartBlock, CopyLengthInStartBlock, EndBlock, SectorOffsetInEndBlock, BlockCount));
|
||||
|
||||
//
|
||||
// Read the first block into the buffer
|
||||
//
|
||||
if (BlockCount > 0)
|
||||
{
|
||||
//
|
||||
// Get cache block pointer (this forces the disk sectors into the cache memory)
|
||||
//
|
||||
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, StartBlock);
|
||||
if (CacheBlock == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the portion requested into the buffer
|
||||
//
|
||||
RtlCopyMemory(Buffer,
|
||||
(CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)),
|
||||
(CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector));
|
||||
DbgPrint((DPRINT_CACHE, "1 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, (CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)), (CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector)));
|
||||
|
||||
//
|
||||
// Update the buffer address
|
||||
//
|
||||
Buffer += (CopyLengthInStartBlock * CacheManagerDrive.DriveGeometry.BytesPerSector);
|
||||
|
||||
//
|
||||
// Update the block count
|
||||
//
|
||||
BlockCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through the middle blocks and read them into the buffer
|
||||
//
|
||||
for (Idx=StartBlock+1; BlockCount>1; Idx++)
|
||||
{
|
||||
//
|
||||
// Get cache block pointer (this forces the disk sectors into the cache memory)
|
||||
//
|
||||
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
|
||||
if (CacheBlock == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the portion requested into the buffer
|
||||
//
|
||||
RtlCopyMemory(Buffer,
|
||||
CacheBlock->BlockData,
|
||||
CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector);
|
||||
DbgPrint((DPRINT_CACHE, "2 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector));
|
||||
|
||||
//
|
||||
// Update the buffer address
|
||||
//
|
||||
Buffer += CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector;
|
||||
|
||||
//
|
||||
// Update the block count
|
||||
//
|
||||
BlockCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// Read the last block into the buffer
|
||||
//
|
||||
if (BlockCount > 0)
|
||||
{
|
||||
//
|
||||
// Get cache block pointer (this forces the disk sectors into the cache memory)
|
||||
//
|
||||
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, EndBlock);
|
||||
if (CacheBlock == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the portion requested into the buffer
|
||||
//
|
||||
RtlCopyMemory(Buffer,
|
||||
CacheBlock->BlockData,
|
||||
SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector);
|
||||
DbgPrint((DPRINT_CACHE, "3 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector));
|
||||
|
||||
//
|
||||
// Update the buffer address
|
||||
//
|
||||
Buffer += SectorOffsetInEndBlock * CacheManagerDrive.DriveGeometry.BytesPerSector;
|
||||
|
||||
//
|
||||
// Update the block count
|
||||
//
|
||||
BlockCount--;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount)
|
||||
{
|
||||
PCACHE_BLOCK CacheBlock;
|
||||
ULONG StartBlock;
|
||||
ULONG EndBlock;
|
||||
ULONG BlockCount;
|
||||
ULONG Idx;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount));
|
||||
|
||||
// If we aren't initialized yet then they can't do this
|
||||
if (CacheManagerInitialized == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Caculate which blocks we must cache
|
||||
//
|
||||
StartBlock = StartSector / CacheManagerDrive.BlockSize;
|
||||
EndBlock = (StartSector + SectorCount) / CacheManagerDrive.BlockSize;
|
||||
BlockCount = (EndBlock - StartBlock) + 1;
|
||||
|
||||
//
|
||||
// Loop through and cache them
|
||||
//
|
||||
for (Idx=StartBlock; Idx<(StartBlock+BlockCount); Idx++)
|
||||
{
|
||||
//
|
||||
// Get cache block pointer (this forces the disk sectors into the cache memory)
|
||||
//
|
||||
CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
|
||||
if (CacheBlock == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Lock the sectors into the cache
|
||||
//
|
||||
CacheBlock->LockedInCache = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease)
|
||||
{
|
||||
ULONG AmountReleased;
|
||||
|
||||
DbgPrint((DPRINT_CACHE, "CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease));
|
||||
|
||||
// If we aren't initialized yet then they can't do this
|
||||
if (CacheManagerInitialized == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Loop through and try to free the requested amount of memory
|
||||
for (AmountReleased=0; AmountReleased<MinimumAmountToRelease; )
|
||||
{
|
||||
// Try to free a block
|
||||
// If this fails then break out of the loop
|
||||
if (!CacheInternalFreeBlock(&CacheManagerDrive))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// It succeeded so increment the amount of memory we have freed
|
||||
AmountReleased += CacheManagerDrive.BlockSize * CacheManagerDrive.DriveGeometry.BytesPerSector;
|
||||
}
|
||||
|
||||
// Return status
|
||||
return (AmountReleased >= MinimumAmountToRelease);
|
||||
}
|
93
freeldr/freeldr/cache/cm.h
vendored
Normal file
93
freeldr/freeldr/cache/cm.h
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <freeldr.h>
|
||||
#include <rtl.h>
|
||||
#include <disk.h>
|
||||
|
||||
#ifndef __CM_H
|
||||
#define __CM_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This structure describes a cached block element. The disk is divided up into
|
||||
// cache blocks. For disks which LBA is not supported each block is the size of
|
||||
// one track. This will force the cache manager to make track sized reads, and
|
||||
// therefore maximizes throughput. For disks which support LBA the block size
|
||||
// is 64k because they have no cylinder, head, or sector boundaries.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct
|
||||
{
|
||||
LIST_ITEM ListEntry; // Doubly linked list synchronization member
|
||||
|
||||
ULONG BlockNumber; // Track index for CHS, 64k block index for LBA
|
||||
BOOL LockedInCache; // Indicates that this block is locked in cache memory
|
||||
ULONG AccessCount; // Access count for this block
|
||||
|
||||
PVOID BlockData; // Pointer to block data
|
||||
|
||||
} CACHE_BLOCK, *PCACHE_BLOCK;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This structure describes a cached drive. It contains the BIOS drive number
|
||||
// and indicates whether or not LBA is supported. If LBA is not supported then
|
||||
// the drive's geometry is described here.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct
|
||||
{
|
||||
ULONG DriveNumber;
|
||||
BOOL LbaSupported;
|
||||
GEOMETRY DriveGeometry;
|
||||
|
||||
ULONG BlockSize; // Block size (in sectors)
|
||||
PCACHE_BLOCK CacheBlockHead;
|
||||
|
||||
} CACHE_DRIVE, *PCACHE_DRIVE;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Internal data
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
extern CACHE_DRIVE CacheManagerDrive;
|
||||
extern BOOL CacheManagerInitialized;
|
||||
extern ULONG CacheBlockCount;
|
||||
extern ULONG CacheSizeLimit;
|
||||
extern ULONG CacheSizeCurrent;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Internal functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Returns a pointer to a CACHE_BLOCK structure given a block number
|
||||
PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Searches the block list for a particular block
|
||||
PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Adds a block to the cache's block list
|
||||
BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive); // Removes a block from the cache's block list & frees the memory
|
||||
VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive); // Checks the cache size limits to see if we can add a new block, if not calls CacheInternalFreeBlock()
|
||||
VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive); // Dumps the list of cached blocks to the debug output port
|
||||
VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock); // Moves the specified block to the head of the list
|
||||
|
||||
|
||||
#endif // defined __CM_H
|
|
@ -17,14 +17,7 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
include ../rules.mk
|
||||
|
||||
OBJS = rs232.o portio.o
|
||||
|
||||
|
|
|
@ -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++)))
|
||||
|
|
|
@ -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, ...);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,16 +17,9 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
include ../rules.mk
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
|
||||
OBJS = disk.o
|
||||
OBJS = disk.o geometry.o
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
|
@ -38,6 +31,9 @@ disk.a: $(OBJS)
|
|||
disk.o: disk.c ../disk.h
|
||||
$(CC) $(FLAGS) -o disk.o -c disk.c
|
||||
|
||||
geometry.o: geometry.c ../disk.h
|
||||
$(CC) $(FLAGS) -o geometry.o -c geometry.c
|
||||
|
||||
clean:
|
||||
- $(RM) *.o
|
||||
- $(RM) *.a
|
||||
|
|
|
@ -26,14 +26,6 @@
|
|||
#include <debug.h>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DATA
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GEOMETRY DriveGeometry;
|
||||
ULONG VolumeHiddenSectors;
|
||||
ULONG CurrentlyOpenDriveNumber;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FUNCTIONS
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -54,122 +46,30 @@ VOID DiskError(PUCHAR ErrorString)
|
|||
}
|
||||
}
|
||||
|
||||
VOID DiskSetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
|
||||
BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
DriveGeometry.Cylinders = Cylinders;
|
||||
DriveGeometry.Heads = Heads;
|
||||
DriveGeometry.Sectors = Sectors;
|
||||
DriveGeometry.BytesPerSector = BytesPerSector;
|
||||
ULONG PhysicalSector;
|
||||
ULONG PhysicalHead;
|
||||
ULONG PhysicalTrack;
|
||||
GEOMETRY DriveGeometry;
|
||||
ULONG NumberOfSectorsToRead;
|
||||
|
||||
DbgPrint((DPRINT_DISK, "DriveGeometry.Cylinders: %d\n", DriveGeometry.Cylinders));
|
||||
DbgPrint((DPRINT_DISK, "DriveGeometry.Heads: %d\n", DriveGeometry.Heads));
|
||||
DbgPrint((DPRINT_DISK, "DriveGeometry.Sectors: %d\n", DriveGeometry.Sectors));
|
||||
DbgPrint((DPRINT_DISK, "DriveGeometry.BytesPerSector: %d\n", DriveGeometry.BytesPerSector));
|
||||
}
|
||||
|
||||
VOID DiskSetVolumeProperties(ULONG HiddenSectors)
|
||||
{
|
||||
VolumeHiddenSectors = HiddenSectors;
|
||||
}
|
||||
|
||||
BOOL DiskReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
/*BOOL bRetVal;
|
||||
int PhysicalSector;
|
||||
int PhysicalHead;
|
||||
int PhysicalTrack;
|
||||
int nNum;
|
||||
|
||||
nSect += nHiddenSectors;
|
||||
|
||||
while (nNumberOfSectors)
|
||||
{
|
||||
PhysicalSector = 1 + (nSect % nSectorsPerTrack);
|
||||
PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
|
||||
PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
|
||||
|
||||
if (PhysicalSector > 1)
|
||||
{
|
||||
if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1)))
|
||||
nNum = (nSectorsPerTrack - (PhysicalSector - 1));
|
||||
else
|
||||
nNum = nNumberOfSectors;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nNumberOfSectors >= nSectorsPerTrack)
|
||||
nNum = nSectorsPerTrack;
|
||||
else
|
||||
nNum = nNumberOfSectors;
|
||||
}
|
||||
|
||||
bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
|
||||
|
||||
if (!bRetVal)
|
||||
{
|
||||
FS_DO_ERROR("Disk Error");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pBuffer += (nNum * 512);
|
||||
nNumberOfSectors -= nNum;
|
||||
nSect += nNum;
|
||||
}*/
|
||||
|
||||
ULONG CurrentSector;
|
||||
PVOID RealBuffer = Buffer;
|
||||
|
||||
for (CurrentSector=SectorNumber; CurrentSector<(SectorNumber + SectorCount); CurrentSector++)
|
||||
{
|
||||
if (!DiskReadLogicalSector(CurrentSector, RealBuffer) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RealBuffer += DriveGeometry.BytesPerSector;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DiskReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
|
||||
{
|
||||
ULONG PhysicalSector;
|
||||
ULONG PhysicalHead;
|
||||
ULONG PhysicalTrack;
|
||||
|
||||
DbgPrint((DPRINT_DISK, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber, Buffer));
|
||||
|
||||
SectorNumber += VolumeHiddenSectors;
|
||||
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
|
||||
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
|
||||
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
|
||||
|
||||
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
|
||||
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
|
||||
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
|
||||
if (PhysicalHead >= DriveGeometry.Heads)
|
||||
{
|
||||
BugCheck((DPRINT_DISK, "PhysicalHead >= DriveGeometry.Heads\nPhysicalHead = %d\nDriveGeometry.Heads = %d\n", PhysicalHead, DriveGeometry.Heads));
|
||||
}
|
||||
if (PhysicalTrack >= DriveGeometry.Cylinders)
|
||||
{
|
||||
BugCheck((DPRINT_DISK, "PhysicalTrack >= DriveGeometry.Cylinders\nPhysicalTrack = %d\nDriveGeometry.Cylinders = %d\n", PhysicalTrack, DriveGeometry.Cylinders));
|
||||
}
|
||||
if (PhysicalSector > DriveGeometry.Sectors)
|
||||
{
|
||||
BugCheck((DPRINT_DISK, "PhysicalSector > DriveGeometry.Sectors\nPhysicalSector = %d\nDriveGeometry.Sectors = %d\n", PhysicalSector, DriveGeometry.Sectors));
|
||||
}
|
||||
DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
|
||||
|
||||
//
|
||||
// Check to see if it is a fixed disk drive
|
||||
// If so then check to see if Int13 extensions work
|
||||
// If they do then use them, otherwise default back to BIOS calls
|
||||
//
|
||||
if ((CurrentlyOpenDriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber)) && (SectorNumber > (DriveGeometry.Cylinders * DriveGeometry.Heads * DriveGeometry.Sectors)))
|
||||
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
|
||||
{
|
||||
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", CurrentlyOpenDriveNumber, BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber) ? "TRUE" : "FALSE"));
|
||||
if ( !BiosInt13ReadExtended(CurrentlyOpenDriveNumber, SectorNumber, 1, Buffer) )
|
||||
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
|
||||
|
||||
//
|
||||
// LBA is easy, nothing to calculate
|
||||
// Just do the read
|
||||
//
|
||||
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
|
||||
{
|
||||
DiskError("Disk read error.");
|
||||
return FALSE;
|
||||
|
@ -177,7 +77,141 @@ BOOL DiskReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( !BiosInt13Read(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer) )
|
||||
//
|
||||
// Get the drive geometry
|
||||
//
|
||||
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (SectorCount)
|
||||
{
|
||||
|
||||
//
|
||||
// Calculate the physical disk offsets
|
||||
//
|
||||
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
|
||||
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
|
||||
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
|
||||
|
||||
//
|
||||
// Calculate how many sectors we are supposed to read
|
||||
//
|
||||
if (PhysicalSector > 1)
|
||||
{
|
||||
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
|
||||
NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
|
||||
else
|
||||
NumberOfSectorsToRead = SectorCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SectorCount >= DriveGeometry.Sectors)
|
||||
NumberOfSectorsToRead = DriveGeometry.Sectors;
|
||||
else
|
||||
NumberOfSectorsToRead = SectorCount;
|
||||
}
|
||||
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead));
|
||||
|
||||
//
|
||||
// Make sure the read is within the geometry boundaries
|
||||
//
|
||||
if ((PhysicalHead >= DriveGeometry.Heads) ||
|
||||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
|
||||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
|
||||
(PhysicalSector > DriveGeometry.Sectors))
|
||||
{
|
||||
DiskError("Disk read exceeds drive geometry limits.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Perform the read
|
||||
//
|
||||
if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer))
|
||||
{
|
||||
DiskError("Disk read error.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
|
||||
SectorCount -= NumberOfSectorsToRead;
|
||||
SectorNumber += NumberOfSectorsToRead;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer)
|
||||
{
|
||||
ULONG PhysicalSector;
|
||||
ULONG PhysicalHead;
|
||||
ULONG PhysicalTrack;
|
||||
GEOMETRY DriveGeometry;
|
||||
|
||||
DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
|
||||
|
||||
//
|
||||
// Check to see if it is a fixed disk drive
|
||||
// If so then check to see if Int13 extensions work
|
||||
// If they do then use them, otherwise default back to BIOS calls
|
||||
//
|
||||
if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
|
||||
{
|
||||
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
|
||||
|
||||
//
|
||||
// LBA is easy, nothing to calculate
|
||||
// Just do the read
|
||||
//
|
||||
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
|
||||
{
|
||||
DiskError("Disk read error.");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Get the drive geometry
|
||||
//
|
||||
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the physical disk offsets
|
||||
//
|
||||
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
|
||||
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
|
||||
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
|
||||
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
|
||||
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
|
||||
|
||||
//
|
||||
// Make sure the read is within the geometry boundaries
|
||||
//
|
||||
if ((PhysicalHead >= DriveGeometry.Heads) ||
|
||||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
|
||||
(PhysicalSector > DriveGeometry.Sectors))
|
||||
{
|
||||
DiskError("Disk read exceeds drive geometry limits.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Perform the read
|
||||
//
|
||||
if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer))
|
||||
{
|
||||
DiskError("Disk read error.");
|
||||
return FALSE;
|
||||
|
|
126
freeldr/freeldr/disk/geometry.c
Normal file
126
freeldr/freeldr/disk/geometry.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <freeldr.h>
|
||||
#include <disk.h>
|
||||
#include <rtl.h>
|
||||
#include <mm.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ITEM ListEntry;
|
||||
|
||||
ULONG DriveNumber;
|
||||
GEOMETRY DriveGeometry;
|
||||
|
||||
} DRIVE_GEOMETRY, *PDRIVE_GEOMETRY;
|
||||
|
||||
|
||||
PDRIVE_GEOMETRY DriveGeometryListHead = NULL;
|
||||
|
||||
|
||||
BOOL DiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry)
|
||||
{
|
||||
PDRIVE_GEOMETRY DriveGeometryListEntry;
|
||||
|
||||
//
|
||||
// Search the drive geometry list for the requested drive
|
||||
//
|
||||
DriveGeometryListEntry = DriveGeometryListHead;
|
||||
while (DriveGeometryListEntry != NULL)
|
||||
{
|
||||
//
|
||||
// Check to see if this is the drive we want
|
||||
//
|
||||
if (DriveGeometryListEntry->DriveNumber == DriveNumber)
|
||||
{
|
||||
//
|
||||
// Yep - return the information
|
||||
//
|
||||
RtlCopyMemory(DriveGeometry, &DriveGeometryListEntry->DriveGeometry, sizeof(GEOMETRY));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Nope, get next item
|
||||
//
|
||||
DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry);
|
||||
}
|
||||
|
||||
DiskError("Drive geometry unknown.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL DiskSetDriveGeometry(ULONG DriveNumber, ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
|
||||
{
|
||||
PDRIVE_GEOMETRY DriveGeometryListEntry;
|
||||
|
||||
//
|
||||
// Search the drive geometry list for the requested drive
|
||||
//
|
||||
DriveGeometryListEntry = DriveGeometryListHead;
|
||||
while (DriveGeometryListEntry != NULL)
|
||||
{
|
||||
//
|
||||
// Check to see if this is the drive
|
||||
//
|
||||
if (DriveGeometryListEntry->DriveNumber == DriveNumber)
|
||||
{
|
||||
//
|
||||
// Yes, we already have this drive's geometry information
|
||||
// so just return
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Nope, get next item
|
||||
//
|
||||
DriveGeometryListEntry = (PDRIVE_GEOMETRY)RtlListGetNext((PLIST_ITEM)DriveGeometryListEntry);
|
||||
}
|
||||
|
||||
//
|
||||
// If we get here then this is a new drive and we have
|
||||
// to add it's information to our list
|
||||
//
|
||||
DriveGeometryListEntry = (PDRIVE_GEOMETRY)AllocateMemory(sizeof(DRIVE_GEOMETRY));
|
||||
if (DriveGeometryListEntry == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RtlZeroMemory(DriveGeometryListEntry, sizeof(DRIVE_GEOMETRY));
|
||||
DriveGeometryListEntry->DriveNumber = DriveNumber;
|
||||
DriveGeometryListEntry->DriveGeometry.Cylinders = Cylinders;
|
||||
DriveGeometryListEntry->DriveGeometry.Heads = Heads;
|
||||
DriveGeometryListEntry->DriveGeometry.Sectors = Sectors;
|
||||
DriveGeometryListEntry->DriveGeometry.BytesPerSector = BytesPerSector;
|
||||
|
||||
if (DriveGeometryListHead == NULL)
|
||||
{
|
||||
DriveGeometryListHead = DriveGeometryListEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlListInsertTail((PLIST_ITEM)DriveGeometryListHead, (PLIST_ITEM)DriveGeometryListEntry);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -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 (;;)
|
||||
{
|
||||
|
|
|
@ -17,14 +17,7 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
include ../rules.mk
|
||||
|
||||
OBJS = fs.o fat.o
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,14 +17,7 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
include ../rules.mk
|
||||
|
||||
OBJS = mm.o
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -17,14 +17,7 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
include ../rules.mk
|
||||
|
||||
OBJS = reactos.o arcname.o hwdetect.o reghive.o registry.o
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,16 +17,9 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
include ../rules.mk
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
|
||||
OBJS = memory.o print.o stdlib.o string.o
|
||||
OBJS = memory.o print.o stdlib.o string.o list.o
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
|
@ -47,6 +40,9 @@ stdlib.o: stdlib.c ../rtl.h
|
|||
string.o: string.c ../rtl.h
|
||||
$(CC) $(FLAGS) -o string.o -c string.c
|
||||
|
||||
list.o: list.c ../rtl.h
|
||||
$(CC) $(FLAGS) -o list.o -c list.c
|
||||
|
||||
clean:
|
||||
- $(RM) *.o
|
||||
- $(RM) *.a
|
||||
|
|
175
freeldr/freeldr/rtl/list.c
Normal file
175
freeldr/freeldr/rtl/list.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
VOID RtlListInitializeHead(PLIST_ITEM ListHead)
|
||||
{
|
||||
ListHead->ListPrev = NULL;
|
||||
ListHead->ListNext = NULL;
|
||||
}
|
||||
|
||||
VOID RtlListInsertHead(PLIST_ITEM ListHead, PLIST_ITEM Entry)
|
||||
{
|
||||
ListHead = RtlListGetHead(ListHead);
|
||||
ListHead->ListPrev = Entry;
|
||||
Entry->ListNext = ListHead;
|
||||
Entry->ListPrev = NULL;
|
||||
}
|
||||
|
||||
VOID RtlListInsertTail(PLIST_ITEM ListHead, PLIST_ITEM Entry)
|
||||
{
|
||||
ListHead = RtlListGetTail(ListHead);
|
||||
ListHead->ListNext = Entry;
|
||||
Entry->ListNext = NULL;
|
||||
Entry->ListPrev = ListHead;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListRemoveHead(PLIST_ITEM ListHead)
|
||||
{
|
||||
PLIST_ITEM OldListHead = RtlListGetHead(ListHead);
|
||||
|
||||
ListHead = ListHead->ListNext;
|
||||
ListHead->ListPrev = NULL;
|
||||
|
||||
return OldListHead;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListRemoveTail(PLIST_ITEM ListHead)
|
||||
{
|
||||
PLIST_ITEM ListTail;
|
||||
|
||||
ListTail = RtlListGetTail(ListHead);
|
||||
ListHead = ListTail->ListPrev;
|
||||
ListHead->ListNext = NULL;
|
||||
|
||||
return ListTail;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListGetHead(PLIST_ITEM ListHead)
|
||||
{
|
||||
while (ListHead->ListPrev != NULL)
|
||||
{
|
||||
ListHead = ListHead->ListPrev;
|
||||
}
|
||||
|
||||
return ListHead;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListGetTail(PLIST_ITEM ListHead)
|
||||
{
|
||||
while (ListHead->ListNext != NULL)
|
||||
{
|
||||
ListHead = ListHead->ListNext;
|
||||
}
|
||||
|
||||
return ListHead;
|
||||
}
|
||||
|
||||
BOOL RtlListIsEmpty(PLIST_ITEM ListHead)
|
||||
{
|
||||
if (ListHead == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return (ListHead->ListNext == NULL);
|
||||
}
|
||||
|
||||
ULONG RtlListCountEntries(PLIST_ITEM ListHead)
|
||||
{
|
||||
ULONG Count = 0;
|
||||
|
||||
while (ListHead != NULL)
|
||||
{
|
||||
Count++;
|
||||
ListHead = ListHead->ListNext;
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListGetPrevious(PLIST_ITEM ListEntry)
|
||||
{
|
||||
return ListEntry->ListPrev;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListGetNext(PLIST_ITEM ListEntry)
|
||||
{
|
||||
return ListEntry->ListNext;
|
||||
}
|
||||
|
||||
PLIST_ITEM RtlListRemoveEntry(PLIST_ITEM ListEntry)
|
||||
{
|
||||
PLIST_ITEM ListNext = RtlListGetNext(ListEntry);
|
||||
PLIST_ITEM ListPrev = RtlListGetPrevious(ListEntry);
|
||||
|
||||
if (ListPrev != NULL)
|
||||
{
|
||||
ListPrev->ListNext = ListNext;
|
||||
}
|
||||
|
||||
if (ListNext != NULL)
|
||||
{
|
||||
ListNext->ListPrev = ListPrev;
|
||||
}
|
||||
|
||||
return ListNext;
|
||||
}
|
||||
|
||||
VOID RtlListInsertEntry(PLIST_ITEM InsertAfter, PLIST_ITEM ListEntry)
|
||||
{
|
||||
PLIST_ITEM ListNext = RtlListGetNext(InsertAfter);
|
||||
|
||||
InsertAfter->ListNext = ListEntry;
|
||||
ListEntry->ListPrev = InsertAfter;
|
||||
ListEntry->ListNext = ListNext;
|
||||
}
|
||||
|
||||
VOID RtlListMoveEntryPrevious(PLIST_ITEM ListEntry)
|
||||
{
|
||||
PLIST_ITEM ListPrev = RtlListGetPrevious(ListEntry);
|
||||
|
||||
if (ListPrev == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Move the previous entry after this one
|
||||
//
|
||||
RtlListRemoveEntry(ListPrev);
|
||||
RtlListInsertEntry(ListEntry, ListPrev);
|
||||
}
|
||||
|
||||
VOID RtlListMoveEntryNext(PLIST_ITEM ListEntry)
|
||||
{
|
||||
PLIST_ITEM ListNext = RtlListGetNext(ListEntry);
|
||||
|
||||
if (ListNext == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Move this entry after the next entry
|
||||
//
|
||||
RtlListRemoveEntry(ListEntry);
|
||||
RtlListInsertEntry(ListNext, ListEntry);
|
||||
}
|
32
freeldr/freeldr/rules.mk
Normal file
32
freeldr/freeldr/rules.mk
Normal file
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# FreeLoader
|
||||
# Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
CC = gcc
|
||||
LD = ld
|
||||
AR = ar
|
||||
RM = cmd /C del
|
||||
CP = cmd /C copy
|
||||
MAKE = make
|
||||
|
||||
# For a release build uncomment this line
|
||||
FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -O3
|
||||
|
||||
# For a debug build uncomment this line
|
||||
#FLAGS = -Wall -nostdlib -nostdinc -fno-builtin -I./ -I../ -DDEBUG -O3
|
|
@ -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
|
||||
|
|
|
@ -17,14 +17,7 @@
|
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
|
||||
export CC = gcc
|
||||
export LD = ld
|
||||
export AR = ar
|
||||
export RM = cmd /C del
|
||||
export CP = cmd /C copy
|
||||
|
||||
FLAGS = -Wall -fno-builtin -I../ -DDEBUG -O3
|
||||
include ../rules.mk
|
||||
|
||||
OBJS = tui.o menu.o
|
||||
|
||||
|
|
|
@ -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, "");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue