2 * PROJECT: ReactOS Boot Loader (FreeLDR)
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/disk/scsiport.c
5 * PURPOSE: Interface for SCSI Emulation
6 * PROGRAMMERS: Hervé Poussineau <hpoussin@reactos.org>
9 /* INCLUDES *******************************************************************/
14 DBG_DEFAULT_CHANNEL(SCSIPORT
);
27 #undef ScsiPortLogError
28 #undef ScsiPortMoveMemory
29 #undef ScsiPortWritePortBufferUchar
30 #undef ScsiPortWritePortBufferUlong
31 #undef ScsiPortWritePortBufferUshort
32 #undef ScsiPortWritePortUchar
33 #undef ScsiPortWritePortUlong
34 #undef ScsiPortWritePortUshort
35 #undef ScsiPortWriteRegisterBufferUchar
36 #undef ScsiPortWriteRegisterBufferUlong
37 #undef ScsiPortWriteRegisterBufferUshort
38 #undef ScsiPortWriteRegisterUchar
39 #undef ScsiPortWriteRegisterUlong
40 #undef ScsiPortWriteRegisterUshort
41 #undef ScsiPortReadPortBufferUchar
42 #undef ScsiPortReadPortBufferUlong
43 #undef ScsiPortReadPortBufferUshort
44 #undef ScsiPortReadPortUchar
45 #undef ScsiPortReadPortUlong
46 #undef ScsiPortReadPortUshort
47 #undef ScsiPortReadRegisterBufferUchar
48 #undef ScsiPortReadRegisterBufferUlong
49 #undef ScsiPortReadRegisterBufferUshort
50 #undef ScsiPortReadRegisterUchar
51 #undef ScsiPortReadRegisterUlong
52 #undef ScsiPortReadRegisterUshort
54 #define SCSI_PORT_NEXT_REQUEST_READY 0x0008
56 #define TAG_SCSI_DEVEXT 'DscS'
57 #define TAG_SCSI_ACCESS_RANGES 'AscS'
59 /* GLOBALS ********************************************************************/
62 VOID NTAPI
HalpInitializePciStubs(VOID
);
63 VOID NTAPI
HalpInitBusHandler(VOID
);
68 PVOID NonCachedExtension
;
75 /* SRB extension stuff */
76 ULONG SrbExtensionSize
;
77 PVOID SrbExtensionBuffer
;
79 IO_SCSI_CAPABILITIES PortCapabilities
;
81 PHW_INITIALIZE HwInitialize
;
82 PHW_STARTIO HwStartIo
;
83 PHW_INTERRUPT HwInterrupt
;
84 PHW_RESET_BUS HwResetBus
;
86 /* DMA related stuff */
87 PADAPTER_OBJECT AdapterObject
;
89 ULONG CommonBufferLength
;
91 PVOID MiniPortDeviceExtension
;
92 } SCSI_PORT_DEVICE_EXTENSION
, *PSCSI_PORT_DEVICE_EXTENSION
;
94 typedef struct tagDISKCONTEXT
97 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
102 /* Device characteristics */
104 ULONGLONG SectorOffset
;
105 ULONGLONG SectorCount
;
106 ULONGLONG SectorNumber
;
109 PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions
[SCSI_MAXIMUM_BUSES
];
111 /* FUNCTIONS ******************************************************************/
118 PFOUR_BYTE Source
= (PFOUR_BYTE
)&Value
;
120 Dest
.Byte0
= Source
->Byte3
;
121 Dest
.Byte1
= Source
->Byte2
;
122 Dest
.Byte2
= Source
->Byte1
;
123 Dest
.Byte3
= Source
->Byte0
;
130 SpiSendSynchronousSrb(
131 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
132 IN PSCSI_REQUEST_BLOCK Srb
)
136 ASSERT(!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
));
138 /* HACK: handle lack of interrupts */
139 while (!(DeviceExtension
->InterruptFlags
& SCSI_PORT_NEXT_REQUEST_READY
))
141 KeStallExecutionProcessor(100 * 1000);
142 DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
);
145 DeviceExtension
->InterruptFlags
&= ~SCSI_PORT_NEXT_REQUEST_READY
;
146 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
148 if (!DeviceExtension
->HwStartIo(
149 DeviceExtension
->MiniPortDeviceExtension
,
156 /* HACK: handle lack of interrupts */
157 while (Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
)
159 KeStallExecutionProcessor(100 * 1000);
160 DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
);
163 ret
= SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
;
169 static ARC_STATUS
DiskClose(ULONG FileId
)
171 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
176 static ARC_STATUS
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
178 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
180 RtlZeroMemory(Information
, sizeof(*Information
));
183 * The ARC specification mentions that for partitions, StartingAddress and
184 * EndingAddress are the start and end positions of the partition in terms
185 * of byte offsets from the start of the disk.
186 * CurrentAddress is the current offset into (i.e. relative to) the partition.
188 Information
->StartingAddress
.QuadPart
= Context
->SectorOffset
* Context
->SectorSize
;
189 Information
->EndingAddress
.QuadPart
= (Context
->SectorOffset
+ Context
->SectorCount
) * Context
->SectorSize
;
190 Information
->CurrentAddress
.QuadPart
= Context
->SectorNumber
* Context
->SectorSize
;
195 static ARC_STATUS
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
197 PSCSI_REQUEST_BLOCK Srb
;
199 READ_CAPACITY_DATA ReadCapacityBuffer
;
201 DISKCONTEXT
* Context
;
202 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
203 ULONG ScsiBus
, PathId
, TargetId
, Lun
, Partition
, PathSyntax
;
205 ULONGLONG SectorOffset
= 0;
206 ULONGLONG SectorCount
;
209 if (!DissectArcPath2(Path
, &ScsiBus
, &TargetId
, &Lun
, &Partition
, &PathSyntax
))
211 if (PathSyntax
!= 0) /* scsi() format */
213 DeviceExtension
= ScsiDeviceExtensions
[ScsiBus
];
214 PathId
= ScsiBus
- DeviceExtension
->BusNum
;
216 /* Get disk capacity and sector size */
217 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
220 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
221 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
222 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
223 Srb
->PathId
= (UCHAR
)PathId
;
224 Srb
->TargetId
= (UCHAR
)TargetId
;
225 Srb
->Lun
= (UCHAR
)Lun
;
227 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
228 Srb
->DataTransferLength
= sizeof(READ_CAPACITY_DATA
);
229 Srb
->TimeOutValue
= 5; /* in seconds */
230 Srb
->DataBuffer
= &ReadCapacityBuffer
;
231 Cdb
= (PCDB
)Srb
->Cdb
;
232 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
233 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
238 /* Transform result to host endianness */
239 SectorCount
= ntohl(ReadCapacityBuffer
.LogicalBlockAddress
);
240 SectorSize
= ntohl(ReadCapacityBuffer
.BytesPerBlock
);
244 /* Need to offset start of disk and length */
249 Context
= ExAllocatePool(PagedPool
, sizeof(DISKCONTEXT
));
252 Context
->DeviceExtension
= DeviceExtension
;
253 Context
->PathId
= (UCHAR
)PathId
;
254 Context
->TargetId
= (UCHAR
)TargetId
;
255 Context
->Lun
= (UCHAR
)Lun
;
256 Context
->SectorSize
= SectorSize
;
257 Context
->SectorOffset
= SectorOffset
;
258 Context
->SectorCount
= SectorCount
;
259 Context
->SectorNumber
= 0;
260 FsSetDeviceSpecific(*FileId
, Context
);
265 static ARC_STATUS
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
267 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
268 PSCSI_REQUEST_BLOCK Srb
;
270 ULONG FullSectors
, NbSectors
;
278 FullSectors
= N
/ Context
->SectorSize
;
279 NbSectors
= (N
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
280 if (Context
->SectorNumber
+ NbSectors
>= Context
->SectorCount
)
282 if (FullSectors
> 0xffff)
285 /* Read full sectors */
286 ASSERT(Context
->SectorNumber
< 0xFFFFFFFF);
287 Lba
= (ULONG
)(Context
->SectorOffset
+ Context
->SectorNumber
);
290 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
294 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
295 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
296 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
297 Srb
->PathId
= Context
->PathId
;
298 Srb
->TargetId
= Context
->TargetId
;
299 Srb
->Lun
= Context
->Lun
;
301 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
302 Srb
->DataTransferLength
= FullSectors
* Context
->SectorSize
;
303 Srb
->TimeOutValue
= 5; /* in seconds */
304 Srb
->DataBuffer
= Buffer
;
305 Cdb
= (PCDB
)Srb
->Cdb
;
306 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
307 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
308 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
309 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
310 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
311 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
312 Cdb
->CDB10
.TransferBlocksMsb
= (FullSectors
>> 8) & 0xff;
313 Cdb
->CDB10
.TransferBlocksLsb
= FullSectors
& 0xff;
314 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
318 Buffer
= (PUCHAR
)Buffer
+ FullSectors
* Context
->SectorSize
;
319 N
-= FullSectors
* Context
->SectorSize
;
320 *Count
+= FullSectors
* Context
->SectorSize
;
321 Context
->SectorNumber
+= FullSectors
;
325 /* Read incomplete last sector */
330 Sector
= ExAllocatePool(PagedPool
, Context
->SectorSize
);
334 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
341 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
342 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
343 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
344 Srb
->PathId
= Context
->PathId
;
345 Srb
->TargetId
= Context
->TargetId
;
346 Srb
->Lun
= Context
->Lun
;
348 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
349 Srb
->DataTransferLength
= Context
->SectorSize
;
350 Srb
->TimeOutValue
= 5; /* in seconds */
351 Srb
->DataBuffer
= Sector
;
352 Cdb
= (PCDB
)Srb
->Cdb
;
353 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
354 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
355 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
356 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
357 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
358 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
359 Cdb
->CDB10
.TransferBlocksMsb
= 0;
360 Cdb
->CDB10
.TransferBlocksLsb
= 1;
361 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
366 RtlCopyMemory(Buffer
, Sector
, N
);
368 /* Context->SectorNumber remains untouched (incomplete sector read) */
375 static ARC_STATUS
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
377 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
378 LARGE_INTEGER NewPosition
= *Position
;
385 NewPosition
.QuadPart
+= (Context
->SectorNumber
* Context
->SectorSize
);
392 if (NewPosition
.QuadPart
& (Context
->SectorSize
- 1))
395 /* Convert in number of sectors */
396 NewPosition
.QuadPart
/= Context
->SectorSize
;
397 if (NewPosition
.QuadPart
>= Context
->SectorCount
)
400 Context
->SectorNumber
= NewPosition
.QuadPart
;
404 static const DEVVTBL DiskVtbl
=
407 DiskGetFileInformation
,
416 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
417 IN PHW_INITIALIZATION_DATA HwInitData
,
418 OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
419 IN BOOLEAN ZeroStruct
)
423 /* Zero out the struct if told so */
426 /* First zero the portconfig */
427 RtlZeroMemory(ConfigInfo
, sizeof(PORT_CONFIGURATION_INFORMATION
));
429 /* Initialize the struct */
430 ConfigInfo
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
431 ConfigInfo
->AdapterInterfaceType
= HwInitData
->AdapterInterfaceType
;
432 ConfigInfo
->InterruptMode
= Latched
;
433 ConfigInfo
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
434 ConfigInfo
->DmaPort
= SP_UNINITIALIZED_VALUE
;
435 ConfigInfo
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
436 ConfigInfo
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
438 /* Store parameters */
439 ConfigInfo
->NeedPhysicalAddresses
= HwInitData
->NeedPhysicalAddresses
;
440 ConfigInfo
->MapBuffers
= HwInitData
->MapBuffers
;
441 ConfigInfo
->AutoRequestSense
= HwInitData
->AutoRequestSense
;
442 ConfigInfo
->ReceiveEvent
= HwInitData
->ReceiveEvent
;
443 ConfigInfo
->TaggedQueuing
= HwInitData
->TaggedQueuing
;
444 ConfigInfo
->MultipleRequestPerLu
= HwInitData
->MultipleRequestPerLu
;
446 /* Get the disk usage */
447 ConfigInfo
->AtdiskPrimaryClaimed
= FALSE
; // FIXME
448 ConfigInfo
->AtdiskSecondaryClaimed
= FALSE
; // FIXME
450 /* Initiator bus id is not set */
451 for (Bus
= 0; Bus
< 8; Bus
++)
452 ConfigInfo
->InitiatorBusId
[Bus
] = (CCHAR
)SP_UNINITIALIZED_VALUE
;
455 ConfigInfo
->NumberOfPhysicalBreaks
= 17;
457 return STATUS_SUCCESS
;
463 IN ULONG DebugPrintLevel
,
464 IN PCCHAR DebugMessage
,
471 if (DebugPrintLevel
> 10)
474 va_start(ap
, DebugMessage
);
476 /* Construct a string */
477 Length
= _vsnprintf(Buffer
, 512, DebugMessage
, ap
);
479 /* Check if we went past the buffer */
480 if (Length
== MAXULONG
)
482 /* Terminate it if we went over-board */
483 Buffer
[sizeof(Buffer
) - 1] = '\0';
486 Length
= sizeof(Buffer
);
489 /* Print the message */
498 ScsiPortCompleteRequest(
499 IN PVOID HwDeviceExtension
,
509 #undef ScsiPortConvertPhysicalAddressToUlong
512 ScsiPortConvertPhysicalAddressToUlong(
513 IN SCSI_PHYSICAL_ADDRESS Address
)
515 return Address
.LowPart
;
518 SCSI_PHYSICAL_ADDRESS
520 ScsiPortConvertUlongToPhysicalAddress(
521 IN ULONG_PTR UlongAddress
)
523 SCSI_PHYSICAL_ADDRESS Address
;
525 Address
.QuadPart
= UlongAddress
;
532 IN PVOID DeviceExtension
)
540 ScsiPortFreeDeviceBase(
541 IN PVOID HwDeviceExtension
,
542 IN PVOID MappedAddress
)
550 IN PVOID DeviceExtension
,
551 IN ULONG BusDataType
,
552 IN ULONG SystemIoBusNumber
,
557 return HalGetBusDataByOffset(BusDataType
, SystemIoBusNumber
, SlotNumber
, Buffer
, 0, Length
);
562 ScsiPortGetDeviceBase(
563 IN PVOID HwDeviceExtension
,
564 IN INTERFACE_TYPE BusType
,
565 IN ULONG SystemIoBusNumber
,
566 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
567 IN ULONG NumberOfBytes
,
568 IN BOOLEAN InIoSpace
)
570 PHYSICAL_ADDRESS TranslatedAddress
;
573 AddressSpace
= (ULONG
)InIoSpace
;
574 if (HalTranslateBusAddress(BusType
,
578 &TranslatedAddress
) == FALSE
)
584 if (AddressSpace
!= 0)
585 return (PVOID
)TranslatedAddress
.u
.LowPart
;
589 return (PVOID
)IoAddress
.LowPart
;
594 ScsiPortGetLogicalUnit(
595 IN PVOID HwDeviceExtension
,
605 SCSI_PHYSICAL_ADDRESS
607 ScsiPortGetPhysicalAddress(
608 IN PVOID HwDeviceExtension
,
609 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
610 IN PVOID VirtualAddress
,
613 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
614 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
615 ULONG BufferLength
= 0;
618 TRACE("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
619 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
621 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
623 if (Srb
== NULL
|| Srb
->SenseInfoBuffer
== VirtualAddress
)
625 /* Simply look it up in the allocated common buffer */
626 Offset
= (PUCHAR
)VirtualAddress
- (PUCHAR
)DeviceExtension
->SrbExtensionBuffer
;
628 BufferLength
= DeviceExtension
->CommonBufferLength
- Offset
;
629 PhysicalAddress
.QuadPart
= Offset
;
634 PhysicalAddress
.QuadPart
= (LONGLONG
)(SP_UNINITIALIZED_VALUE
);
637 *Length
= BufferLength
;
638 return PhysicalAddress
;
644 IN PVOID DeviceExtension
,
657 SpiAllocateCommonBuffer(
658 IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
659 IN ULONG NonCachedSize
)
662 ULONG CommonBufferLength
, BufSize
;
664 /* If size is 0, set it to 16 */
665 if (!DeviceExtension
->SrbExtensionSize
)
666 DeviceExtension
->SrbExtensionSize
= 16;
669 BufSize
= DeviceExtension
->SrbExtensionSize
;
672 BufSize
= (BufSize
+ sizeof(LONGLONG
) - 1) & ~(sizeof(LONGLONG
) - 1);
674 /* Sum up into the total common buffer length, and round it to page size */
676 ROUND_TO_PAGES(NonCachedSize
);
679 if (!DeviceExtension
->AdapterObject
)
681 /* From nonpaged pool if there is no DMA */
682 CommonBuffer
= ExAllocatePool(NonPagedPool
, CommonBufferLength
);
686 /* Perform a full request since we have a DMA adapter*/
691 /* Fail in case of error */
693 return STATUS_INSUFFICIENT_RESOURCES
;
696 RtlZeroMemory(CommonBuffer
, CommonBufferLength
);
698 /* Store its size in Device Extension */
699 DeviceExtension
->CommonBufferLength
= CommonBufferLength
;
701 /* SrbExtension buffer is located at the beginning of the buffer */
702 DeviceExtension
->SrbExtensionBuffer
= CommonBuffer
;
704 /* Non-cached extension buffer is located at the end of
708 CommonBufferLength
-= NonCachedSize
;
709 DeviceExtension
->NonCachedExtension
= (PUCHAR
)CommonBuffer
+ CommonBufferLength
;
713 DeviceExtension
->NonCachedExtension
= NULL
;
716 return STATUS_SUCCESS
;
721 ScsiPortGetUncachedExtension(
722 IN PVOID HwDeviceExtension
,
723 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
724 IN ULONG NumberOfBytes
)
726 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
727 DEVICE_DESCRIPTION DeviceDescription
;
728 ULONG MapRegistersCount
;
731 TRACE("ScsiPortGetUncachedExtension(%p %p %lu)\n",
732 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
734 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
736 /* Check for allocated common DMA buffer */
737 if (DeviceExtension
->SrbExtensionBuffer
!= NULL
)
742 /* Check for DMA adapter object */
743 if (DeviceExtension
->AdapterObject
== NULL
)
745 /* Initialize DMA adapter description */
746 RtlZeroMemory(&DeviceDescription
, sizeof(DEVICE_DESCRIPTION
));
748 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
749 DeviceDescription
.Master
= ConfigInfo
->Master
;
750 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
751 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
752 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
753 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
754 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
755 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
756 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
757 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
758 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
759 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
761 /* Get a DMA adapter object */
763 DeviceExtension
->AdapterObject
=
764 HalGetAdapter(&DeviceDescription
, &MapRegistersCount
);
766 /* Fail in case of error */
767 if (DeviceExtension
->AdapterObject
== NULL
)
772 MapRegistersCount
= 0;
775 /* Set number of physical breaks */
776 if (ConfigInfo
->NumberOfPhysicalBreaks
!= 0 &&
777 MapRegistersCount
> ConfigInfo
->NumberOfPhysicalBreaks
)
779 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
=
780 ConfigInfo
->NumberOfPhysicalBreaks
;
784 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
= MapRegistersCount
;
788 /* Update Srb extension size */
789 if (DeviceExtension
->SrbExtensionSize
!= ConfigInfo
->SrbExtensionSize
)
790 DeviceExtension
->SrbExtensionSize
= ConfigInfo
->SrbExtensionSize
;
792 /* Allocate a common DMA buffer */
793 Status
= SpiAllocateCommonBuffer(DeviceExtension
, NumberOfBytes
);
795 if (!NT_SUCCESS(Status
))
797 TRACE("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status
);
801 return DeviceExtension
->NonCachedExtension
;
806 ScsiPortGetVirtualAddress(
807 IN PVOID HwDeviceExtension
,
808 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
818 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
827 struct _DRIVE_LAYOUT_INFORMATION
*PartitionBuffer
;
828 CHAR PartitionName
[64];
830 /* Register device with partition(0) suffix */
831 RtlStringCbPrintfA(PartitionName
, sizeof(PartitionName
), "%spartition(0)", ArcName
);
832 FsRegisterDevice(PartitionName
, &DiskVtbl
);
834 /* Read device partition table */
835 Status
= ArcOpen(PartitionName
, OpenReadOnly
, &FileId
);
836 if (Status
== ESUCCESS
)
838 ret
= HALDISPATCH
->HalIoReadPartitionTable((PDEVICE_OBJECT
)FileId
, 512, FALSE
, &PartitionBuffer
);
841 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
++)
843 if (PartitionBuffer
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
845 RtlStringCbPrintfA(PartitionName
,
846 sizeof(PartitionName
),
849 PartitionBuffer
->PartitionEntry
[i
].PartitionNumber
);
850 FsRegisterDevice(PartitionName
, &DiskVtbl
);
853 ExFreePool(PartitionBuffer
);
862 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
867 PSCSI_REQUEST_BLOCK Srb
;
869 INQUIRYDATA InquiryBuffer
;
873 if (!DeviceExtension
->HwResetBus(DeviceExtension
->MiniPortDeviceExtension
, PathId
))
878 /* Remember the extension */
879 ScsiDeviceExtensions
[ScsiBus
] = DeviceExtension
;
881 for (TargetId
= 0; TargetId
< DeviceExtension
->MaxTargedIds
; TargetId
++)
886 TRACE("Scanning SCSI device %d.%d.%d\n",
887 ScsiBus
, TargetId
, Lun
);
889 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
892 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
893 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
894 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
895 Srb
->PathId
= PathId
;
896 Srb
->TargetId
= TargetId
;
899 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
900 Srb
->DataTransferLength
= INQUIRYDATABUFFERSIZE
;
901 Srb
->TimeOutValue
= 5; /* in seconds */
902 Srb
->DataBuffer
= &InquiryBuffer
;
903 Cdb
= (PCDB
)Srb
->Cdb
;
904 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
905 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= Srb
->Lun
;
906 Cdb
->CDB6INQUIRY
.AllocationLength
= (UCHAR
)Srb
->DataTransferLength
;
907 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
909 /* Don't check next LUNs */
913 /* Device exists, create its ARC name */
914 if (InquiryBuffer
.RemovableMedia
)
916 sprintf(ArcName
, "scsi(%ld)cdrom(%d)fdisk(%d)",
917 ScsiBus
, TargetId
, Lun
);
918 FsRegisterDevice(ArcName
, &DiskVtbl
);
922 sprintf(ArcName
, "scsi(%ld)disk(%d)rdisk(%d)",
923 ScsiBus
, TargetId
, Lun
);
924 /* Now, check if it has partitions */
925 SpiScanDevice(DeviceExtension
, ArcName
, PathId
, TargetId
, Lun
);
930 } while (Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
);
937 IN PHW_INITIALIZATION_DATA HwInitializationData
,
938 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
,
939 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
)
941 PACCESS_RANGE AccessRange
;
942 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData
;
948 /* Loop through all entries */
949 for (Index
= 0; Index
< ResourceDescriptor
->PartialResourceList
.Count
; Index
++)
951 PartialData
= &ResourceDescriptor
->PartialResourceList
.PartialDescriptors
[Index
];
953 switch (PartialData
->Type
)
955 case CmResourceTypePort
:
956 /* Copy access ranges */
957 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
959 TRACE("Got port at 0x%I64x, len 0x%x\n",
960 PartialData
->u
.Port
.Start
.QuadPart
, PartialData
->u
.Port
.Length
);
961 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
963 AccessRange
->RangeStart
= PartialData
->u
.Port
.Start
;
964 AccessRange
->RangeLength
= PartialData
->u
.Port
.Length
;
966 AccessRange
->RangeInMemory
= FALSE
;
971 case CmResourceTypeMemory
:
972 /* Copy access ranges */
973 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
975 TRACE("Got memory at 0x%I64x, len 0x%x\n",
976 PartialData
->u
.Memory
.Start
.QuadPart
, PartialData
->u
.Memory
.Length
);
977 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
979 AccessRange
->RangeStart
= PartialData
->u
.Memory
.Start
;
980 AccessRange
->RangeLength
= PartialData
->u
.Memory
.Length
;
982 AccessRange
->RangeInMemory
= TRUE
;
987 case CmResourceTypeInterrupt
:
988 /* Copy interrupt data */
989 TRACE("Got interrupt level %d, vector %d\n",
990 PartialData
->u
.Interrupt
.Level
, PartialData
->u
.Interrupt
.Vector
);
991 PortConfig
->BusInterruptLevel
= PartialData
->u
.Interrupt
.Level
;
992 PortConfig
->BusInterruptVector
= PartialData
->u
.Interrupt
.Vector
;
994 /* Set interrupt mode accordingly to the resource */
995 if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
997 PortConfig
->InterruptMode
= Latched
;
999 else if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
1001 PortConfig
->InterruptMode
= LevelSensitive
;
1005 case CmResourceTypeDma
:
1006 TRACE("Got DMA channel %d, port %d\n",
1007 PartialData
->u
.Dma
.Channel
, PartialData
->u
.Dma
.Port
);
1008 PortConfig
->DmaChannel
= PartialData
->u
.Dma
.Channel
;
1009 PortConfig
->DmaPort
= PartialData
->u
.Dma
.Port
;
1017 SpiGetPciConfigData(
1018 IN PHW_INITIALIZATION_DATA HwInitializationData
,
1019 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1021 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1023 PCI_COMMON_CONFIG PciConfig
;
1024 PCI_SLOT_NUMBER SlotNumber
;
1027 ULONG FunctionNumber
;
1028 CHAR VendorIdString
[8];
1029 CHAR DeviceIdString
[8];
1030 PCM_RESOURCE_LIST ResourceList
= NULL
;
1033 SlotNumber
.u
.AsULONG
= 0;
1035 /* Loop through all devices */
1036 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1038 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1040 /* Loop through all functions */
1041 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1043 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1045 /* Get PCI config bytes */
1046 DataSize
= HalGetBusDataByOffset(
1049 SlotNumber
.u
.AsULONG
,
1054 /* If result of HalGetBusData is 0, then the bus is wrong */
1058 /* If result is PCI_INVALID_VENDORID, then this device has no more
1060 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
1063 sprintf(VendorIdString
, "%04hx", PciConfig
.VendorID
);
1064 sprintf(DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1066 if (_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) ||
1067 _strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1069 /* It is not our device */
1073 TRACE( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1074 PciConfig
.VendorID
, PciConfig
.DeviceID
,
1076 SlotNumber
.u
.bits
.DeviceNumber
, SlotNumber
.u
.bits
.FunctionNumber
);
1078 Status
= HalAssignSlotResources(NULL
,
1084 SlotNumber
.u
.AsULONG
,
1087 if (!NT_SUCCESS(Status
))
1090 /* Create configuration information */
1091 SpiResourceToConfig(HwInitializationData
,
1095 /* Free the resource list */
1096 ExFreePool(ResourceList
);
1098 /* Set dev & fn numbers */
1099 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1100 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
+ 1;
1102 /* Save the slot number */
1103 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1107 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1110 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1120 IN PHW_INITIALIZATION_DATA HwInitializationData
,
1121 IN PVOID HwContext OPTIONAL
)
1123 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1124 ULONG DeviceExtensionSize
;
1125 PORT_CONFIGURATION_INFORMATION PortConfig
;
1127 BOOLEAN FirstConfigCall
= TRUE
;
1128 PCI_SLOT_NUMBER SlotNumber
;
1132 if (HwInitializationData
->HwInitializationDataSize
!= sizeof(HW_INITIALIZATION_DATA
))
1134 return STATUS_INVALID_PARAMETER
;
1137 /* Check params for validity */
1138 if ((HwInitializationData
->HwInitialize
== NULL
) ||
1139 (HwInitializationData
->HwStartIo
== NULL
) ||
1140 (HwInitializationData
->HwInterrupt
== NULL
) ||
1141 (HwInitializationData
->HwFindAdapter
== NULL
) ||
1142 (HwInitializationData
->HwResetBus
== NULL
))
1144 return STATUS_INVALID_PARAMETER
;
1147 /* Zero starting slot number */
1148 SlotNumber
.u
.AsULONG
= 0;
1154 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) + HwInitializationData
->DeviceExtensionSize
;
1155 DeviceExtension
= FrLdrTempAlloc(DeviceExtensionSize
, TAG_SCSI_DEVEXT
);
1156 if (!DeviceExtension
)
1158 return STATUS_NO_MEMORY
;
1160 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
1161 DeviceExtension
->InterruptFlags
= SCSI_PORT_NEXT_REQUEST_READY
;
1162 DeviceExtension
->HwInitialize
= HwInitializationData
->HwInitialize
;
1163 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
1164 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
1165 DeviceExtension
->HwResetBus
= HwInitializationData
->HwResetBus
;
1166 DeviceExtension
->MiniPortDeviceExtension
= (PVOID
)(DeviceExtension
+ 1);
1168 Status
= SpiCreatePortConfig(DeviceExtension
,
1169 HwInitializationData
,
1172 if (Status
!= STATUS_SUCCESS
)
1174 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1178 PortConfig
.NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
1179 PortConfig
.AccessRanges
= FrLdrTempAlloc(sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
,
1180 TAG_SCSI_ACCESS_RANGES
);
1181 if (!PortConfig
.AccessRanges
)
1183 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1184 return STATUS_NO_MEMORY
;
1186 RtlZeroMemory(PortConfig
.AccessRanges
, sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1188 /* Search for matching PCI device */
1189 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
1190 (HwInitializationData
->VendorIdLength
> 0) &&
1191 (HwInitializationData
->VendorId
!= NULL
) &&
1192 (HwInitializationData
->DeviceIdLength
> 0) &&
1193 (HwInitializationData
->DeviceId
!= NULL
))
1195 PortConfig
.BusInterruptLevel
= 0;
1197 /* Get PCI device data */
1198 TRACE("VendorId '%.*s' DeviceId '%.*s'\n",
1199 HwInitializationData
->VendorIdLength
,
1200 HwInitializationData
->VendorId
,
1201 HwInitializationData
->DeviceIdLength
,
1202 HwInitializationData
->DeviceId
);
1204 if (!SpiGetPciConfigData(HwInitializationData
,
1209 /* Continue to the next bus, nothing here */
1210 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1211 return STATUS_INTERNAL_ERROR
;
1214 if (!PortConfig
.BusInterruptLevel
)
1216 /* Bypass this slot, because no interrupt was assigned */
1217 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1218 return STATUS_INTERNAL_ERROR
;
1222 if (HwInitializationData
->HwFindAdapter(
1223 DeviceExtension
->MiniPortDeviceExtension
,
1228 &Again
) != SP_RETURN_FOUND
)
1230 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1231 return STATUS_INTERNAL_ERROR
;
1234 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1235 if (PortConfig
.MaximumNumberOfTargets
> SCSI_MAXIMUM_TARGETS_PER_BUS
)
1236 DeviceExtension
->MaxTargedIds
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
1238 DeviceExtension
->MaxTargedIds
= PortConfig
.MaximumNumberOfTargets
;
1240 DeviceExtension
->BusNum
= PortConfig
.SystemIoBusNumber
;
1242 TRACE("Adapter found: buses = %d, targets = %d\n",
1243 PortConfig
.NumberOfBuses
, DeviceExtension
->MaxTargedIds
);
1245 /* Initialize adapter */
1246 if (!DeviceExtension
->HwInitialize(DeviceExtension
->MiniPortDeviceExtension
))
1248 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1249 return STATUS_INTERNAL_ERROR
;
1253 for (ScsiBus
= 0; ScsiBus
< PortConfig
.NumberOfBuses
; ScsiBus
++)
1255 SpiScanAdapter(DeviceExtension
, PortConfig
.SystemIoBusNumber
, ScsiBus
);
1256 PortConfig
.SystemIoBusNumber
++;
1259 FirstConfigCall
= FALSE
;
1266 return STATUS_SUCCESS
;
1271 ScsiPortIoMapTransfer(
1272 IN PVOID HwDeviceExtension
,
1273 IN PSCSI_REQUEST_BLOCK Srb
,
1274 IN PVOID LogicalAddress
,
1284 IN PVOID HwDeviceExtension
,
1285 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1299 IN PVOID WriteBuffer
,
1300 IN PVOID ReadBuffer
,
1303 RtlMoveMemory(WriteBuffer
, ReadBuffer
, Length
);
1308 ScsiPortNotification(
1309 IN SCSI_NOTIFICATION_TYPE NotificationType
,
1310 IN PVOID HwDeviceExtension
,
1313 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1314 PSCSI_REQUEST_BLOCK Srb
;
1317 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
1319 va_start(ap
, HwDeviceExtension
);
1321 switch (NotificationType
)
1323 case RequestComplete
:
1324 /* Mask the SRB as completed */
1325 Srb
= va_arg(ap
, PSCSI_REQUEST_BLOCK
);
1326 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1330 /* Say that device is ready */
1331 DeviceExtension
->InterruptFlags
|= SCSI_PORT_NEXT_REQUEST_READY
;
1344 ScsiPortReadPortBufferUchar(
1349 __inbytestring(H2I(Port
), Buffer
, Count
);
1354 ScsiPortReadPortBufferUlong(
1359 __indwordstring(H2I(Port
), Buffer
, Count
);
1364 ScsiPortReadPortBufferUshort(
1369 __inwordstring(H2I(Port
), Buffer
, Count
);
1374 ScsiPortReadPortUchar(
1377 TRACE("ScsiPortReadPortUchar(%p)\n", Port
);
1379 return READ_PORT_UCHAR(Port
);
1384 ScsiPortReadPortUlong(
1387 return READ_PORT_ULONG(Port
);
1392 ScsiPortReadPortUshort(
1395 return READ_PORT_USHORT(Port
);
1400 ScsiPortReadRegisterBufferUchar(
1411 ScsiPortReadRegisterBufferUlong(
1422 ScsiPortReadRegisterBufferUshort(
1423 IN PUSHORT Register
,
1433 ScsiPortReadRegisterUchar(
1436 return READ_REGISTER_UCHAR(Register
);
1441 ScsiPortReadRegisterUlong(
1444 return READ_REGISTER_ULONG(Register
);
1449 ScsiPortReadRegisterUshort(
1450 IN PUSHORT Register
)
1452 return READ_REGISTER_USHORT(Register
);
1457 ScsiPortSetBusDataByOffset(
1458 IN PVOID DeviceExtension
,
1459 IN ULONG BusDataType
,
1460 IN ULONG SystemIoBusNumber
,
1461 IN ULONG SlotNumber
,
1473 ScsiPortStallExecution(
1476 KeStallExecutionProcessor(Delay
);
1481 ScsiPortValidateRange(
1482 IN PVOID HwDeviceExtension
,
1483 IN INTERFACE_TYPE BusType
,
1484 IN ULONG SystemIoBusNumber
,
1485 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1486 IN ULONG NumberOfBytes
,
1487 IN BOOLEAN InIoSpace
)
1501 ScsiPortWritePortBufferUchar(
1506 __outbytestring(H2I(Port
), Buffer
, Count
);
1511 ScsiPortWritePortBufferUlong(
1516 __outdwordstring(H2I(Port
), Buffer
, Count
);
1521 ScsiPortWritePortBufferUshort(
1526 __outwordstring(H2I(Port
), Buffer
, Count
);
1531 ScsiPortWritePortUchar(
1535 WRITE_PORT_UCHAR(Port
, Value
);
1540 ScsiPortWritePortUlong(
1544 WRITE_PORT_ULONG(Port
, Value
);
1549 ScsiPortWritePortUshort(
1553 WRITE_PORT_USHORT(Port
, Value
);
1558 ScsiPortWriteRegisterBufferUchar(
1569 ScsiPortWriteRegisterBufferUlong(
1580 ScsiPortWriteRegisterBufferUshort(
1581 IN PUSHORT Register
,
1591 ScsiPortWriteRegisterUchar(
1595 WRITE_REGISTER_UCHAR(Register
, Value
);
1600 ScsiPortWriteRegisterUlong(
1604 WRITE_REGISTER_ULONG(Register
, Value
);
1609 ScsiPortWriteRegisterUshort(
1610 IN PUSHORT Register
,
1613 WRITE_REGISTER_USHORT(Register
, Value
);
1616 extern char __ImageBase
;
1619 LoadBootDeviceDriver(VOID
)
1621 PIMAGE_NT_HEADERS NtHeaders
;
1622 LIST_ENTRY ModuleListHead
;
1623 PIMAGE_IMPORT_DESCRIPTOR ImportTable
;
1624 ULONG ImportTableSize
;
1625 PLDR_DATA_TABLE_ENTRY BootDdDTE
, FreeldrDTE
;
1626 CHAR NtBootDdPath
[MAX_PATH
];
1627 PVOID ImageBase
= NULL
;
1628 ULONG (NTAPI
*EntryPoint
)(IN PVOID DriverObject
, IN PVOID RegistryPath
);
1631 // FIXME: Must be done *INSIDE* the HAL!
1633 HalpInitializePciStubs();
1634 HalpInitBusHandler();
1637 /* Initialize the loaded module list */
1638 InitializeListHead(&ModuleListHead
);
1640 /* Create full ntbootdd.sys path */
1641 strcpy(NtBootDdPath
, FrLdrBootPath
);
1642 strcat(NtBootDdPath
, "\\NTBOOTDD.SYS");
1645 Success
= PeLdrLoadImage(NtBootDdPath
, LoaderBootDriver
, &ImageBase
);
1648 /* That's OK. File simply doesn't exist */
1652 /* Allocate a DTE for ntbootdd */
1653 Success
= PeLdrAllocateDataTableEntry(&ModuleListHead
, "ntbootdd.sys",
1654 "NTBOOTDD.SYS", ImageBase
, &BootDdDTE
);
1658 /* Add the PE part of freeldr.sys to the list of loaded executables, it
1659 contains ScsiPort* exports, imported by ntbootdd.sys */
1660 Success
= PeLdrAllocateDataTableEntry(&ModuleListHead
, "scsiport.sys",
1661 "FREELDR.SYS", &__ImageBase
, &FreeldrDTE
);
1664 RemoveEntryList(&BootDdDTE
->InLoadOrderLinks
);
1669 Success
= PeLdrScanImportDescriptorTable(&ModuleListHead
, "", BootDdDTE
);
1671 /* Now unlinkt the DTEs, they won't be valid later */
1672 RemoveEntryList(&BootDdDTE
->InLoadOrderLinks
);
1673 RemoveEntryList(&FreeldrDTE
->InLoadOrderLinks
);
1678 /* Change imports to PA */
1679 ImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE
->DllBase
),
1680 TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &ImportTableSize
);
1681 for (;(ImportTable
->Name
!= 0) && (ImportTable
->FirstThunk
!= 0);ImportTable
++)
1683 PIMAGE_THUNK_DATA ThunkData
= (PIMAGE_THUNK_DATA
)VaToPa(RVA(BootDdDTE
->DllBase
, ImportTable
->FirstThunk
));
1685 while (((PIMAGE_THUNK_DATA
)ThunkData
)->u1
.AddressOfData
!= 0)
1687 ThunkData
->u1
.Function
= (ULONG
)VaToPa((PVOID
)ThunkData
->u1
.Function
);
1692 /* Relocate image to PA */
1693 NtHeaders
= RtlImageNtHeader(VaToPa(BootDdDTE
->DllBase
));
1696 Success
= (BOOLEAN
)LdrRelocateImageWithBias(VaToPa(BootDdDTE
->DllBase
),
1697 NtHeaders
->OptionalHeader
.ImageBase
- (ULONG_PTR
)BootDdDTE
->DllBase
,
1700 TRUE
, /* in case of conflict still return success */
1705 /* Call the entrypoint */
1706 EntryPoint
= VaToPa(BootDdDTE
->EntryPoint
);
1707 (*EntryPoint
)(NULL
, NULL
);