715 lines
19 KiB
C
715 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1993 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
XIPDisk.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This is the XIP Disk driver for Whistler NT/Embedded.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
DavePr 18-Sep-2000 -- base one NT4 DDK ramdisk by RobertN 10-Mar-1993.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Include files.
|
|||
|
//
|
|||
|
|
|||
|
#include <ntddk.h>
|
|||
|
#include "initguid.h"
|
|||
|
#include "mountdev.h"
|
|||
|
|
|||
|
#include <ntdddisk.h> // Disk device IOCTLs, DiskClassGuid
|
|||
|
|
|||
|
#include "fat.h"
|
|||
|
#include "xip.h"
|
|||
|
#include "XIPDisk.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// ISSUE-2000/10/11-DavePr -- haven't decided how to define DO_XIP appropriately.
|
|||
|
//
|
|||
|
#ifndef DO_XIP
|
|||
|
#define DO_XIP 0x00020000
|
|||
|
#endif
|
|||
|
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
XIPDiskCreateClose(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by the I/O system when the XIPDisk is opened or
|
|||
|
closed.
|
|||
|
|
|||
|
No action is performed other than completing the request successfully.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - a pointer to the object that represents the device
|
|||
|
that I/O is to be done on.
|
|||
|
|
|||
|
Irp - a pointer to the I/O Request Packet for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_INVALID_PARAMETER if parameters are invalid,
|
|||
|
STATUS_SUCCESS otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PXIPDISK_EXTENSION diskExtension = NULL; // ptr to device extension
|
|||
|
PBIOS_PARAMETER_BLOCK bios;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
diskExtension = DeviceObject->DeviceExtension;
|
|||
|
status = XIPDispatch(XIPCMD_NOOP, NULL, 0);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status) || !diskExtension->BootParameters.BasePage) {
|
|||
|
status = STATUS_DEVICE_NOT_READY;
|
|||
|
} else {
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
Irp->IoStatus.Status = status;
|
|||
|
Irp->IoStatus.Information = 0;
|
|||
|
|
|||
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
XIPDiskReadWrite(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by the I/O system to read or write to a
|
|||
|
device that we control.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - a pointer to the object that represents the device
|
|||
|
that I/O is to be done on.
|
|||
|
|
|||
|
Irp - a pointer to the I/O Request Packet for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_INVALID_PARAMETER if parameters are invalid,
|
|||
|
STATUS_SUCCESS otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PXIPDISK_EXTENSION diskExtension;
|
|||
|
PIO_STACK_LOCATION irpSp;
|
|||
|
PUCHAR bufferAddress, diskByteAddress;
|
|||
|
PUCHAR romPageAddress = NULL;
|
|||
|
ULONG_PTR ioOffset;
|
|||
|
ULONG ioLength;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PHYSICAL_ADDRESS physicalAddress;
|
|||
|
ULONG mappingSize;
|
|||
|
|
|||
|
//
|
|||
|
// Set up necessary object and extension pointers.
|
|||
|
//
|
|||
|
diskExtension = DeviceObject->DeviceExtension;
|
|||
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
|
|||
|
//
|
|||
|
// Check for invalid parameters. It is an error for the starting offset
|
|||
|
// + length to go past the end of the buffer, or for the offset or length
|
|||
|
// not to be a proper multiple of the sector size.
|
|||
|
//
|
|||
|
// Others are possible, but we don't check them since we trust the
|
|||
|
// file system and they aren't deadly.
|
|||
|
//
|
|||
|
|
|||
|
if (irpSp->Parameters.Read.ByteOffset.HighPart) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
ioOffset = irpSp->Parameters.Read.ByteOffset.LowPart;
|
|||
|
ioLength = irpSp->Parameters.Read.Length;
|
|||
|
|
|||
|
if (ioLength == 0) {
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
if (ioOffset + ioLength < ioOffset) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
if ((ioOffset | ioLength) & (diskExtension->BiosParameters.BytesPerSector - 1)) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
goto done;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ((ioOffset + ioLength) > (diskExtension->BootParameters.PageCount * PAGE_SIZE)) {
|
|||
|
status = STATUS_NONEXISTENT_SECTOR;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
if (irpSp->MajorFunction == IRP_MJ_WRITE && diskExtension->BootParameters.ReadOnly) {
|
|||
|
status = STATUS_MEDIA_WRITE_PROTECTED;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Map the pages in the ROM into system space
|
|||
|
//
|
|||
|
mappingSize = ADDRESS_AND_SIZE_TO_SPAN_PAGES (ioOffset, ioLength) * PAGE_SIZE;
|
|||
|
|
|||
|
//
|
|||
|
// Get a system-space pointer to the disk region.
|
|||
|
//
|
|||
|
physicalAddress.QuadPart = (diskExtension->BootParameters.BasePage + (ioOffset/PAGE_SIZE)) * PAGE_SIZE;
|
|||
|
|
|||
|
romPageAddress = MmMapIoSpace(physicalAddress, mappingSize, MmCached);
|
|||
|
if (! romPageAddress) {
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
diskByteAddress = romPageAddress + (ioOffset & (PAGE_SIZE-1));
|
|||
|
|
|||
|
//
|
|||
|
// Get a system-space pointer to the user's buffer. A system
|
|||
|
// address must be used because we may already have left the
|
|||
|
// original caller's address space.
|
|||
|
//
|
|||
|
|
|||
|
Irp->IoStatus.Information = irpSp->Parameters.Read.Length;
|
|||
|
|
|||
|
ASSERT (Irp->MdlAddress != NULL);
|
|||
|
|
|||
|
bufferAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
|
|||
|
|
|||
|
if (! bufferAddress) {
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto done;
|
|||
|
}
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
|
|||
|
switch (irpSp->MajorFunction) {
|
|||
|
case IRP_MJ_READ:
|
|||
|
RtlCopyMemory( bufferAddress, diskByteAddress, ioLength );
|
|||
|
break;
|
|||
|
|
|||
|
case IRP_MJ_WRITE:
|
|||
|
RtlCopyMemory( diskByteAddress, bufferAddress, ioLength );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ASSERT(FALSE);
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
done:
|
|||
|
if (romPageAddress) {
|
|||
|
MmUnmapIoSpace (romPageAddress, mappingSize);
|
|||
|
}
|
|||
|
|
|||
|
Irp->IoStatus.Status = status;
|
|||
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
XIPDiskDeviceControl(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by the I/O system to perform a device I/O
|
|||
|
control function.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - a pointer to the object that represents the device
|
|||
|
that I/O is to be done on.
|
|||
|
|
|||
|
Irp - a pointer to the I/O Request Packet for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS if recognized I/O control code,
|
|||
|
STATUS_INVALID_DEVICE_REQUEST otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PBIOS_PARAMETER_BLOCK bios;
|
|||
|
PXIPDISK_EXTENSION diskExtension;
|
|||
|
PIO_STACK_LOCATION irpSp;
|
|||
|
NTSTATUS status;
|
|||
|
ULONG info;
|
|||
|
|
|||
|
//
|
|||
|
// Set up necessary object and extension pointers.
|
|||
|
//
|
|||
|
|
|||
|
diskExtension = DeviceObject->DeviceExtension;
|
|||
|
bios = &diskExtension->BiosParameters;
|
|||
|
|
|||
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
//
|
|||
|
// Assume failure.
|
|||
|
//
|
|||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|||
|
info = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Determine which I/O control code was specified.
|
|||
|
//
|
|||
|
switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
|
|||
|
|
|||
|
case IOCTL_DISK_GET_MEDIA_TYPES:
|
|||
|
case IOCTL_STORAGE_GET_MEDIA_TYPES:
|
|||
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
|
|||
|
//
|
|||
|
// Return the drive geometry for the virtual disk. Note that
|
|||
|
// we return values which were made up to suit the disk size.
|
|||
|
//
|
|||
|
|
|||
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) {
|
|||
|
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
PDISK_GEOMETRY outputBuffer;
|
|||
|
|
|||
|
outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
outputBuffer->MediaType = FixedMedia;
|
|||
|
outputBuffer->Cylinders.QuadPart = diskExtension->NumberOfCylinders;
|
|||
|
outputBuffer->TracksPerCylinder = diskExtension->TracksPerCylinder;
|
|||
|
outputBuffer->SectorsPerTrack = bios->SectorsPerTrack;
|
|||
|
outputBuffer->BytesPerSector = bios->BytesPerSector;
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
info = sizeof( DISK_GEOMETRY );
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
#if 0
|
|||
|
//
|
|||
|
// Ignore these IOCTLs for now.
|
|||
|
//
|
|||
|
case IOCTL_DISK_SET_PARTITION_INFO:
|
|||
|
case IOCTL_DISK_SET_DRIVE_LAYOUT:
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
case IOCTL_DISK_GET_PARTITION_INFO:
|
|||
|
//
|
|||
|
// Return the information about the partition.
|
|||
|
//
|
|||
|
|
|||
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION)) {
|
|||
|
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
PPARTITION_INFORMATION outputBuffer;
|
|||
|
|
|||
|
outputBuffer = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// Fat hardwired here...
|
|||
|
//
|
|||
|
outputBuffer->PartitionType = PARTITION_FAT_16;
|
|||
|
outputBuffer->BootIndicator = diskExtension->BootParameters.SystemDrive;
|
|||
|
outputBuffer->RecognizedPartition = TRUE;
|
|||
|
outputBuffer->RewritePartition = FALSE;
|
|||
|
outputBuffer->StartingOffset.QuadPart = 0;
|
|||
|
outputBuffer->PartitionLength.QuadPart = diskExtension->BootParameters.PageCount * PAGE_SIZE;
|
|||
|
outputBuffer->HiddenSectors = diskExtension->BiosParameters.HiddenSectors;
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
info = sizeof(PARTITION_INFORMATION);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
case IOCTL_DISK_VERIFY:
|
|||
|
{
|
|||
|
PVERIFY_INFORMATION verifyInformation;
|
|||
|
ULONG buflen;
|
|||
|
ULONG_PTR ioOffset;
|
|||
|
ULONG ioLength;
|
|||
|
|
|||
|
buflen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|||
|
|
|||
|
if ( buflen < sizeof(VERIFY_INFORMATION) ) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
verifyInformation = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
if (verifyInformation->StartingOffset.HighPart) {
|
|||
|
status = STATUS_DISK_CORRUPT_ERROR;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
ioOffset = verifyInformation->StartingOffset.LowPart;
|
|||
|
ioLength = verifyInformation->Length;
|
|||
|
|
|||
|
if (ioLength == 0) {
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
|
|||
|
} else if ((ioOffset | ioLength) & (diskExtension->BiosParameters.BytesPerSector - 1)) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
} else if ((ioOffset + ioLength) > (diskExtension->BootParameters.PageCount * PAGE_SIZE)) {
|
|||
|
status = STATUS_NONEXISTENT_SECTOR;
|
|||
|
|
|||
|
} else {
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IOCTL_DISK_IS_WRITABLE:
|
|||
|
status = diskExtension->BootParameters.ReadOnly? STATUS_MEDIA_WRITE_PROTECTED : STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
case IOCTL_DISK_CHECK_VERIFY:
|
|||
|
case IOCTL_STORAGE_CHECK_VERIFY:
|
|||
|
case IOCTL_STORAGE_CHECK_VERIFY2:
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//
|
|||
|
// The specified I/O control code is unrecognized by this driver.
|
|||
|
// The I/O status field in the IRP has already been set so just
|
|||
|
// terminate the switch.
|
|||
|
//
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("XIPDisk: ERROR: unrecognized IOCTL %x\n",
|
|||
|
irpSp->Parameters.DeviceIoControl.IoControlCode);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
|
|||
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
|||
|
{
|
|||
|
PMOUNTDEV_NAME mountName;
|
|||
|
ULONG outlen;
|
|||
|
|
|||
|
outlen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|||
|
|
|||
|
if ( outlen < sizeof(MOUNTDEV_NAME) ) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
mountName = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
mountName->NameLength = diskExtension->DeviceName.Length;
|
|||
|
|
|||
|
if ( outlen < mountName->NameLength + sizeof(WCHAR)) {
|
|||
|
status = STATUS_BUFFER_OVERFLOW;
|
|||
|
info = sizeof(MOUNTDEV_NAME);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory( mountName->Name, diskExtension->DeviceName.Buffer, mountName->NameLength);
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
info = mountName->NameLength + sizeof(WCHAR);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
|||
|
{
|
|||
|
PMOUNTDEV_UNIQUE_ID uniqueId;
|
|||
|
ULONG outlen;
|
|||
|
|
|||
|
outlen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|||
|
|
|||
|
if (outlen < sizeof(MOUNTDEV_UNIQUE_ID)) {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
uniqueId = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
uniqueId->UniqueIdLength = sizeof(XIPDISK_DEVICENAME);
|
|||
|
|
|||
|
if (outlen < uniqueId->UniqueIdLength) {
|
|||
|
status = STATUS_BUFFER_OVERFLOW;
|
|||
|
info = sizeof(MOUNTDEV_UNIQUE_ID);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory( uniqueId->UniqueId, XIPDISK_DEVICENAME, uniqueId->UniqueIdLength );
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
info = uniqueId->UniqueIdLength;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME:
|
|||
|
{
|
|||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Finish the I/O operation by simply completing the packet and returning
|
|||
|
// the same status as in the packet itself.
|
|||
|
// Note that IoCompleteRequest may deallocate Irp before returning.
|
|||
|
//
|
|||
|
Irp->IoStatus.Information = info;
|
|||
|
Irp->IoStatus.Status = status;
|
|||
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
XIPDiskUnloadDriver(
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by the I/O system to unload the driver.
|
|||
|
|
|||
|
Any resources previously allocated must be freed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DriverObject - a pointer to the object that represents our driver.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
|
|||
|
PXIPDISK_EXTENSION diskExtension = deviceObject->DeviceExtension;
|
|||
|
|
|||
|
RtlFreeUnicodeString(&diskExtension->InterfaceString);
|
|||
|
diskExtension->InterfaceString.Buffer = NULL;
|
|||
|
|
|||
|
if (deviceObject != NULL) {
|
|||
|
IoDeleteDevice( deviceObject );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DriverEntry(
|
|||
|
IN OUT PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
This routine is called by the Operating System to initialize the driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
DriverObject - a pointer to a device extension object for the XIPDisk driver.
|
|||
|
|
|||
|
RegistryPath - a pointer to our Services key in the registry.
|
|||
|
|
|||
|
Return Value:
|
|||
|
STATUS_SUCCESS if this disk is initialized; an error otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
XIP_BOOT_PARAMETERS xipbootparameters;
|
|||
|
PBIOS_PARAMETER_BLOCK bios;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
// UNICODE_STRING deviceName;
|
|||
|
UNICODE_STRING realDeviceName;
|
|||
|
UNICODE_STRING dosSymlink;
|
|||
|
UNICODE_STRING driveLetter;
|
|||
|
|
|||
|
PDEVICE_OBJECT pdo = NULL;
|
|||
|
PDEVICE_OBJECT deviceObject;
|
|||
|
|
|||
|
PXIPDISK_EXTENSION ext = NULL; // ptr to device extension
|
|||
|
|
|||
|
//
|
|||
|
// Read the parameters from the registry
|
|||
|
//
|
|||
|
status = XIPDispatch(XIPCMD_GETBOOTPARAMETERS, &xipbootparameters, sizeof(xipbootparameters));
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
if (xipbootparameters.BasePage == 0) {
|
|||
|
return STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
// Initialize the driver object with this driver's entry points.
|
|||
|
//
|
|||
|
|
|||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = XIPDiskCreateClose;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = XIPDiskCreateClose;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_READ] = XIPDiskReadWrite;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = XIPDiskReadWrite;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = XIPDiskDeviceControl;
|
|||
|
|
|||
|
//
|
|||
|
// Create and initialize a device object for the disk.
|
|||
|
//
|
|||
|
ObReferenceObject(DriverObject);
|
|||
|
|
|||
|
status = IoReportDetectedDevice(
|
|||
|
DriverObject,
|
|||
|
InterfaceTypeUndefined,
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
TRUE,
|
|||
|
&pdo
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create the XIP root device.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString(&realDeviceName, XIPDISK_DEVICENAME);
|
|||
|
|
|||
|
status = IoCreateDevice( DriverObject,
|
|||
|
sizeof( XIPDISK_EXTENSION ),
|
|||
|
&realDeviceName,
|
|||
|
FILE_DEVICE_VIRTUAL_DISK,
|
|||
|
0,
|
|||
|
FALSE,
|
|||
|
&deviceObject );
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
// ISSUE-2000/10/14-DavePr -- Hardwiring the driveLetter because I haven't
|
|||
|
// figured out how to get the mountmgr to give out a drive letter. Naming
|
|||
|
// it as a form of floppy (deviceName) was one suggestion that failed (so far).
|
|||
|
// The dosSymlink isn't really necessary, but is another
|
|||
|
|
|||
|
//
|
|||
|
// Create symbolic links. Ignore failures
|
|||
|
//
|
|||
|
// RtlInitUnicodeString(&deviceName, XIPDISK_FLOPPYNAME);
|
|||
|
RtlInitUnicodeString(&dosSymlink, XIPDISK_DOSNAME);
|
|||
|
RtlInitUnicodeString(&driveLetter, XIPDISK_DRIVELETTER);
|
|||
|
|
|||
|
// (void) IoCreateSymbolicLink(&deviceName, &realDeviceName);
|
|||
|
(void) IoCreateSymbolicLink(&dosSymlink, &realDeviceName);
|
|||
|
(void) IoCreateSymbolicLink(&driveLetter, &realDeviceName);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize device object and extension.
|
|||
|
//
|
|||
|
deviceObject->Flags |= DO_DIRECT_IO | DO_XIP;
|
|||
|
deviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
|||
|
|
|||
|
ext = deviceObject->DeviceExtension;
|
|||
|
|
|||
|
bios = &ext->BiosParameters;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the newly allocated disk extension from our temporary
|
|||
|
// Get the bios boot parameters from the kernel
|
|||
|
//
|
|||
|
ext->BootParameters = xipbootparameters;
|
|||
|
status = XIPDispatch(XIPCMD_GETBIOSPARAMETERS, bios, sizeof(*bios));
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the device objects
|
|||
|
//
|
|||
|
ext->DeviceObject = deviceObject;
|
|||
|
// ext->DeviceName = deviceName;
|
|||
|
ext->DeviceName = realDeviceName;
|
|||
|
|
|||
|
ext->TracksPerCylinder = 1;
|
|||
|
ext->BytesPerCylinder = bios->BytesPerSector * bios->SectorsPerTrack * ext->TracksPerCylinder;
|
|||
|
ext->NumberOfCylinders = ext->BootParameters.PageCount * PAGE_SIZE / ext->BytesPerCylinder;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Attach the root device
|
|||
|
//
|
|||
|
ext->TargetObject = IoAttachDeviceToDeviceStack(deviceObject, pdo);
|
|||
|
|
|||
|
if (!ext->TargetObject) {
|
|||
|
// IoDeleteSymbolicLink(&deviceName);
|
|||
|
IoDeleteSymbolicLink(&dosSymlink);
|
|||
|
IoDeleteSymbolicLink(&driveLetter);
|
|||
|
IoDeleteSymbolicLink(&realDeviceName);
|
|||
|
IoDeleteDevice(deviceObject);
|
|||
|
return STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
ext->UnderlyingPDO = pdo;
|
|||
|
|
|||
|
status = IoRegisterDeviceInterface(pdo,
|
|||
|
(LPGUID)&DiskClassGuid,
|
|||
|
NULL,
|
|||
|
&ext->InterfaceString );
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
status = IoSetDeviceInterfaceState( &ext->InterfaceString, TRUE );
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
DbgPrint("XIP: Warning: ignored failure %x retruned by IoSetDeviceInterface\n", status);
|
|||
|
}
|
|||
|
} else {
|
|||
|
DbgPrint("XIP: Warning: ignored failure %x retruned by IoRegisterDeviceInterface\n", status);
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|