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_PTR UlongAddress
)
450 SCSI_PHYSICAL_ADDRESS Address
;
452 Address
.QuadPart
= UlongAddress
;
459 IN PVOID DeviceExtension
)
467 ScsiPortFreeDeviceBase(
468 IN PVOID HwDeviceExtension
,
469 IN PVOID MappedAddress
)
477 IN PVOID DeviceExtension
,
478 IN ULONG BusDataType
,
479 IN ULONG SystemIoBusNumber
,
484 return HalGetBusDataByOffset(BusDataType
, SystemIoBusNumber
, SlotNumber
, Buffer
, 0, Length
);
489 ScsiPortGetDeviceBase(
490 IN PVOID HwDeviceExtension
,
491 IN INTERFACE_TYPE BusType
,
492 IN ULONG SystemIoBusNumber
,
493 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
494 IN ULONG NumberOfBytes
,
495 IN BOOLEAN InIoSpace
)
497 PHYSICAL_ADDRESS TranslatedAddress
;
500 AddressSpace
= (ULONG
)InIoSpace
;
501 if (HalTranslateBusAddress(BusType
,
505 &TranslatedAddress
) == FALSE
)
511 if (AddressSpace
!= 0)
512 return (PVOID
)TranslatedAddress
.u
.LowPart
;
516 return (PVOID
)IoAddress
.LowPart
;
521 ScsiPortGetLogicalUnit(
522 IN PVOID HwDeviceExtension
,
532 SCSI_PHYSICAL_ADDRESS
534 ScsiPortGetPhysicalAddress(
535 IN PVOID HwDeviceExtension
,
536 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
537 IN PVOID VirtualAddress
,
540 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
541 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
542 ULONG BufferLength
= 0;
545 DPRINTM2("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
546 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
548 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
550 if (Srb
== NULL
|| Srb
->SenseInfoBuffer
== VirtualAddress
)
552 /* Simply look it up in the allocated common buffer */
553 Offset
= (PUCHAR
)VirtualAddress
- (PUCHAR
)DeviceExtension
->SrbExtensionBuffer
;
555 BufferLength
= DeviceExtension
->CommonBufferLength
- Offset
;
556 PhysicalAddress
.QuadPart
= Offset
;
562 PhysicalAddress
.QuadPart
= (LONGLONG
)(SP_UNINITIALIZED_VALUE
);
565 *Length
= BufferLength
;
566 return PhysicalAddress
;
572 IN PVOID DeviceExtension
,
584 SpiAllocateCommonBuffer(
585 IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
586 IN ULONG NonCachedSize
)
589 ULONG CommonBufferLength
, BufSize
;
591 /* If size is 0, set it to 16 */
592 if (!DeviceExtension
->SrbExtensionSize
)
593 DeviceExtension
->SrbExtensionSize
= 16;
596 BufSize
= DeviceExtension
->SrbExtensionSize
;
599 BufSize
= (BufSize
+ sizeof(LONGLONG
) - 1) & ~(sizeof(LONGLONG
) - 1);
601 /* Sum up into the total common buffer length, and round it to page size */
603 ROUND_TO_PAGES(NonCachedSize
);
606 if (!DeviceExtension
->AdapterObject
)
608 /* From nonpaged pool if there is no DMA */
609 CommonBuffer
= ExAllocatePool(NonPagedPool
, CommonBufferLength
);
613 /* Perform a full request since we have a DMA adapter*/
618 /* Fail in case of error */
620 return STATUS_INSUFFICIENT_RESOURCES
;
623 RtlZeroMemory(CommonBuffer
, CommonBufferLength
);
625 /* Store its size in Device Extension */
626 DeviceExtension
->CommonBufferLength
= CommonBufferLength
;
628 /* SrbExtension buffer is located at the beginning of the buffer */
629 DeviceExtension
->SrbExtensionBuffer
= CommonBuffer
;
631 /* Non-cached extension buffer is located at the end of
635 CommonBufferLength
-= NonCachedSize
;
636 DeviceExtension
->NonCachedExtension
= (PUCHAR
)CommonBuffer
+ CommonBufferLength
;
640 DeviceExtension
->NonCachedExtension
= NULL
;
643 return STATUS_SUCCESS
;
648 ScsiPortGetUncachedExtension(
649 IN PVOID HwDeviceExtension
,
650 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
651 IN ULONG NumberOfBytes
)
653 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
654 DEVICE_DESCRIPTION DeviceDescription
;
655 ULONG MapRegistersCount
;
658 DPRINTM2("ScsiPortGetUncachedExtension(%p %p %lu)\n",
659 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
661 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
663 /* Check for allocated common DMA buffer */
664 if (DeviceExtension
->SrbExtensionBuffer
!= NULL
)
669 /* Check for DMA adapter object */
670 if (DeviceExtension
->AdapterObject
== NULL
)
672 /* Initialize DMA adapter description */
673 RtlZeroMemory(&DeviceDescription
, sizeof(DEVICE_DESCRIPTION
));
675 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
676 DeviceDescription
.Master
= ConfigInfo
->Master
;
677 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
678 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
679 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
680 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
681 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
682 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
683 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
684 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
685 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
686 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
688 /* Get a DMA adapter object */
690 DeviceExtension
->AdapterObject
=
691 HalGetAdapter(&DeviceDescription
, &MapRegistersCount
);
693 /* Fail in case of error */
694 if (DeviceExtension
->AdapterObject
== NULL
)
699 MapRegistersCount
= 0;
702 /* Set number of physical breaks */
703 if (ConfigInfo
->NumberOfPhysicalBreaks
!= 0 &&
704 MapRegistersCount
> ConfigInfo
->NumberOfPhysicalBreaks
)
706 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
=
707 ConfigInfo
->NumberOfPhysicalBreaks
;
711 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
= MapRegistersCount
;
715 /* Update Srb extension size */
716 if (DeviceExtension
->SrbExtensionSize
!= ConfigInfo
->SrbExtensionSize
)
717 DeviceExtension
->SrbExtensionSize
= ConfigInfo
->SrbExtensionSize
;
719 /* Allocate a common DMA buffer */
720 Status
= SpiAllocateCommonBuffer(DeviceExtension
, NumberOfBytes
);
722 if (!NT_SUCCESS(Status
))
724 DPRINTM2("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status
);
728 return DeviceExtension
->NonCachedExtension
;
733 ScsiPortGetVirtualAddress(
734 IN PVOID HwDeviceExtension
,
735 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
744 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
753 struct _DRIVE_LAYOUT_INFORMATION
*PartitionBuffer
;
754 CHAR PartitionName
[64];
756 /* Register device with partition(0) suffix */
757 sprintf(PartitionName
, "%spartition(0)", ArcName
);
758 FsRegisterDevice(PartitionName
, &DiskVtbl
);
760 /* Read device partition table */
761 Status
= ArcOpen(PartitionName
, OpenReadOnly
, &FileId
);
762 if (Status
== ESUCCESS
)
764 ret
= HALDISPATCH
->HalIoReadPartitionTable((PDEVICE_OBJECT
)FileId
, 512, FALSE
, &PartitionBuffer
);
767 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
++)
769 if (PartitionBuffer
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
771 sprintf(PartitionName
, "%spartition(%lu)",
772 ArcName
, PartitionBuffer
->PartitionEntry
[i
].PartitionNumber
);
773 FsRegisterDevice(PartitionName
, &DiskVtbl
);
776 ExFreePool(PartitionBuffer
);
784 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
789 PSCSI_REQUEST_BLOCK Srb
;
791 INQUIRYDATA InquiryBuffer
;
795 if (!DeviceExtension
->HwResetBus(DeviceExtension
->MiniPortDeviceExtension
, PathId
))
800 /* Remember the extension */
801 ScsiDeviceExtensions
[ScsiBus
] = DeviceExtension
;
803 for (TargetId
= 0; TargetId
< DeviceExtension
->MaxTargedIds
; TargetId
++)
808 DPRINTM2("Scanning SCSI device %d.%d.%d\n",
809 ScsiBus
, TargetId
, Lun
);
811 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
814 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
815 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
816 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
817 Srb
->PathId
= PathId
;
818 Srb
->TargetId
= TargetId
;
821 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
822 Srb
->DataTransferLength
= INQUIRYDATABUFFERSIZE
;
823 Srb
->TimeOutValue
= 5; /* in seconds */
824 Srb
->DataBuffer
= &InquiryBuffer
;
825 Cdb
= (PCDB
)Srb
->Cdb
;
826 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
827 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= Srb
->Lun
;
828 Cdb
->CDB6INQUIRY
.AllocationLength
= Srb
->DataTransferLength
;
829 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
831 /* Don't check next LUNs */
835 /* Device exists, create its ARC name */
836 if (InquiryBuffer
.RemovableMedia
)
838 sprintf(ArcName
, "scsi(%ld)cdrom(%ld)fdisk(%ld)",
839 ScsiBus
, TargetId
, Lun
);
840 FsRegisterDevice(ArcName
, &DiskVtbl
);
844 sprintf(ArcName
, "scsi(%ld)disk(%ld)rdisk(%ld)",
845 ScsiBus
, TargetId
, Lun
);
846 /* Now, check if it has partitions */
847 SpiScanDevice(DeviceExtension
, ArcName
, PathId
, TargetId
, Lun
);
852 } while (Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
);
858 IN PHW_INITIALIZATION_DATA HwInitializationData
,
859 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
,
860 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
)
862 PACCESS_RANGE AccessRange
;
863 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData
;
869 /* Loop through all entries */
870 for (Index
= 0; Index
< ResourceDescriptor
->PartialResourceList
.Count
; Index
++)
872 PartialData
= &ResourceDescriptor
->PartialResourceList
.PartialDescriptors
[Index
];
874 switch (PartialData
->Type
)
876 case CmResourceTypePort
:
877 /* Copy access ranges */
878 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
880 DPRINTM2("Got port at 0x%I64x, len 0x%x\n",
881 PartialData
->u
.Port
.Start
.QuadPart
, PartialData
->u
.Port
.Length
);
882 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
884 AccessRange
->RangeStart
= PartialData
->u
.Port
.Start
;
885 AccessRange
->RangeLength
= PartialData
->u
.Port
.Length
;
887 AccessRange
->RangeInMemory
= FALSE
;
892 case CmResourceTypeMemory
:
893 /* Copy access ranges */
894 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
896 DPRINTM2("Got memory at 0x%I64x, len 0x%x\n",
897 PartialData
->u
.Memory
.Start
.QuadPart
, PartialData
->u
.Memory
.Length
);
898 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
900 AccessRange
->RangeStart
= PartialData
->u
.Memory
.Start
;
901 AccessRange
->RangeLength
= PartialData
->u
.Memory
.Length
;
903 AccessRange
->RangeInMemory
= TRUE
;
908 case CmResourceTypeInterrupt
:
909 /* Copy interrupt data */
910 DPRINTM2("Got interrupt level %d, vector %d\n",
911 PartialData
->u
.Interrupt
.Level
, PartialData
->u
.Interrupt
.Vector
);
912 PortConfig
->BusInterruptLevel
= PartialData
->u
.Interrupt
.Level
;
913 PortConfig
->BusInterruptVector
= PartialData
->u
.Interrupt
.Vector
;
915 /* Set interrupt mode accordingly to the resource */
916 if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
918 PortConfig
->InterruptMode
= Latched
;
920 else if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
922 PortConfig
->InterruptMode
= LevelSensitive
;
926 case CmResourceTypeDma
:
927 DPRINTM2("Got DMA channel %d, port %d\n",
928 PartialData
->u
.Dma
.Channel
, PartialData
->u
.Dma
.Port
);
929 PortConfig
->DmaChannel
= PartialData
->u
.Dma
.Channel
;
930 PortConfig
->DmaPort
= PartialData
->u
.Dma
.Port
;
938 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
939 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
941 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
943 PCI_COMMON_CONFIG PciConfig
;
944 PCI_SLOT_NUMBER SlotNumber
;
947 ULONG FunctionNumber
;
948 CHAR VendorIdString
[8];
949 CHAR DeviceIdString
[8];
950 PCM_RESOURCE_LIST ResourceList
;
953 RtlZeroMemory(&ResourceList
, sizeof(PCM_RESOURCE_LIST
));
954 SlotNumber
.u
.AsULONG
= 0;
956 /* Loop through all devices */
957 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
959 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
961 /* Loop through all functions */
962 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
964 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
966 /* Get PCI config bytes */
967 DataSize
= HalGetBusDataByOffset(
970 SlotNumber
.u
.AsULONG
,
975 /* If result of HalGetBusData is 0, then the bus is wrong */
979 /* If result is PCI_INVALID_VENDORID, then this device has no more
981 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
984 sprintf(VendorIdString
, "%04hx", PciConfig
.VendorID
);
985 sprintf(DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
987 if (_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) ||
988 _strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
990 /* It is not our device */
994 DPRINTM2( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
995 PciConfig
.VendorID
, PciConfig
.DeviceID
,
997 SlotNumber
.u
.bits
.DeviceNumber
, SlotNumber
.u
.bits
.FunctionNumber
);
999 Status
= HalAssignSlotResources(NULL
,
1005 SlotNumber
.u
.AsULONG
,
1008 if (!NT_SUCCESS(Status
))
1011 /* Create configuration information */
1012 SpiResourceToConfig(HwInitializationData
,
1016 /* Free the resource list */
1017 ExFreePool(ResourceList
);
1019 /* Set dev & fn numbers */
1020 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1021 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
+ 1;
1023 /* Save the slot number */
1024 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1028 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1031 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1041 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1042 IN PVOID HwContext OPTIONAL
)
1044 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1045 ULONG DeviceExtensionSize
;
1046 PORT_CONFIGURATION_INFORMATION PortConfig
;
1048 BOOLEAN FirstConfigCall
= TRUE
;
1049 PCI_SLOT_NUMBER SlotNumber
;
1052 if (HwInitializationData
->HwInitializationDataSize
!= sizeof(HW_INITIALIZATION_DATA
))
1054 return STATUS_INVALID_PARAMETER
;
1057 /* Check params for validity */
1058 if ((HwInitializationData
->HwInitialize
== NULL
) ||
1059 (HwInitializationData
->HwStartIo
== NULL
) ||
1060 (HwInitializationData
->HwInterrupt
== NULL
) ||
1061 (HwInitializationData
->HwFindAdapter
== NULL
) ||
1062 (HwInitializationData
->HwResetBus
== NULL
))
1064 return STATUS_INVALID_PARAMETER
;
1067 /* Zero starting slot number */
1068 SlotNumber
.u
.AsULONG
= 0;
1074 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) + HwInitializationData
->DeviceExtensionSize
;
1075 DeviceExtension
= MmHeapAlloc(DeviceExtensionSize
);
1076 if (!DeviceExtension
)
1078 return STATUS_NO_MEMORY
;
1080 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
1081 DeviceExtension
->InterruptFlags
= SCSI_PORT_NEXT_REQUEST_READY
;
1082 DeviceExtension
->HwInitialize
= HwInitializationData
->HwInitialize
;
1083 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
1084 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
1085 DeviceExtension
->HwResetBus
= HwInitializationData
->HwResetBus
;
1086 DeviceExtension
->MiniPortDeviceExtension
= (PVOID
)(DeviceExtension
+ 1);
1088 Status
= SpiCreatePortConfig(DeviceExtension
,
1089 HwInitializationData
,
1092 if (Status
!= STATUS_SUCCESS
)
1094 MmHeapFree(DeviceExtension
);
1098 PortConfig
.NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
1099 PortConfig
.AccessRanges
= MmHeapAlloc(sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1100 if (!PortConfig
.AccessRanges
)
1102 MmHeapFree(DeviceExtension
);
1103 return STATUS_NO_MEMORY
;
1105 RtlZeroMemory(PortConfig
.AccessRanges
, sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1107 /* Search for matching PCI device */
1108 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
1109 (HwInitializationData
->VendorIdLength
> 0) &&
1110 (HwInitializationData
->VendorId
!= NULL
) &&
1111 (HwInitializationData
->DeviceIdLength
> 0) &&
1112 (HwInitializationData
->DeviceId
!= NULL
))
1114 PortConfig
.BusInterruptLevel
= 0;
1116 /* Get PCI device data */
1117 DPRINTM2("VendorId '%.*s' DeviceId '%.*s'\n",
1118 HwInitializationData
->VendorIdLength
,
1119 HwInitializationData
->VendorId
,
1120 HwInitializationData
->DeviceIdLength
,
1121 HwInitializationData
->DeviceId
);
1123 if (!SpiGetPciConfigData(HwInitializationData
,
1128 /* Continue to the next bus, nothing here */
1129 MmHeapFree(DeviceExtension
);
1130 return STATUS_INTERNAL_ERROR
;
1133 if (!PortConfig
.BusInterruptLevel
)
1135 /* Bypass this slot, because no interrupt was assigned */
1136 MmHeapFree(DeviceExtension
);
1137 return STATUS_INTERNAL_ERROR
;
1141 if (HwInitializationData
->HwFindAdapter(
1142 DeviceExtension
->MiniPortDeviceExtension
,
1147 &Again
) != SP_RETURN_FOUND
)
1149 MmHeapFree(DeviceExtension
);
1150 return STATUS_INTERNAL_ERROR
;
1153 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1154 if (PortConfig
.MaximumNumberOfTargets
> SCSI_MAXIMUM_TARGETS_PER_BUS
)
1155 DeviceExtension
->MaxTargedIds
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
1157 DeviceExtension
->MaxTargedIds
= PortConfig
.MaximumNumberOfTargets
;
1159 DeviceExtension
->BusNum
= PortConfig
.SystemIoBusNumber
;
1161 DPRINTM2("Adapter found: buses = %d, targets = %d\n",
1162 PortConfig
.NumberOfBuses
, DeviceExtension
->MaxTargedIds
);
1164 /* Initialize adapter */
1165 if (!DeviceExtension
->HwInitialize(DeviceExtension
->MiniPortDeviceExtension
))
1167 MmHeapFree(DeviceExtension
);
1168 return STATUS_INTERNAL_ERROR
;
1174 for (ScsiBus
= 0; ScsiBus
< PortConfig
.NumberOfBuses
; ScsiBus
++)
1176 SpiScanAdapter(DeviceExtension
, PortConfig
.SystemIoBusNumber
, ScsiBus
);
1177 PortConfig
.SystemIoBusNumber
++;
1181 FirstConfigCall
= FALSE
;
1188 return STATUS_SUCCESS
;
1193 ScsiPortIoMapTransfer(
1194 IN PVOID HwDeviceExtension
,
1195 IN PSCSI_REQUEST_BLOCK Srb
,
1196 IN PVOID LogicalAddress
,
1206 IN PVOID HwDeviceExtension
,
1207 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1221 IN PVOID WriteBuffer
,
1222 IN PVOID ReadBuffer
,
1225 RtlMoveMemory(WriteBuffer
, ReadBuffer
, Length
);
1230 ScsiPortNotification(
1231 IN SCSI_NOTIFICATION_TYPE NotificationType
,
1232 IN PVOID HwDeviceExtension
,
1235 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1236 PSCSI_REQUEST_BLOCK Srb
;
1239 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
1241 va_start(ap
, HwDeviceExtension
);
1243 switch (NotificationType
)
1245 case RequestComplete
:
1246 /* Mask the SRB as completed */
1247 Srb
= va_arg(ap
, PSCSI_REQUEST_BLOCK
);
1248 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1252 /* Say that device is ready */
1253 DeviceExtension
->InterruptFlags
|= SCSI_PORT_NEXT_REQUEST_READY
;
1266 ScsiPortReadPortBufferUchar(
1271 __inbytestring(H2I(Port
), Buffer
, Count
);
1276 ScsiPortReadPortBufferUlong(
1281 __indwordstring(H2I(Port
), Buffer
, Count
);
1286 ScsiPortReadPortBufferUshort(
1291 __inwordstring(H2I(Port
), Buffer
, Count
);
1296 ScsiPortReadPortUchar(
1299 DPRINTM2("ScsiPortReadPortUchar(%p)\n",
1302 return READ_PORT_UCHAR(Port
);
1307 ScsiPortReadPortUlong(
1310 return READ_PORT_ULONG(Port
);
1315 ScsiPortReadPortUshort(
1318 return READ_PORT_USHORT(Port
);
1323 ScsiPortReadRegisterBufferUchar(
1334 ScsiPortReadRegisterBufferUlong(
1345 ScsiPortReadRegisterBufferUshort(
1346 IN PUSHORT Register
,
1356 ScsiPortReadRegisterUchar(
1359 return READ_REGISTER_UCHAR(Register
);
1364 ScsiPortReadRegisterUlong(
1367 return READ_REGISTER_ULONG(Register
);
1372 ScsiPortReadRegisterUshort(
1373 IN PUSHORT Register
)
1375 return READ_REGISTER_USHORT(Register
);
1380 ScsiPortSetBusDataByOffset(
1381 IN PVOID DeviceExtension
,
1382 IN ULONG BusDataType
,
1383 IN ULONG SystemIoBusNumber
,
1384 IN ULONG SlotNumber
,
1396 ScsiPortStallExecution(
1399 KeStallExecutionProcessor(Delay
);
1404 ScsiPortValidateRange(
1405 IN PVOID HwDeviceExtension
,
1406 IN INTERFACE_TYPE BusType
,
1407 IN ULONG SystemIoBusNumber
,
1408 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1409 IN ULONG NumberOfBytes
,
1410 IN BOOLEAN InIoSpace
)
1424 ScsiPortWritePortBufferUchar(
1429 __outbytestring(H2I(Port
), Buffer
, Count
);
1434 ScsiPortWritePortBufferUlong(
1439 __outdwordstring(H2I(Port
), Buffer
, Count
);
1444 ScsiPortWritePortBufferUshort(
1449 __outwordstring(H2I(Port
), Buffer
, Count
);
1454 ScsiPortWritePortUchar(
1458 WRITE_PORT_UCHAR(Port
, Value
);
1463 ScsiPortWritePortUlong(
1467 WRITE_PORT_ULONG(Port
, Value
);
1472 ScsiPortWritePortUshort(
1476 WRITE_PORT_USHORT(Port
, Value
);
1481 ScsiPortWriteRegisterBufferUchar(
1492 ScsiPortWriteRegisterBufferUlong(
1503 ScsiPortWriteRegisterBufferUshort(
1504 IN PUSHORT Register
,
1514 ScsiPortWriteRegisterUchar(
1518 WRITE_REGISTER_UCHAR(Register
, Value
);
1523 ScsiPortWriteRegisterUlong(
1527 WRITE_REGISTER_ULONG(Register
, Value
);
1532 ScsiPortWriteRegisterUshort(
1533 IN PUSHORT Register
,
1536 WRITE_REGISTER_USHORT(Register
, Value
);
1540 LoadBootDeviceDriver(VOID
)
1548 { "ScsiDebugPrint", ScsiDebugPrint
},
1549 { "ScsiPortCompleteRequest", ScsiPortCompleteRequest
},
1550 { "ScsiPortConvertPhysicalAddressToUlong", ScsiPortConvertPhysicalAddressToUlong
},
1551 { "ScsiPortConvertUlongToPhysicalAddress", ScsiPortConvertUlongToPhysicalAddress
},
1552 { "ScsiPortFlushDma", ScsiPortFlushDma
},
1553 { "ScsiPortFreeDeviceBase", ScsiPortFreeDeviceBase
},
1554 { "ScsiPortGetBusData", ScsiPortGetBusData
},
1555 { "ScsiPortGetDeviceBase", ScsiPortGetDeviceBase
},
1556 { "ScsiPortGetLogicalUnit", ScsiPortGetLogicalUnit
},
1557 { "ScsiPortGetPhysicalAddress", ScsiPortGetPhysicalAddress
},
1558 { "ScsiPortGetSrb", ScsiPortGetSrb
},
1559 { "ScsiPortGetUncachedExtension", ScsiPortGetUncachedExtension
},
1560 { "ScsiPortGetVirtualAddress", ScsiPortGetVirtualAddress
},
1561 { "ScsiPortInitialize", ScsiPortInitialize
},
1562 { "ScsiPortIoMapTransfer", ScsiPortIoMapTransfer
},
1563 { "ScsiPortLogError", ScsiPortLogError
},
1564 { "ScsiPortMoveMemory", ScsiPortMoveMemory
},
1565 { "ScsiPortNotification", ScsiPortNotification
},
1566 { "ScsiPortReadPortBufferUchar", ScsiPortReadPortBufferUchar
},
1567 { "ScsiPortReadPortBufferUlong", ScsiPortReadPortBufferUlong
},
1568 { "ScsiPortReadPortBufferUshort", ScsiPortReadPortBufferUshort
},
1569 { "ScsiPortReadPortUchar", ScsiPortReadPortUchar
},
1570 { "ScsiPortReadPortUlong", ScsiPortReadPortUlong
},
1571 { "ScsiPortReadPortUshort", ScsiPortReadPortUshort
},
1572 { "ScsiPortReadRegisterBufferUchar", ScsiPortReadRegisterBufferUchar
},
1573 { "ScsiPortReadRegisterBufferUlong", ScsiPortReadRegisterBufferUlong
},
1574 { "ScsiPortReadRegisterBufferUshort", ScsiPortReadRegisterBufferUshort
},
1575 { "ScsiPortReadRegisterUchar", ScsiPortReadRegisterUchar
},
1576 { "ScsiPortReadRegisterUlong", ScsiPortReadRegisterUlong
},
1577 { "ScsiPortReadRegisterUshort", ScsiPortReadRegisterUshort
},
1578 { "ScsiPortSetBusDataByOffset", ScsiPortSetBusDataByOffset
},
1579 { "ScsiPortStallExecution", ScsiPortStallExecution
},
1580 { "ScsiPortValidateRange", ScsiPortValidateRange
},
1581 { "ScsiPortWritePortBufferUchar", ScsiPortWritePortBufferUchar
},
1582 { "ScsiPortWritePortBufferUlong", ScsiPortWritePortBufferUlong
},
1583 { "ScsiPortWritePortBufferUshort", ScsiPortWritePortBufferUshort
},
1584 { "ScsiPortWritePortUchar", ScsiPortWritePortUchar
},
1585 { "ScsiPortWritePortUlong", ScsiPortWritePortUlong
},
1586 { "ScsiPortWritePortUshort", ScsiPortWritePortUshort
},
1587 { "ScsiPortWriteRegisterBufferUchar", ScsiPortWriteRegisterBufferUchar
},
1588 { "ScsiPortWriteRegisterBufferUlong", ScsiPortWriteRegisterBufferUlong
},
1589 { "ScsiPortWriteRegisterBufferUshort", ScsiPortWriteRegisterBufferUshort
},
1590 { "ScsiPortWriteRegisterUchar", ScsiPortWriteRegisterUchar
},
1591 { "ScsiPortWriteRegisterUlong", ScsiPortWriteRegisterUlong
},
1592 { "ScsiPortWriteRegisterUshort", ScsiPortWriteRegisterUshort
},
1594 IMAGE_DOS_HEADER ImageDosHeader
;
1595 IMAGE_NT_HEADERS ImageNtHeaders
;
1596 IMAGE_EXPORT_DIRECTORY ImageExportDirectory
;
1597 CHAR
* TableName
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1598 USHORT OrdinalTable
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1599 ULONG FunctionTable
[sizeof(ExportTable
) / sizeof(ExportTable
[0])];
1601 PIMAGE_NT_HEADERS NtHeaders
;
1602 LOADER_PARAMETER_BLOCK LoaderBlock
;
1603 PIMAGE_IMPORT_DESCRIPTOR ImportTable
;
1604 ULONG ImportTableSize
;
1605 PLDR_DATA_TABLE_ENTRY BootDdDTE
, FreeldrDTE
;
1606 CHAR NtBootDdPath
[MAX_PATH
];
1608 ULONG (NTAPI
*EntryPoint
)(IN PVOID DriverObject
, IN PVOID RegistryPath
);
1612 /* Some initialization of our temporary loader block */
1613 RtlZeroMemory(&LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
1614 InitializeListHead(&LoaderBlock
.LoadOrderListHead
);
1616 /* Create our fake executable header for freeldr.sys */
1617 RtlZeroMemory(&ImageDosHeader
, sizeof(IMAGE_DOS_HEADER
));
1618 RtlZeroMemory(&ImageNtHeaders
, sizeof(IMAGE_NT_HEADERS
));
1619 RtlZeroMemory(&ImageExportDirectory
, sizeof(IMAGE_EXPORT_DIRECTORY
));
1620 ImageDosHeader
.e_magic
= SWAPW(IMAGE_DOS_SIGNATURE
);
1621 ImageDosHeader
.e_lfanew
= SWAPD((ULONG_PTR
)&ImageNtHeaders
- (ULONG_PTR
)&ImageDosHeader
);
1622 ImageNtHeaders
.Signature
= IMAGE_NT_SIGNATURE
;
1623 ImageNtHeaders
.OptionalHeader
.NumberOfRvaAndSizes
= SWAPD(IMAGE_DIRECTORY_ENTRY_EXPORT
+ 1);
1624 ImageNtHeaders
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
=
1625 SWAPW((ULONG_PTR
)&ImageExportDirectory
- (ULONG_PTR
)&ImageDosHeader
);
1626 ImageNtHeaders
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
= 1;
1627 ImageExportDirectory
.NumberOfNames
= sizeof(ExportTable
) / sizeof(ExportTable
[0]);
1628 ImageExportDirectory
.AddressOfNames
= (ULONG_PTR
)TableName
- (ULONG_PTR
)&ImageDosHeader
;
1629 ImageExportDirectory
.AddressOfNameOrdinals
= (ULONG_PTR
)OrdinalTable
- (ULONG_PTR
)&ImageDosHeader
;
1630 ImageExportDirectory
.NumberOfFunctions
= sizeof(ExportTable
) / sizeof(ExportTable
[0]);
1631 ImageExportDirectory
.AddressOfFunctions
= (ULONG_PTR
)FunctionTable
- (ULONG_PTR
)&ImageDosHeader
;
1633 /* Fill freeldr.sys export table */
1634 for (i
= 0; i
< sizeof(ExportTable
) / sizeof(ExportTable
[0]); i
++)
1636 TableName
[i
] = PaToVa((PVOID
)((ULONG_PTR
)ExportTable
[i
].Name
- (ULONG_PTR
)&ImageDosHeader
));
1637 OrdinalTable
[i
] = i
;
1638 FunctionTable
[i
] = (ULONG
)((ULONG_PTR
)ExportTable
[i
].Function
- (ULONG_PTR
)&ImageDosHeader
);
1641 /* Add freeldr.sys to list of loaded executables */
1642 Status
= WinLdrAllocateDataTableEntry(&LoaderBlock
, "scsiport.sys",
1643 "FREELDR.SYS", &ImageDosHeader
, &FreeldrDTE
);
1647 /* Create full ntbootdd.sys path */
1648 MachDiskGetBootPath(NtBootDdPath
, sizeof(NtBootDdPath
));
1649 strcat(NtBootDdPath
, "\\NTBOOTDD.SYS");
1652 Status
= WinLdrLoadImage(NtBootDdPath
, LoaderBootDriver
, &ImageBase
);
1655 /* That's OK. File simply doesn't exist */
1660 Status
= WinLdrAllocateDataTableEntry(&LoaderBlock
, "ntbootdd.sys",
1661 "NTBOOTDD.SYS", ImageBase
, &BootDdDTE
);
1664 Status
= WinLdrScanImportDescriptorTable(&LoaderBlock
, "", BootDdDTE
);
1668 /* Change imports to PA */
1669 ImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE
->DllBase
),
1670 TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &ImportTableSize
);
1671 for (;(ImportTable
->Name
!= 0) && (ImportTable
->FirstThunk
!= 0);ImportTable
++)
1673 PIMAGE_THUNK_DATA ThunkData
= (PIMAGE_THUNK_DATA
)VaToPa(RVA(BootDdDTE
->DllBase
, ImportTable
->FirstThunk
));
1675 while (((PIMAGE_THUNK_DATA
)ThunkData
)->u1
.AddressOfData
!= 0)
1677 ThunkData
->u1
.Function
= (ULONG
)VaToPa((PVOID
)ThunkData
->u1
.Function
);
1682 /* Relocate image to PA */
1683 NtHeaders
= RtlImageNtHeader(VaToPa(BootDdDTE
->DllBase
));
1686 Status
= LdrRelocateImageWithBias(
1687 VaToPa(BootDdDTE
->DllBase
),
1688 NtHeaders
->OptionalHeader
.ImageBase
- (ULONG_PTR
)BootDdDTE
->DllBase
,
1691 TRUE
, /* in case of conflict still return success */
1696 /* Call the entrypoint */
1697 EntryPoint
= VaToPa(BootDdDTE
->EntryPoint
);
1698 (*EntryPoint
)(NULL
, NULL
);