#include <initguid.h>
#include <ntddk.h>
+#include <ntifs.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <scsi.h>
#include <ntddvol.h>
#include <mountdev.h>
#include <mountmgr.h>
-#include <helper.h>
#include <ketypes.h>
#include <iotypes.h>
#include <rtlfuncs.h>
#define NDEBUG
#include <debug.h>
+#define DO_XIP 0x00020000
+
/* GLOBALS ********************************************************************/
#define RAMDISK_SESSION_SIZE \
typedef struct _RAMDISK_DRIVE_EXTENSION
{
+ //
+ // Inherited base class
+ //
RAMDISK_EXTENSION;
+
+ //
+ // Data we get from the creator
+ //
GUID DiskGuid;
UNICODE_STRING GuidString;
UNICODE_STRING SymbolicLinkName;
ULONG DiskType;
RAMDISK_CREATE_OPTIONS DiskOptions;
- LONGLONG DiskLength;
+ LARGE_INTEGER DiskLength;
LONG DiskOffset;
WCHAR DriveLetter;
+ ULONG BasePage;
+
+ //
+ // Data we get from the disk
+ //
ULONG BytesPerSector;
ULONG SectorsPerTrack;
ULONG NumberOfHeads;
+ ULONG Cylinders;
+ ULONG HiddenSectors;
} RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
ULONG MaximumViewLength;
IN ULONG Length,
OUT PULONG OutputLength)
{
- DPRINT1("Mapping %lx bytes at %I64x\n", Length, Offset.QuadPart);
- UNIMPLEMENTED;
- while (TRUE);
- return NULL;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID MappedBase;
+ ULONG PageOffset;
+ SIZE_T ActualLength;
+ LARGE_INTEGER ActualOffset;
+ LARGE_INTEGER ActualPages;
+
+ //
+ // We only support boot disks for now
+ //
+ ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
+
+ //
+ // Calculate the actual offset in the drive
+ //
+ ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
+
+ //
+ // Convert to pages
+ //
+ ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
+
+ //
+ // Now add the base page
+ //
+ ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
+
+ //
+ // Calculate final amount of bytes
+ //
+ PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
+
+ //
+ // Calculate pages spanned for the mapping
+ //
+ ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
+
+ //
+ // And convert this back to bytes
+ //
+ ActualLength <<= PAGE_SHIFT;
+
+ //
+ // Get the offset within the page
+ //
+ PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
+
+ //
+ // Map the I/O Space from the loader
+ //
+ MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
+
+ //
+ // Return actual offset within the page as well as the length
+ //
+ if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
+ *OutputLength = Length;
+ return MappedBase;
}
-PVOID
+VOID
NTAPI
RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
IN PVOID BaseAddress,
IN LARGE_INTEGER Offset,
IN ULONG Length)
{
- UNIMPLEMENTED;
- while (TRUE);
- return NULL;
+ LARGE_INTEGER ActualOffset;
+ SIZE_T ActualLength;
+ ULONG PageOffset;
+
+ //
+ // We only support boot disks for now
+ //
+ ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
+
+ //
+ // Calculate the actual offset in the drive
+ //
+ ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
+
+ //
+ // Calculate pages spanned for the mapping
+ //
+ ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
+
+ //
+ // And convert this back to bytes
+ //
+ ActualLength <<= PAGE_SHIFT;
+
+ //
+ // Get the offset within the page
+ //
+ PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
+
+ //
+ // Calculate actual base address where we mapped this
+ //
+ BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
+
+ //
+ // Unmap the I/O space we got from the loader
+ //
+ MmUnmapIoSpace(BaseAddress, ActualLength);
}
NTSTATUS
PVOID Buffer;
WCHAR LocalBuffer[16];
UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
- PPACKED_BIOS_PARAMETER_BLOCK Parameters;
+ PPACKED_BOOT_SECTOR BootSector;
+ BIOS_PARAMETER_BLOCK BiosBlock;
ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
PVOID BaseAddress;
- LARGE_INTEGER CurrentOffset;
+ LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
+ ULONG CylinderCount, SizeByCylinders;
//
// Check if we're a boot RAM disk
Length = GuidString.Length + 32;
Buffer = ExAllocatePoolWithTag(NonPagedPool,
Length,
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!Buffer)
{
//
DeviceName.MaximumLength = Length;
wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
- DPRINT1("Creating device: %wZ\n", &DeviceName);
//
// Create the drive device
SymbolicLinkName.Length = GuidString.Length + 34;
Buffer = ExAllocatePoolWithTag(NonPagedPool,
SymbolicLinkName.MaximumLength,
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
SymbolicLinkName.Buffer = Buffer;
if (Buffer)
{
wcsncat(Buffer,
GuidString.Buffer,
SymbolicLinkName.MaximumLength / sizeof(WCHAR));
- DPRINT1("Creating symbolic link: %wZ to %wZ \n",
- &SymbolicLinkName, &DeviceName);
Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (!NT_SUCCESS(Status))
{
L"\\DosDevices\\%wc:",
Input->DriveLetter);
RtlInitUnicodeString(&DriveString, LocalBuffer);
- DPRINT1("Creating symbolic link: %wZ to %wZ\n",
- &DriveString, &DeviceName);
IoDeleteSymbolicLink(&DriveString);
IoCreateSymbolicLink(&DriveString, &DeviceName);
//
*NewDriveExtension = DriveExtension;
DriveExtension->Type = RamdiskDrive;
+ DiskLength = Input->DiskLength;
ExInitializeFastMutex(&DriveExtension->DiskListLock);
IoInitializeRemoveLock(&DriveExtension->RemoveLock,
- TAG('R', 'a', 'm', 'd'),
+ 'dmaR',
0,
1);
DriveExtension->DriveDeviceName = DeviceName;
DriveExtension->AttachedDevice = RamdiskBusFdo;
DriveExtension->DiskType = Input->DiskType;
DriveExtension->DiskOptions = Input->Options;
- DriveExtension->DiskLength = Input->DiskLength;
+ DriveExtension->DiskLength = DiskLength;
DriveExtension->DiskOffset = Input->DiskOffset;
-
+ DriveExtension->BasePage = Input->BasePage;
+ DriveExtension->BytesPerSector = 0;
+ DriveExtension->SectorsPerTrack = 0;
+ DriveExtension->NumberOfHeads = 0;
+
//
// Make sure we don't free it later
//
//
// Get the data
//
- Parameters = (PPACKED_BIOS_PARAMETER_BLOCK)BaseAddress;
- BytesPerSector = Parameters->BytesPerSector[0];
- SectorsPerTrack = Parameters->SectorsPerTrack[0];
- Heads = Parameters->Heads[0];
+ BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
+ FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
+ BytesPerSector = BiosBlock.BytesPerSector;
+ SectorsPerTrack = BiosBlock.SectorsPerTrack;
+ Heads = BiosBlock.Heads;
//
// Save it
goto FailCreate;
}
}
-
+
//
// Check if the drive settings haven't been set yet
//
DriveExtension->NumberOfHeads = 16;
}
}
-
+
+ //
+ // Calculate the cylinder size
+ //
+ CylinderSize.QuadPart = DriveExtension->BytesPerSector *
+ DriveExtension->SectorsPerTrack *
+ DriveExtension->NumberOfHeads;
+ CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
+ SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
+ DriveExtension->Cylinders = CylinderCount;
+ if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
+ {
+ //
+ // Align cylinder size up
+ //
+ DriveExtension->Cylinders++;
+ }
+
//
// Acquire the disk lock
//
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
- return IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ return;
}
//
//
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
- return IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
NTSTATUS
// Get the MDL and check if it's mapped
//
Mdl = Irp->MdlAddress;
- if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
+ if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
{
//
// Use the mapped address
//
// Do the copy loop
//
- DPRINT1("Initiating copy loop for %lx bytes at %p\n", BytesLeft, SystemVa);
while (TRUE)
{
//
}
}
+NTSTATUS
+NTAPI
+RamdiskGetPartitionInfo(IN PIRP Irp,
+ IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
+{
+ NTSTATUS Status;
+ PPARTITION_INFORMATION PartitionInfo;
+ PVOID BaseAddress;
+ LARGE_INTEGER Zero = {{0, 0}};
+ ULONG Length;
+ PIO_STACK_LOCATION IoStackLocation;
+
+ //
+ // Validate the length
+ //
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(PARTITION_INFORMATION))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ return Status;
+ }
+
+ //
+ // Map the partition table
+ //
+ BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &Length);
+ if (!BaseAddress)
+ {
+ //
+ // No memory
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ return Status;
+ }
+
+ //
+ // Fill out the information
+ //
+ PartitionInfo = Irp->AssociatedIrp.SystemBuffer;
+ PartitionInfo->StartingOffset.QuadPart = DeviceExtension->BytesPerSector;
+ PartitionInfo->PartitionLength.QuadPart = DeviceExtension->BytesPerSector *
+ DeviceExtension->SectorsPerTrack *
+ DeviceExtension->NumberOfHeads *
+ DeviceExtension->Cylinders;
+ PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors;
+ PartitionInfo->PartitionNumber = 0;
+ PartitionInfo->PartitionType = PARTITION_FAT32; //*((PCHAR)BaseAddress + 450);
+ PartitionInfo->BootIndicator = (DeviceExtension->DiskType ==
+ RAMDISK_BOOT_DISK) ? TRUE: FALSE;
+ PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartitionInfo->
+ PartitionType);
+ PartitionInfo->RewritePartition = FALSE;
+
+ //
+ // Unmap the partition table
+ //
+ RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, Length);
+
+ //
+ // Done
+ //
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
NTAPI
RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
NTSTATUS Status;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
ULONG Information;
PCDROM_TOC Toc;
+ PDISK_GEOMETRY DiskGeometry;
//
// Grab the remove lock
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
- UNIMPLEMENTED;
- while (TRUE);
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(DISK_GEOMETRY))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Fill it out
+ //
+ DiskGeometry = Irp->AssociatedIrp.SystemBuffer;
+ DiskGeometry->Cylinders.QuadPart = DriveExtension->Cylinders;
+ DiskGeometry->BytesPerSector = DriveExtension->BytesPerSector;
+ DiskGeometry->SectorsPerTrack = DriveExtension->SectorsPerTrack;
+ DiskGeometry->TracksPerCylinder = DriveExtension->NumberOfHeads;
+ DiskGeometry->MediaType = DriveExtension->DiskOptions.Fixed ?
+ FixedMedia : RemovableMedia;
+
+ //
+ // We're done
+ //
+ Status = STATUS_SUCCESS;
+ Information = sizeof(DISK_GEOMETRY);
break;
//
//
// Validate the length
//
- DPRINT1("Output: %lx\n", IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength);
if (IoStackLocation->Parameters.DeviceIoControl.
OutputBufferLength < sizeof(CDROM_TOC))
{
//
// Fill it out
//
- DPRINT1("TOC: %d\n", RAMDISK_TOC_SIZE);
Toc->Length[0] = 0;
Toc->Length[1] = RAMDISK_TOC_SIZE - sizeof(Toc->Length);
Toc->FirstTrack = 1;
case IOCTL_DISK_GET_PARTITION_INFO:
- UNIMPLEMENTED;
- while (TRUE);
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(PARTITION_INFORMATION))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Check if we need to do this sync or async
+ //
+ if (DriveExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
+ {
+ //
+ // Call the helper function
+ //
+ Status = RamdiskGetPartitionInfo(Irp, DriveExtension);
+ }
+ else
+ {
+ //
+ // Do it asynchronously later
+ //
+ goto CallWorker;
+ }
+
+ //
+ // We're done
+ //
+ Information = Irp->IoStatus.Information;
break;
case IOCTL_DISK_GET_DRIVE_LAYOUT:
//
// Queue the request to our worker thread
//
+CallWorker:
Status = SendIrpToThread(DeviceObject, Irp);
CompleteRequest:
Objects) +
FinalCount *
sizeof(PDEVICE_OBJECT),
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!OurDeviceRelations)
{
//
DeviceExtension->Type = RamdiskBus;
ExInitializeFastMutex(&DeviceExtension->DiskListLock);
IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
- TAG('R', 'a', 'm', 'd'),
+ 'dmaR',
0,
1);
InitializeListHead(&DeviceExtension->DiskList);
//
// Are we being booted from setup? Not yet supported
//
- ASSERT (!KeLoaderBlock->SetupLdrBlock);
+ //ASSERT(!KeLoaderBlock->SetupLdrBlock);
}
//
PCHAR BootDeviceName, CommandLine;
PDEVICE_OBJECT PhysicalDeviceObject = NULL;
NTSTATUS Status;
+ DPRINT("RAM Disk Driver Initialized\n");
//
// Query ramdisk parameters
DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
RegistryPath->Length +
sizeof(WCHAR),
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
//
// Installing from Ramdisk isn't supported yet
//
- ASSERT(!KeLoaderBlock->SetupLdrBlock);
+ //ASSERT(!KeLoaderBlock->SetupLdrBlock);
//
// Are we reporting the device