17 #define DPRINTM2(fmt, ...) DPRINTM(DPRINT_SCSIPORT, "(%s:%d) SCSIPORT: " fmt, __FILE__, __LINE__, __VA_ARGS__)
20 #define UNIMPLEMENTED DPRINTM2("%s UNIMPLEMENTED\n", __FUNCTION__)
22 #define SCSI_PORT_NEXT_REQUEST_READY 0x0008
26 PVOID NonCachedExtension
;
33 /* SRB extension stuff */
34 ULONG SrbExtensionSize
;
35 PVOID SrbExtensionBuffer
;
37 IO_SCSI_CAPABILITIES PortCapabilities
;
39 PHW_INITIALIZE HwInitialize
;
40 PHW_STARTIO HwStartIo
;
41 PHW_INTERRUPT HwInterrupt
;
42 PHW_RESET_BUS HwResetBus
;
44 /* DMA related stuff */
45 PADAPTER_OBJECT AdapterObject
;
47 ULONG CommonBufferLength
;
49 PVOID MiniPortDeviceExtension
;
50 } SCSI_PORT_DEVICE_EXTENSION
, *PSCSI_PORT_DEVICE_EXTENSION
;
52 PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions
[SCSI_MAXIMUM_BUSES
];
59 PFOUR_BYTE Source
= (PFOUR_BYTE
)&Value
;
61 Dest
.Byte0
= Source
->Byte3
;
62 Dest
.Byte1
= Source
->Byte2
;
63 Dest
.Byte2
= Source
->Byte1
;
64 Dest
.Byte3
= Source
->Byte0
;
70 SpiSendSynchronousSrb(
71 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
72 IN PSCSI_REQUEST_BLOCK Srb
)
76 ASSERT(!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
));
78 /* HACK: handle lack of interrupts */
79 while (!(DeviceExtension
->InterruptFlags
& SCSI_PORT_NEXT_REQUEST_READY
))
81 KeStallExecutionProcessor(100 * 1000);
82 DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
);
85 DeviceExtension
->InterruptFlags
&= ~SCSI_PORT_NEXT_REQUEST_READY
;
86 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
88 if (!DeviceExtension
->HwStartIo(
89 DeviceExtension
->MiniPortDeviceExtension
,
96 /* HACK: handle lack of interrupts */
97 while (Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
)
99 KeStallExecutionProcessor(100 * 1000);
100 DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
);
103 ret
= SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
;
109 typedef struct tagDISKCONTEXT
112 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
117 /* Device characteristics */
119 ULONGLONG SectorOffset
;
120 ULONGLONG SectorCount
;
121 ULONGLONG SectorNumber
;
124 static LONG
DiskClose(ULONG FileId
)
126 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
132 static LONG
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
134 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
136 RtlZeroMemory(Information
, sizeof(FILEINFORMATION
));
137 Information
->EndingAddress
.QuadPart
= Context
->SectorCount
* Context
->SectorSize
;
138 Information
->CurrentAddress
.LowPart
= Context
->SectorNumber
* Context
->SectorSize
;
143 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
145 PSCSI_REQUEST_BLOCK Srb
;
147 READ_CAPACITY_DATA ReadCapacityBuffer
;
149 DISKCONTEXT
* Context
;
150 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
151 ULONG ScsiBus
, PathId
, TargetId
, Lun
, Partition
, PathSyntax
;
153 ULONGLONG SectorOffset
= 0;
154 ULONGLONG SectorCount
;
157 if (!DissectArcPath2(Path
, &ScsiBus
, &TargetId
, &Lun
, &Partition
, &PathSyntax
))
159 if (PathSyntax
!= 0) /* scsi() format */
161 DeviceExtension
= ScsiDeviceExtensions
[ScsiBus
];
162 PathId
= ScsiBus
- DeviceExtension
->BusNum
;
164 /* Get disk capacity and sector size */
165 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
168 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
169 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
170 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
171 Srb
->PathId
= PathId
;
172 Srb
->TargetId
= TargetId
;
175 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
176 Srb
->DataTransferLength
= sizeof(READ_CAPACITY_DATA
);
177 Srb
->TimeOutValue
= 5; /* in seconds */
178 Srb
->DataBuffer
= &ReadCapacityBuffer
;
179 Cdb
= (PCDB
)Srb
->Cdb
;
180 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
181 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
186 /* Transform result to host endianness */
187 SectorCount
= ntohl(ReadCapacityBuffer
.LogicalBlockAddress
);
188 SectorSize
= ntohl(ReadCapacityBuffer
.BytesPerBlock
);
192 /* Need to offset start of disk and length */
197 Context
= ExAllocatePool(PagedPool
, sizeof(DISKCONTEXT
));
200 Context
->DeviceExtension
= DeviceExtension
;
201 Context
->PathId
= PathId
;
202 Context
->TargetId
= TargetId
;
204 Context
->SectorSize
= SectorSize
;
205 Context
->SectorOffset
= SectorOffset
;
206 Context
->SectorCount
= SectorCount
;
207 Context
->SectorNumber
= 0;
208 FsSetDeviceSpecific(*FileId
, Context
);
213 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
215 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
216 PSCSI_REQUEST_BLOCK Srb
;
218 ULONG FullSectors
, NbSectors
;
226 FullSectors
= N
/ Context
->SectorSize
;
227 NbSectors
= (N
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
228 if (Context
->SectorNumber
+ NbSectors
>= Context
->SectorCount
)
230 if (FullSectors
> 0xffff)
233 /* Read full sectors */
234 Lba
= Context
->SectorNumber
;
237 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
241 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
242 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
243 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
244 Srb
->PathId
= Context
->PathId
;
245 Srb
->TargetId
= Context
->TargetId
;
246 Srb
->Lun
= Context
->Lun
;
248 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
249 Srb
->DataTransferLength
= FullSectors
* Context
->SectorSize
;
250 Srb
->TimeOutValue
= 5; /* in seconds */
251 Srb
->DataBuffer
= Buffer
;
252 Cdb
= (PCDB
)Srb
->Cdb
;
253 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
254 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
255 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
256 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
257 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
258 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
259 Cdb
->CDB10
.TransferBlocksMsb
= (FullSectors
>> 8) & 0xff;
260 Cdb
->CDB10
.TransferBlocksLsb
= FullSectors
& 0xff;
261 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
265 Buffer
= (PUCHAR
)Buffer
+ FullSectors
* Context
->SectorSize
;
266 N
-= FullSectors
* Context
->SectorSize
;
267 *Count
+= FullSectors
* Context
->SectorSize
;
271 /* Read incomplete last sector */
276 Sector
= ExAllocatePool(PagedPool
, Context
->SectorSize
);
280 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
287 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
288 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
289 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
290 Srb
->PathId
= Context
->PathId
;
291 Srb
->TargetId
= Context
->TargetId
;
292 Srb
->Lun
= Context
->Lun
;
294 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
295 Srb
->DataTransferLength
= Context
->SectorSize
;
296 Srb
->TimeOutValue
= 5; /* in seconds */
297 Srb
->DataBuffer
= Sector
;
298 Cdb
= (PCDB
)Srb
->Cdb
;
299 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
300 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
301 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
302 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
303 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
304 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
305 Cdb
->CDB10
.TransferBlocksMsb
= 0;
306 Cdb
->CDB10
.TransferBlocksLsb
= 1;
307 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
312 RtlCopyMemory(Buffer
, Sector
, N
);
320 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
322 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
324 if (SeekMode
!= SeekAbsolute
)
326 if (Position
->QuadPart
& (Context
->SectorSize
- 1))
329 Context
->SectorNumber
= Position
->QuadPart
/ Context
->SectorSize
;
333 static const DEVVTBL DiskVtbl
= {
335 DiskGetFileInformation
,
343 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
344 IN PHW_INITIALIZATION_DATA HwInitData
,
345 OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
346 IN BOOLEAN ZeroStruct
)
350 /* Zero out the struct if told so */
353 /* First zero the portconfig */
354 RtlZeroMemory(ConfigInfo
, sizeof(PORT_CONFIGURATION_INFORMATION
));
356 /* Initialize the struct */
357 ConfigInfo
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
358 ConfigInfo
->AdapterInterfaceType
= HwInitData
->AdapterInterfaceType
;
359 ConfigInfo
->InterruptMode
= Latched
;
360 ConfigInfo
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
361 ConfigInfo
->DmaPort
= SP_UNINITIALIZED_VALUE
;
362 ConfigInfo
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
363 ConfigInfo
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
365 /* Store parameters */
366 ConfigInfo
->NeedPhysicalAddresses
= HwInitData
->NeedPhysicalAddresses
;
367 ConfigInfo
->MapBuffers
= HwInitData
->MapBuffers
;
368 ConfigInfo
->AutoRequestSense
= HwInitData
->AutoRequestSense
;
369 ConfigInfo
->ReceiveEvent
= HwInitData
->ReceiveEvent
;
370 ConfigInfo
->TaggedQueuing
= HwInitData
->TaggedQueuing
;
371 ConfigInfo
->MultipleRequestPerLu
= HwInitData
->MultipleRequestPerLu
;
373 /* Get the disk usage */
374 ConfigInfo
->AtdiskPrimaryClaimed
= FALSE
; // FIXME
375 ConfigInfo
->AtdiskSecondaryClaimed
= FALSE
; // FIXME
377 /* Initiator bus id is not set */
378 for (Bus
= 0; Bus
< 8; Bus
++)
379 ConfigInfo
->InitiatorBusId
[Bus
] = (CCHAR
)SP_UNINITIALIZED_VALUE
;
382 ConfigInfo
->NumberOfPhysicalBreaks
= 17;
384 return STATUS_SUCCESS
;
390 IN ULONG DebugPrintLevel
,
391 IN PCCHAR DebugMessage
,
398 if (DebugPrintLevel
> 10)
401 va_start(ap
, DebugMessage
);
403 /* Construct a string */
404 Length
= _vsnprintf(Buffer
, 512, DebugMessage
, ap
);
406 /* Check if we went past the buffer */
407 if (Length
== MAXULONG
)
409 /* Terminate it if we went over-board */
410 Buffer
[sizeof(Buffer
) - 1] = '\0';
413 Length
= sizeof(Buffer
);
416 /* Print the message */
417 DPRINTM(DPRINT_SCSIPORT
, "%s", Buffer
);
425 ScsiPortCompleteRequest(
426 IN PVOID HwDeviceExtension
,
436 #undef ScsiPortConvertPhysicalAddressToUlong
439 ScsiPortConvertPhysicalAddressToUlong(
440 IN SCSI_PHYSICAL_ADDRESS Address
)
442 return Address
.LowPart
;
445 SCSI_PHYSICAL_ADDRESS
447 ScsiPortConvertUlongToPhysicalAddress(
448 IN ULONG UlongAddress
)
450 return RtlConvertUlongToLargeInteger(UlongAddress
);
456 IN PVOID DeviceExtension
)
464 ScsiPortFreeDeviceBase(
465 IN PVOID HwDeviceExtension
,
466 IN PVOID MappedAddress
)
474 IN PVOID DeviceExtension
,
475 IN ULONG BusDataType
,
476 IN ULONG SystemIoBusNumber
,
481 return HalGetBusDataByOffset(BusDataType
, SystemIoBusNumber
, SlotNumber
, Buffer
, 0, Length
);
486 ScsiPortGetDeviceBase(
487 IN PVOID HwDeviceExtension
,
488 IN INTERFACE_TYPE BusType
,
489 IN ULONG SystemIoBusNumber
,
490 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
491 IN ULONG NumberOfBytes
,
492 IN BOOLEAN InIoSpace
)
494 PHYSICAL_ADDRESS TranslatedAddress
;
497 AddressSpace
= (ULONG
)InIoSpace
;
498 if (HalTranslateBusAddress(BusType
,
502 &TranslatedAddress
) == FALSE
)
508 if (AddressSpace
!= 0)
509 return (PVOID
)TranslatedAddress
.u
.LowPart
;
513 return (PVOID
)IoAddress
.LowPart
;
518 ScsiPortGetLogicalUnit(
519 IN PVOID HwDeviceExtension
,
529 SCSI_PHYSICAL_ADDRESS
531 ScsiPortGetPhysicalAddress(
532 IN PVOID HwDeviceExtension
,
533 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
534 IN PVOID VirtualAddress
,
537 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
538 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
539 ULONG BufferLength
= 0;
542 DPRINTM2("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
543 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
545 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
547 if (Srb
== NULL
|| Srb
->SenseInfoBuffer
== VirtualAddress
)
549 /* Simply look it up in the allocated common buffer */
550 Offset
= (PUCHAR
)VirtualAddress
- (PUCHAR
)DeviceExtension
->SrbExtensionBuffer
;
552 BufferLength
= DeviceExtension
->CommonBufferLength
- Offset
;
553 PhysicalAddress
.QuadPart
= Offset
;
559 PhysicalAddress
.QuadPart
= (LONGLONG
)(SP_UNINITIALIZED_VALUE
);
562 *Length
= BufferLength
;
563 return PhysicalAddress
;
569 IN PVOID DeviceExtension
,
581 SpiAllocateCommonBuffer(
582 IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
583 IN ULONG NonCachedSize
)
586 ULONG CommonBufferLength
, BufSize
;
588 /* If size is 0, set it to 16 */
589 if (!DeviceExtension
->SrbExtensionSize
)
590 DeviceExtension
->SrbExtensionSize
= 16;
593 BufSize
= DeviceExtension
->SrbExtensionSize
;
596 BufSize
= (BufSize
+ sizeof(LONGLONG
) - 1) & ~(sizeof(LONGLONG
) - 1);
598 /* Sum up into the total common buffer length, and round it to page size */
600 ROUND_TO_PAGES(NonCachedSize
);
603 if (!DeviceExtension
->AdapterObject
)
605 /* From nonpaged pool if there is no DMA */
606 CommonBuffer
= ExAllocatePool(NonPagedPool
, CommonBufferLength
);
610 /* Perform a full request since we have a DMA adapter*/
615 /* Fail in case of error */
617 return STATUS_INSUFFICIENT_RESOURCES
;
620 RtlZeroMemory(CommonBuffer
, CommonBufferLength
);
622 /* Store its size in Device Extension */
623 DeviceExtension
->CommonBufferLength
= CommonBufferLength
;
625 /* SrbExtension buffer is located at the beginning of the buffer */
626 DeviceExtension
->SrbExtensionBuffer
= CommonBuffer
;
628 /* Non-cached extension buffer is located at the end of
632 CommonBufferLength
-= NonCachedSize
;
633 DeviceExtension
->NonCachedExtension
= (PUCHAR
)CommonBuffer
+ CommonBufferLength
;
637 DeviceExtension
->NonCachedExtension
= NULL
;
640 return STATUS_SUCCESS
;
645 ScsiPortGetUncachedExtension(
646 IN PVOID HwDeviceExtension
,
647 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
648 IN ULONG NumberOfBytes
)
650 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
651 DEVICE_DESCRIPTION DeviceDescription
;
652 ULONG MapRegistersCount
;
655 DPRINTM2("ScsiPortGetUncachedExtension(%p %p %lu)\n",
656 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
658 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
660 /* Check for allocated common DMA buffer */
661 if (DeviceExtension
->SrbExtensionBuffer
!= NULL
)
666 /* Check for DMA adapter object */
667 if (DeviceExtension
->AdapterObject
== NULL
)
669 /* Initialize DMA adapter description */
670 RtlZeroMemory(&DeviceDescription
, sizeof(DEVICE_DESCRIPTION
));
672 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
673 DeviceDescription
.Master
= ConfigInfo
->Master
;
674 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
675 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
676 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
677 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
678 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
679 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
680 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
681 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
682 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
683 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
685 /* Get a DMA adapter object */
687 DeviceExtension
->AdapterObject
=
688 HalGetAdapter(&DeviceDescription
, &MapRegistersCount
);
690 /* Fail in case of error */
691 if (DeviceExtension
->AdapterObject
== NULL
)
696 MapRegistersCount
= 0;
699 /* Set number of physical breaks */
700 if (ConfigInfo
->NumberOfPhysicalBreaks
!= 0 &&
701 MapRegistersCount
> ConfigInfo
->NumberOfPhysicalBreaks
)
703 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
=
704 ConfigInfo
->NumberOfPhysicalBreaks
;
708 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
= MapRegistersCount
;
712 /* Update Srb extension size */
713 if (DeviceExtension
->SrbExtensionSize
!= ConfigInfo
->SrbExtensionSize
)
714 DeviceExtension
->SrbExtensionSize
= ConfigInfo
->SrbExtensionSize
;
716 /* Allocate a common DMA buffer */
717 Status
= SpiAllocateCommonBuffer(DeviceExtension
, NumberOfBytes
);
719 if (!NT_SUCCESS(Status
))
721 DPRINTM2("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status
);
725 return DeviceExtension
->NonCachedExtension
;
730 ScsiPortGetVirtualAddress(
731 IN PVOID HwDeviceExtension
,
732 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
741 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
750 struct _DRIVE_LAYOUT_INFORMATION
*PartitionBuffer
;
751 CHAR PartitionName
[64];
753 /* Register device with partition(0) suffix */
754 sprintf(PartitionName
, "%spartition(0)", ArcName
);
755 FsRegisterDevice(PartitionName
, &DiskVtbl
);
757 /* Read device partition table */
758 Status
= ArcOpen(PartitionName
, OpenReadOnly
, &FileId
);
759 if (Status
== ESUCCESS
)
761 ret
= HALDISPATCH
->HalIoReadPartitionTable((PDEVICE_OBJECT
)FileId
, 512, FALSE
, &PartitionBuffer
);
764 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
++)
766 if (PartitionBuffer
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
768 sprintf(PartitionName
, "%spartition(%lu)",
769 ArcName
, PartitionBuffer
->PartitionEntry
[i
].PartitionNumber
);
770 FsRegisterDevice(PartitionName
, &DiskVtbl
);
773 ExFreePool(PartitionBuffer
);
781 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
786 PSCSI_REQUEST_BLOCK Srb
;
788 INQUIRYDATA InquiryBuffer
;
792 if (!DeviceExtension
->HwResetBus(DeviceExtension
->MiniPortDeviceExtension
, PathId
))
797 /* Remember the extension */
798 ScsiDeviceExtensions
[ScsiBus
] = DeviceExtension
;
800 for (TargetId
= 0; TargetId
< DeviceExtension
->MaxTargedIds
; TargetId
++)
805 DPRINTM2("Scanning SCSI device %d.%d.%d\n",
806 ScsiBus
, TargetId
, Lun
);
808 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
811 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
812 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
813 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
814 Srb
->PathId
= PathId
;
815 Srb
->TargetId
= TargetId
;
818 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
819 Srb
->DataTransferLength
= INQUIRYDATABUFFERSIZE
;
820 Srb
->TimeOutValue
= 5; /* in seconds */
821 Srb
->DataBuffer
= &InquiryBuffer
;
822 Cdb
= (PCDB
)Srb
->Cdb
;
823 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
824 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= Srb
->Lun
;
825 Cdb
->CDB6INQUIRY
.AllocationLength
= Srb
->DataTransferLength
;
826 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
828 /* Don't check next LUNs */
832 /* Device exists, create its ARC name */
833 if (InquiryBuffer
.RemovableMedia
)
835 sprintf(ArcName
, "scsi(%ld)cdrom(%ld)fdisk(%ld)",
836 ScsiBus
, TargetId
, Lun
);
837 FsRegisterDevice(ArcName
, &DiskVtbl
);
841 sprintf(ArcName
, "scsi(%ld)disk(%ld)rdisk(%ld)",
842 ScsiBus
, TargetId
, Lun
);
843 /* Now, check if it has partitions */
844 SpiScanDevice(DeviceExtension
, ArcName
, PathId
, TargetId
, Lun
);
849 } while (Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
);
855 IN PHW_INITIALIZATION_DATA HwInitializationData
,
856 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
,
857 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
)
859 PACCESS_RANGE AccessRange
;
860 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData
;
866 /* Loop through all entries */
867 for (Index
= 0; Index
< ResourceDescriptor
->PartialResourceList
.Count
; Index
++)
869 PartialData
= &ResourceDescriptor
->PartialResourceList
.PartialDescriptors
[Index
];
871 switch (PartialData
->Type
)
873 case CmResourceTypePort
:
874 /* Copy access ranges */
875 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
877 DPRINTM2("Got port at 0x%I64x, len 0x%x\n",
878 PartialData
->u
.Port
.Start
.QuadPart
, PartialData
->u
.Port
.Length
);
879 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
881 AccessRange
->RangeStart
= PartialData
->u
.Port
.Start
;
882 AccessRange
->RangeLength
= PartialData
->u
.Port
.Length
;
884 AccessRange
->RangeInMemory
= FALSE
;
889 case CmResourceTypeMemory
:
890 /* Copy access ranges */
891 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
893 DPRINTM2("Got memory at 0x%I64x, len 0x%x\n",
894 PartialData
->u
.Memory
.Start
.QuadPart
, PartialData
->u
.Memory
.Length
);
895 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
897 AccessRange
->RangeStart
= PartialData
->u
.Memory
.Start
;
898 AccessRange
->RangeLength
= PartialData
->u
.Memory
.Length
;
900 AccessRange
->RangeInMemory
= TRUE
;
905 case CmResourceTypeInterrupt
:
906 /* Copy interrupt data */
907 DPRINTM2("Got interrupt level %d, vector %d\n",
908 PartialData
->u
.Interrupt
.Level
, PartialData
->u
.Interrupt
.Vector
);
909 PortConfig
->BusInterruptLevel
= PartialData
->u
.Interrupt
.Level
;
910 PortConfig
->BusInterruptVector
= PartialData
->u
.Interrupt
.Vector
;
912 /* Set interrupt mode accordingly to the resource */
913 if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
915 PortConfig
->InterruptMode
= Latched
;
917 else if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
919 PortConfig
->InterruptMode
= LevelSensitive
;
923 case CmResourceTypeDma
:
924 DPRINTM2("Got DMA channel %d, port %d\n",
925 PartialData
->u
.Dma
.Channel
, PartialData
->u
.Dma
.Port
);
926 PortConfig
->DmaChannel
= PartialData
->u
.Dma
.Channel
;
927 PortConfig
->DmaPort
= PartialData
->u
.Dma
.Port
;
935 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
936 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
938 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
940 PCI_COMMON_CONFIG PciConfig
;
941 PCI_SLOT_NUMBER SlotNumber
;
944 ULONG FunctionNumber
;
945 CHAR VendorIdString
[8];
946 CHAR DeviceIdString
[8];
947 PCM_RESOURCE_LIST ResourceList
;
950 RtlZeroMemory(&ResourceList
, sizeof(PCM_RESOURCE_LIST
));
951 SlotNumber
.u
.AsULONG
= 0;
953 /* Loop through all devices */
954 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
956 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
958 /* Loop through all functions */
959 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
961 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
963 /* Get PCI config bytes */
964 DataSize
= HalGetBusDataByOffset(
967 SlotNumber
.u
.AsULONG
,
972 /* If result of HalGetBusData is 0, then the bus is wrong */
976 /* If result is PCI_INVALID_VENDORID, then this device has no more
978 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
981 sprintf(VendorIdString
, "%04hx", PciConfig
.VendorID
);
982 sprintf(DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
984 if (_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) ||
985 _strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
987 /* It is not our device */
991 DPRINTM2( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
992 PciConfig
.VendorID
, PciConfig
.DeviceID
,
994 SlotNumber
.u
.bits
.DeviceNumber
, SlotNumber
.u
.bits
.FunctionNumber
);
996 Status
= HalAssignSlotResources(NULL
,
1002 SlotNumber
.u
.AsULONG
,
1005 if (!NT_SUCCESS(Status
))
1008 /* Create configuration information */
1009 SpiResourceToConfig(HwInitializationData
,
1013 /* Free the resource list */
1014 ExFreePool(ResourceList
);
1016 /* Set dev & fn numbers */
1017 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1018 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
+ 1;
1020 /* Save the slot number */
1021 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1025 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1028 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1038 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1039 IN PVOID HwContext OPTIONAL
)
1041 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1042 ULONG DeviceExtensionSize
;
1043 PORT_CONFIGURATION_INFORMATION PortConfig
;
1045 BOOLEAN FirstConfigCall
= TRUE
;
1046 PCI_SLOT_NUMBER SlotNumber
;
1049 if (HwInitializationData
->HwInitializationDataSize
!= sizeof(HW_INITIALIZATION_DATA
))
1051 return STATUS_INVALID_PARAMETER
;
1054 /* Check params for validity */
1055 if ((HwInitializationData
->HwInitialize
== NULL
) ||
1056 (HwInitializationData
->HwStartIo
== NULL
) ||
1057 (HwInitializationData
->HwInterrupt
== NULL
) ||
1058 (HwInitializationData
->HwFindAdapter
== NULL
) ||
1059 (HwInitializationData
->HwResetBus
== NULL
))
1061 return STATUS_INVALID_PARAMETER
;
1064 /* Zero starting slot number */
1065 SlotNumber
.u
.AsULONG
= 0;
1071 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) + HwInitializationData
->DeviceExtensionSize
;
1072 DeviceExtension
= MmHeapAlloc(DeviceExtensionSize
);
1073 if (!DeviceExtension
)
1075 return STATUS_NO_MEMORY
;
1077 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
1078 DeviceExtension
->InterruptFlags
= SCSI_PORT_NEXT_REQUEST_READY
;
1079 DeviceExtension
->HwInitialize
= HwInitializationData
->HwInitialize
;
1080 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
1081 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
1082 DeviceExtension
->HwResetBus
= HwInitializationData
->HwResetBus
;
1083 DeviceExtension
->MiniPortDeviceExtension
= (PVOID
)(DeviceExtension
+ 1);
1085 Status
= SpiCreatePortConfig(DeviceExtension
,
1086 HwInitializationData
,
1089 if (Status
!= STATUS_SUCCESS
)
1091 MmHeapFree(DeviceExtension
);
1095 PortConfig
.NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
1096 PortConfig
.AccessRanges
= MmHeapAlloc(sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1097 if (!PortConfig
.AccessRanges
)
1099 MmHeapFree(DeviceExtension
);
1100 return STATUS_NO_MEMORY
;
1102 RtlZeroMemory(PortConfig
.AccessRanges
, sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1104 /* Search for matching PCI device */
1105 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
1106 (HwInitializationData
->VendorIdLength
> 0) &&
1107 (HwInitializationData
->VendorId
!= NULL
) &&
1108 (HwInitializationData
->DeviceIdLength
> 0) &&
1109 (HwInitializationData
->DeviceId
!= NULL
))
1111 PortConfig
.BusInterruptLevel
= 0;
1113 /* Get PCI device data */
1114 DPRINTM2("VendorId '%.*s' DeviceId '%.*s'\n",
1115 HwInitializationData
->VendorIdLength
,
1116 HwInitializationData
->VendorId
,
1117 HwInitializationData
->DeviceIdLength
,
1118 HwInitializationData
->DeviceId
);
1120 if (!SpiGetPciConfigData(HwInitializationData
,
1125 /* Continue to the next bus, nothing here */
1126 MmHeapFree(DeviceExtension
);
1127 return STATUS_INTERNAL_ERROR
;
1130 if (!PortConfig
.BusInterruptLevel
)
1132 /* Bypass this slot, because no interrupt was assigned */
1133 MmHeapFree(DeviceExtension
);
1134 return STATUS_INTERNAL_ERROR
;
1138 if (HwInitializationData
->HwFindAdapter(
1139 DeviceExtension
->MiniPortDeviceExtension
,
1144 &Again
) != SP_RETURN_FOUND
)
1146 MmHeapFree(DeviceExtension
);
1147 return STATUS_INTERNAL_ERROR
;
1150 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1151 if (PortConfig
.MaximumNumberOfTargets
> SCSI_MAXIMUM_TARGETS_PER_BUS
)
1152 DeviceExtension
->MaxTargedIds
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
1154 DeviceExtension
->MaxTargedIds
= PortConfig
.MaximumNumberOfTargets
;
1156 DeviceExtension
->BusNum
= PortConfig
.SystemIoBusNumber
;
1158 DPRINTM2("Adapter found: buses = %d, targets = %d\n",
1159 PortConfig
.NumberOfBuses
, DeviceExtension
->MaxTargedIds
);
1161 /* Initialize adapter */
1162 if (!DeviceExtension
->HwInitialize(DeviceExtension
->MiniPortDeviceExtension
))
1164 MmHeapFree(DeviceExtension
);
1165 return STATUS_INTERNAL_ERROR
;
1171 for (ScsiBus
= 0; ScsiBus
< PortConfig
.NumberOfBuses
; ScsiBus
++)
1173 SpiScanAdapter(DeviceExtension
, PortConfig
.SystemIoBusNumber
, ScsiBus
);
1174 PortConfig
.SystemIoBusNumber
++;
1178 FirstConfigCall
= FALSE
;
1185 return STATUS_SUCCESS
;
1190 ScsiPortIoMapTransfer(
1191 IN PVOID HwDeviceExtension
,
1192 IN PSCSI_REQUEST_BLOCK Srb
,
1193 IN PVOID LogicalAddress
,
1203 IN PVOID HwDeviceExtension
,
1204 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1218 IN PVOID WriteBuffer
,
1219 IN PVOID ReadBuffer
,
1222 RtlMoveMemory(WriteBuffer
, ReadBuffer
, Length
);
1227 ScsiPortNotification(
1228 IN SCSI_NOTIFICATION_TYPE NotificationType
,
1229 IN PVOID HwDeviceExtension
,
1232 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1233 PSCSI_REQUEST_BLOCK Srb
;
1236 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
1238 va_start(ap
, HwDeviceExtension
);
1240 switch (NotificationType
)
1242 case RequestComplete
:
1243 /* Mask the SRB as completed */
1244 Srb
= va_arg(ap
, PSCSI_REQUEST_BLOCK
);
1245 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1249 /* Say that device is ready */
1250 DeviceExtension
->InterruptFlags
|= SCSI_PORT_NEXT_REQUEST_READY
;
1263 ScsiPortReadPortBufferUchar(
1268 __inbytestring(H2I(Port
), Buffer
, Count
);
1273 ScsiPortReadPortBufferUlong(
1278 __indwordstring(H2I(Port
), Buffer
, Count
);
1283 ScsiPortReadPortBufferUshort(
1288 __inwordstring(H2I(Port
), Buffer
, Count
);
1293 ScsiPortReadPortUchar(
1296 DPRINTM2("ScsiPortReadPortUchar(%p)\n",
1299 return READ_PORT_UCHAR(Port
);
1304 ScsiPortReadPortUlong(
1307 return READ_PORT_ULONG(Port
);
1312 ScsiPortReadPortUshort(
1315 return READ_PORT_USHORT(Port
);
1320 ScsiPortReadRegisterBufferUchar(
1331 ScsiPortReadRegisterBufferUlong(
1342 ScsiPortReadRegisterBufferUshort(
1343 IN PUSHORT Register
,
1353 ScsiPortReadRegisterUchar(
1356 return READ_REGISTER_UCHAR(Register
);
1361 ScsiPortReadRegisterUlong(
1364 return READ_REGISTER_ULONG(Register
);
1369 ScsiPortReadRegisterUshort(
1370 IN PUSHORT Register
)
1372 return READ_REGISTER_USHORT(Register
);
1377 ScsiPortSetBusDataByOffset(
1378 IN PVOID DeviceExtension
,
1379 IN ULONG BusDataType
,
1380 IN ULONG SystemIoBusNumber
,
1381 IN ULONG SlotNumber
,
1393 ScsiPortStallExecution(
1396 KeStallExecutionProcessor(Delay
);
1401 ScsiPortValidateRange(
1402 IN PVOID HwDeviceExtension
,
1403 IN INTERFACE_TYPE BusType
,
1404 IN ULONG SystemIoBusNumber
,
1405 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1406 IN ULONG NumberOfBytes
,
1407 IN BOOLEAN InIoSpace
)
1421 ScsiPortWritePortBufferUchar(
1426 __outbytestring(H2I(Port
), Buffer
, Count
);
1431 ScsiPortWritePortBufferUlong(
1436 __outdwordstring(H2I(Port
), Buffer
, Count
);
1441 ScsiPortWritePortBufferUshort(
1446 __outwordstring(H2I(Port
), Buffer
, Count
);
1451 ScsiPortWritePortUchar(
1455 WRITE_PORT_UCHAR(Port
, Value
);
1460 ScsiPortWritePortUlong(
1464 WRITE_PORT_ULONG(Port
, Value
);
1469 ScsiPortWritePortUshort(
1473 WRITE_PORT_USHORT(Port
, Value
);
1478 ScsiPortWriteRegisterBufferUchar(
1489 ScsiPortWriteRegisterBufferUlong(
1500 ScsiPortWriteRegisterBufferUshort(
1501 IN PUSHORT Register
,
1511 ScsiPortWriteRegisterUchar(
1515 WRITE_REGISTER_UCHAR(Register
, Value
);
1520 ScsiPortWriteRegisterUlong(
1524 WRITE_REGISTER_ULONG(Register
, Value
);
1529 ScsiPortWriteRegisterUshort(
1530 IN PUSHORT Register
,
1533 WRITE_REGISTER_USHORT(Register
, Value
);
1537 LoadBootDeviceDriver(VOID
)
1545 { "ScsiDebugPrint", ScsiDebugPrint
},
1546 { "ScsiPortCompleteRequest", ScsiPortCompleteRequest
},
1547 { "ScsiPortConvertPhysicalAddressToUlong", ScsiPortConvertPhysicalAddressToUlong
},
1548 { "ScsiPortConvertUlongToPhysicalAddress", ScsiPortConvertUlongToPhysicalAddress
},
1549 { "ScsiPortFlushDma", ScsiPortFlushDma
},
1550 { "ScsiPortFreeDeviceBase", ScsiPortFreeDeviceBase
},
1551 { "ScsiPortGetBusData", ScsiPortGetBusData
},
1552 { "ScsiPortGetDeviceBase", ScsiPortGetDeviceBase
},
1553 { "ScsiPortGetLogicalUnit", ScsiPortGetLogicalUnit
},
1554 { "ScsiPortGetPhysicalAddress", ScsiPortGetPhysicalAddress
},
1555 { "ScsiPortGetSrb", ScsiPortGetSrb
},
1556 { "ScsiPortGetUncachedExtension", ScsiPortGetUncachedExtension
},
1557 { "ScsiPortGetVirtualAddress", ScsiPortGetVirtualAddress
},
1558 { "ScsiPortInitialize", ScsiPortInitialize
},
1559 { "ScsiPortIoMapTransfer", ScsiPortIoMapTransfer
},
1560 { "ScsiPortLogError", ScsiPortLogError
},
1561 { "ScsiPortMoveMemory", ScsiPortMoveMemory
},
1562 { "ScsiPortNotification", ScsiPortNotification
},
1563 { "ScsiPortReadPortBufferUchar", ScsiPortReadPortBufferUchar
},
1564 { "ScsiPortReadPortBufferUlong", ScsiPortReadPortBufferUlong
},
1565 { "ScsiPortReadPortBufferUshort", ScsiPortReadPortBufferUshort
},
1566 { "ScsiPortReadPortUchar", ScsiPortReadPortUchar
},
1567 { "ScsiPortReadPortUlong", ScsiPortReadPortUlong
},
1568 { "ScsiPortReadPortUshort", ScsiPortReadPortUshort
},
1569 { "ScsiPortReadRegisterBufferUchar", ScsiPortReadRegisterBufferUchar
},
1570 { "ScsiPortReadRegisterBufferUlong", ScsiPortReadRegisterBufferUlong
},
1571 { "ScsiPortReadRegisterBufferUshort", ScsiPortReadRegisterBufferUshort
},
1572 { "ScsiPortReadRegisterUchar", ScsiPortReadRegisterUchar
},
1573 { "ScsiPortReadRegisterUlong", ScsiPortReadRegisterUlong
},
1574 { "ScsiPortReadRegisterUshort", ScsiPortReadRegisterUshort
},
1575 { "ScsiPortSetBusDataByOffset", ScsiPortSetBusDataByOffset
},
1576 { "ScsiPortStallExecution", ScsiPortStallExecution
},
1577 { "ScsiPortValidateRange", ScsiPortValidateRange
},
1578 { "ScsiPortWritePortBufferUchar", ScsiPortWritePortBufferUchar
},
1579 { "ScsiPortWritePortBufferUlong", ScsiPortWritePortBufferUlong
},
1580 { "ScsiPortWritePortBufferUshort", ScsiPortWritePortBufferUshort
},
1581 { "ScsiPortWritePortUchar", ScsiPortWritePortUchar
},
1582 { "ScsiPortWritePortUlong", ScsiPortWritePortUlong
},
1583 { "ScsiPortWritePortUshort", ScsiPortWritePortUshort
},
1584 { "ScsiPortWriteRegisterBufferUchar", ScsiPortWriteRegisterBufferUchar
},
1585 { "ScsiPortWriteRegisterBufferUlong", ScsiPortWriteRegisterBufferUlong
},
1586 { "ScsiPortWriteRegisterBufferUshort", ScsiPortWriteRegisterBufferUshort
},
1587 { "ScsiPortWriteRegisterUchar", ScsiPortWriteRegisterUchar
},
1588 { "ScsiPortWriteRegisterUlong", ScsiPortWriteRegisterUlong
},
1589 { "ScsiPortWriteRegisterUshort", ScsiPortWriteRegisterUshort
},
1591 IMAGE_DOS_HEADER ImageDosHeader
;
1592 IMAGE_NT_HEADERS ImageNtHeaders
;
1593 IMAGE_EXPORT_DIRECTORY ImageExportDirectory
;
1594 CHAR
* TableName
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1595 USHORT OrdinalTable
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1596 ULONG FunctionTable
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1598 PIMAGE_NT_HEADERS NtHeaders
;
1599 LOADER_PARAMETER_BLOCK LoaderBlock
;
1600 PIMAGE_IMPORT_DESCRIPTOR ImportTable
;
1601 ULONG ImportTableSize
;
1602 PLDR_DATA_TABLE_ENTRY BootDdDTE
, FreeldrDTE
;
1603 CHAR NtBootDdPath
[MAX_PATH
];
1605 ULONG (NTAPI
*EntryPoint
)(IN PVOID DriverObject
, IN PVOID RegistryPath
);
1609 /* Some initialization of our temporary loader block */
1610 RtlZeroMemory(&LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
1611 InitializeListHead(&LoaderBlock
.LoadOrderListHead
);
1613 /* Create our fake executable header for freeldr.sys */
1614 RtlZeroMemory(&ImageDosHeader
, sizeof(IMAGE_DOS_HEADER
));
1615 RtlZeroMemory(&ImageNtHeaders
, sizeof(IMAGE_NT_HEADERS
));
1616 RtlZeroMemory(&ImageExportDirectory
, sizeof(IMAGE_EXPORT_DIRECTORY
));
1617 ImageDosHeader
.e_magic
= SWAPW(IMAGE_DOS_SIGNATURE
);
1618 ImageDosHeader
.e_lfanew
= SWAPD((ULONG_PTR
)&ImageNtHeaders
- (ULONG_PTR
)&ImageDosHeader
);
1619 ImageNtHeaders
.Signature
= IMAGE_NT_SIGNATURE
;
1620 ImageNtHeaders
.OptionalHeader
.NumberOfRvaAndSizes
= SWAPD(IMAGE_DIRECTORY_ENTRY_EXPORT
+ 1);
1621 ImageNtHeaders
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
=
1622 SWAPW((ULONG_PTR
)&ImageExportDirectory
- (ULONG_PTR
)&ImageDosHeader
);
1623 ImageNtHeaders
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
= 1;
1624 ImageExportDirectory
.NumberOfNames
= sizeof(ExportTable
) / sizeof(ExportTable
[0]);
1625 ImageExportDirectory
.AddressOfNames
= (ULONG_PTR
)TableName
- (ULONG_PTR
)&ImageDosHeader
;
1626 ImageExportDirectory
.AddressOfNameOrdinals
= (ULONG_PTR
)OrdinalTable
- (ULONG_PTR
)&ImageDosHeader
;
1627 ImageExportDirectory
.NumberOfFunctions
= sizeof(ExportTable
) / sizeof(ExportTable
[0]);
1628 ImageExportDirectory
.AddressOfFunctions
= (ULONG_PTR
)FunctionTable
- (ULONG_PTR
)&ImageDosHeader
;
1630 /* Fill freeldr.sys export table */
1631 for (i
= 0; i
< sizeof(ExportTable
) / sizeof(ExportTable
[0]); i
++)
1633 TableName
[i
] = PaToVa((PVOID
)((ULONG_PTR
)ExportTable
[i
].Name
- (ULONG_PTR
)&ImageDosHeader
));
1634 OrdinalTable
[i
] = i
;
1635 FunctionTable
[i
] = (ULONG
)((ULONG_PTR
)ExportTable
[i
].Function
- (ULONG_PTR
)&ImageDosHeader
);
1638 /* Add freeldr.sys to list of loaded executables */
1639 Status
= WinLdrAllocateDataTableEntry(&LoaderBlock
, "scsiport.sys",
1640 "FREELDR.SYS", &ImageDosHeader
, &FreeldrDTE
);
1644 /* Create full ntbootdd.sys path */
1645 MachDiskGetBootPath(NtBootDdPath
, sizeof(NtBootDdPath
));
1646 strcat(NtBootDdPath
, "\\NTBOOTDD.SYS");
1649 Status
= WinLdrLoadImage(NtBootDdPath
, LoaderBootDriver
, &ImageBase
);
1652 /* That's OK. File simply doesn't exist */
1657 Status
= WinLdrAllocateDataTableEntry(&LoaderBlock
, "ntbootdd.sys",
1658 "NTBOOTDD.SYS", ImageBase
, &BootDdDTE
);
1661 Status
= WinLdrScanImportDescriptorTable(&LoaderBlock
, "", BootDdDTE
);
1665 /* Change imports to PA */
1666 ImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE
->DllBase
),
1667 TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &ImportTableSize
);
1668 for (;(ImportTable
->Name
!= 0) && (ImportTable
->FirstThunk
!= 0);ImportTable
++)
1670 PIMAGE_THUNK_DATA ThunkData
= (PIMAGE_THUNK_DATA
)VaToPa(RVA(BootDdDTE
->DllBase
, ImportTable
->FirstThunk
));
1672 while (((PIMAGE_THUNK_DATA
)ThunkData
)->u1
.AddressOfData
!= 0)
1674 ThunkData
->u1
.Function
= (ULONG
)VaToPa((PVOID
)ThunkData
->u1
.Function
);
1679 /* Relocate image to PA */
1680 NtHeaders
= RtlImageNtHeader(VaToPa(BootDdDTE
->DllBase
));
1683 Status
= LdrRelocateImageWithBias(
1684 VaToPa(BootDdDTE
->DllBase
),
1685 NtHeaders
->OptionalHeader
.ImageBase
- (ULONG_PTR
)BootDdDTE
->DllBase
,
1688 TRUE
, /* in case of conflict still return success */
1693 /* Call the entrypoint */
1694 EntryPoint
= VaToPa(BootDdDTE
->EntryPoint
);
1695 (*EntryPoint
)(NULL
, NULL
);