Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2811 lines
68 KiB

  1. /*++
  2. Copyright (c) 1992-2001 Microsoft Corporation
  3. Module Name:
  4. drive.cxx
  5. --*/
  6. #include <pch.cxx>
  7. #define _NTAPI_ULIB_
  8. #define _IFSUTIL_MEMBER_
  9. #include "ulib.hxx"
  10. #include "ifsutil.hxx"
  11. #if 0
  12. #include "error.hxx"
  13. #include "drive.hxx"
  14. #include "rtmsg.h"
  15. #include "message.hxx"
  16. #include "numset.hxx"
  17. #include "dcache.hxx"
  18. #include "hmem.hxx"
  19. #include "ifssys.hxx"
  20. #endif
  21. #if !defined( _EFICHECK_ )
  22. extern "C" {
  23. #include <stdio.h>
  24. #include <ntdddisk.h>
  25. };
  26. #endif
  27. //#define TRAP_A_WRITE 1
  28. //#define TRAP_A_READ 1
  29. // Don't lock down more that 64K for IO.
  30. CONST MaxIoSize = 65536;
  31. DEFINE_CONSTRUCTOR( DRIVE, OBJECT );
  32. VOID
  33. DRIVE::Construct (
  34. )
  35. /*++
  36. Routine Description:
  37. Contructor for DRIVE.
  38. Arguments:
  39. None.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. // unreferenced parameters
  45. (void)(this);
  46. }
  47. DRIVE::~DRIVE(
  48. )
  49. /*++
  50. Routine Description:
  51. Destructor for DRIVE.
  52. Arguments:
  53. None.
  54. Return Value:
  55. None.
  56. --*/
  57. {
  58. Destroy();
  59. }
  60. BOOLEAN
  61. DRIVE::Initialize(
  62. IN PCWSTRING NtDriveName,
  63. IN OUT PMESSAGE Message
  64. )
  65. /*++
  66. Routine Description:
  67. This routine initializes a drive object.
  68. Arguments:
  69. NtDriveName - Supplies an NT style drive name.
  70. Message - Supplies an outlet for messages.
  71. Return Value:
  72. FALSE - Failure.
  73. TRUE - Success.
  74. --*/
  75. {
  76. Destroy();
  77. if (!NtDriveName) {
  78. Destroy();
  79. return FALSE;
  80. }
  81. if (!_name.Initialize(NtDriveName)) {
  82. Destroy();
  83. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  84. return FALSE;
  85. }
  86. return TRUE;
  87. }
  88. VOID
  89. DRIVE::Destroy(
  90. )
  91. /*++
  92. Routine Description:
  93. This routine returns a DRIVE object to its initial state.
  94. Arguments:
  95. None.
  96. Return Value:
  97. None.
  98. --*/
  99. {
  100. // unreferenced parameters
  101. (void)(this);
  102. }
  103. DEFINE_EXPORTED_CONSTRUCTOR( DP_DRIVE, DRIVE, IFSUTIL_EXPORT );
  104. VOID
  105. DP_DRIVE::Construct (
  106. )
  107. /*++
  108. Routine Description:
  109. Constructor for DP_DRIVE.
  110. Arguments:
  111. None.
  112. Return Value:
  113. None.
  114. --*/
  115. {
  116. memset(&_actual, 0, sizeof(DRTYPE));
  117. _supported_list = NULL;
  118. _num_supported = 0;
  119. _alignment_mask = 0;
  120. _last_status = 0;
  121. _handle = 0;
  122. _alternate_handle = 0;
  123. _hosted_drive = FALSE;
  124. _super_floppy = FALSE;
  125. _is_writeable = FALSE;
  126. _block_io = NULL;
  127. _disk_io = NULL;
  128. }
  129. IFSUTIL_EXPORT
  130. DP_DRIVE::~DP_DRIVE(
  131. )
  132. /*++
  133. Routine Description:
  134. Destructor for DP_DRIVE.
  135. Arguments:
  136. None.
  137. Return Value:
  138. None.
  139. --*/
  140. {
  141. Destroy();
  142. }
  143. NTSTATUS
  144. DP_DRIVE::OpenDrive(
  145. IN PCWSTRING NtDriveName,
  146. IN ACCESS_MASK DesiredAccess,
  147. IN BOOLEAN ExclusiveWrite,
  148. #if defined(_EFICHECK_)
  149. OUT EFI_BLOCK_IO ** BlockIoPtr,
  150. OUT EFI_DISK_IO ** DiskIoPtr,
  151. #else
  152. OUT PHANDLE Handle,
  153. OUT PHANDLE Handle,
  154. #endif
  155. OUT PULONG Alignment,
  156. IN OUT PMESSAGE Message
  157. )
  158. /*++
  159. Routine Description:
  160. This method is a worker function for the Initialize methods,
  161. to open a volume and determine its alignment requirement.
  162. Arguments:
  163. NtDriveName - Supplies the name of the drive.
  164. DesiredAccess - Supplies the access the client desires to the volume.
  165. ExclusiveWrite - Supplies a flag indicating whether the client
  166. wishes to exclude other write handles.
  167. Handle - Receives the handle to the opened volume.
  168. Alignment - Receives the alignment requirement for the volume.
  169. Message - Supplies an outlet for messages.
  170. Return Value:
  171. TRUE upon successful completion.
  172. --*/
  173. {
  174. DEBUG((D_INFO,(CHAR8*)"Entering OpenDrive.\n"));
  175. WSTR * origName = (WSTR*)NtDriveName->GetWSTR();
  176. EFI_DEVICE_PATH * devPath = NULL;
  177. EFI_DEVICE_PATH * devPathPos = NULL;
  178. EFI_DEVICE_PATH * newDevPath = NULL;
  179. EFI_DEVICE_PATH * nextDevPath;
  180. EFI_GUID blk_io_guid = BLOCK_IO_PROTOCOL;
  181. EFI_GUID dsk_io_guid = DISK_IO_PROTOCOL;
  182. EFI_HANDLE handle = NULL;
  183. EFI_STATUS status;
  184. // first we get the device path from the corresponding name
  185. DEBUG((D_INFO,(CHAR8*)"Attempting to open %s\n", origName ));
  186. devPath = (EFI_DEVICE_PATH*)ShellGetMap(origName);
  187. if( devPath == NULL ) {
  188. DEBUG((D_ERROR,(CHAR8*)"DP_DRIVE::OpenDrive was passed a bogus device name.\n"));
  189. return STATUS_INVALID_PARAMETER;
  190. }
  191. DEBUG((D_INFO,(CHAR8*)"Mapped to %s\n",DevicePathToStr(devPath)));
  192. // now we query to see if the device supports BLOCK_IO
  193. devPathPos = devPath;
  194. // LocateDevicePath advances the pointer
  195. status = BS->LocateDevicePath(
  196. &blk_io_guid,
  197. &devPathPos, // this is an IN OUT param
  198. &handle
  199. );
  200. if( status != EFI_SUCCESS ) {
  201. // we were passed a bogus drive path
  202. DEBUG((D_ERROR,(CHAR8*)"DP_DRIVE::OpenDrive was passed a bogus device name.\n"));
  203. return STATUS_INVALID_PARAMETER;
  204. }
  205. // now we retrieve the interface pointer from the object
  206. BS->HandleProtocol(handle, &blk_io_guid, (VOID**)BlockIoPtr);
  207. BS->HandleProtocol(handle, &dsk_io_guid, (VOID**)DiskIoPtr);
  208. if( (*BlockIoPtr)->Media->IoAlign == 0 ) {
  209. // the IoAlign field can't be zero! we are always at least byte aligned.
  210. return STATUS_UNSUCCESSFUL;
  211. }
  212. *Alignment = (*BlockIoPtr)->Media->IoAlign - 1;
  213. DEBUG((D_INFO,(CHAR8*)"Io Alignment mask is %d\n", *Alignment ));
  214. //
  215. // While we are here lets get some things we will need for twiddling the
  216. // partition table later on.
  217. //
  218. newDevPath = DuplicateDevicePath( devPath );
  219. if ( !newDevPath ) {
  220. DEBUG((D_ERROR,(CHAR8*)"DP_DRIVE::OpenDrive failed to get MBR device.\n"));
  221. return STATUS_UNSUCCESSFUL;
  222. }
  223. //
  224. // We have a copy of the partition device path. Now cut that down to just the
  225. // device file path.
  226. //
  227. nextDevPath = newDevPath;
  228. while (DevicePathType(nextDevPath) != MEDIA_DEVICE_PATH &&
  229. DevicePathType(nextDevPath) != END_DEVICE_PATH_TYPE) {
  230. DEBUG((D_INFO,(CHAR8*)"NextDevPath: %d,%d,%d,%s\n",
  231. nextDevPath->Type,
  232. nextDevPath->SubType,
  233. *(USHORT*)nextDevPath->Length,
  234. DevicePathToStr(nextDevPath)));
  235. nextDevPath = NextDevicePathNode( nextDevPath );
  236. }
  237. DEBUG((D_INFO,(CHAR8*)"Final nextDevPath: %d,%d,%d\n",
  238. nextDevPath->Type,
  239. nextDevPath->SubType,
  240. *(USHORT*)nextDevPath->Length));
  241. if (DevicePathType(nextDevPath) != END_DEVICE_PATH_TYPE) {
  242. //
  243. // Get the partition number before we destroy this
  244. //
  245. _partition_number = ( ( UNALIGNED HARDDRIVE_DEVICE_PATH * ) nextDevPath ) -> PartitionNumber;
  246. DEBUG((D_INFO,(CHAR8*)"Partition Number %d\n", _partition_number));
  247. SetDevicePathEndNode( nextDevPath );
  248. } else {
  249. DEBUG((D_INFO,(CHAR8*)"There is no partition\n"));
  250. _partition_number = 0;
  251. }
  252. //
  253. // Get the BLOCK_IO_PROTOCOL for the base disk device
  254. //
  255. devPathPos = newDevPath; // LocateDevicePath advances the pointer
  256. status = BS->LocateDevicePath(
  257. &blk_io_guid,
  258. &devPathPos, // this is an IN OUT param
  259. &handle
  260. );
  261. if( status != EFI_SUCCESS ) {
  262. // we were passed a bogus drive path
  263. DEBUG((D_ERROR,(CHAR8*)"DP_DRIVE::OpenDrive couldn't get base disk block_io.\n"));
  264. return STATUS_UNSUCCESSFUL;
  265. }
  266. // now we retrieve the interface pointer from the object
  267. BS->HandleProtocol(handle, &blk_io_guid, (VOID**)&_device_block_io);
  268. BS->HandleProtocol(handle, &dsk_io_guid, (VOID**)&_device_disk_io);
  269. DEBUG((D_INFO,(CHAR8*)"Leaving OpenDrive.\n"));
  270. return STATUS_SUCCESS;
  271. }
  272. IFSUTIL_EXPORT
  273. BOOLEAN
  274. DP_DRIVE::Initialize(
  275. IN PCWSTRING NtDriveName,
  276. IN OUT PMESSAGE Message,
  277. IN BOOLEAN IsTransient,
  278. IN BOOLEAN ExclusiveWrite
  279. )
  280. /*++
  281. Routine Description:
  282. This routine initializes a DP_DRIVE object based on the supplied drive
  283. path.
  284. Arguments:
  285. NtDriveName - Supplies the drive path.
  286. Message - Supplies an outlet for messages.
  287. IsTransient - Supplies whether or not to keep the handle to the
  288. drive open beyond this method.
  289. ExclusiveWrite - Supplies whether or not to open the drive for
  290. exclusive write.
  291. Return Value:
  292. FALSE - Failure.
  293. TRUE - Success.
  294. --*/
  295. {
  296. CONST NumMediaTypes = 20;
  297. DISK_GEOMETRY disk_geometry;
  298. PARTITION_INFORMATION partition_info;
  299. BOOLEAN partition;
  300. MSGID MessageId;
  301. Destroy();
  302. DEBUG((D_INFO,(CHAR8*)"Entering DP_DRIVE::Initialize\n"));
  303. if (!DRIVE::Initialize(NtDriveName, Message)) {
  304. Destroy();
  305. return FALSE;
  306. }
  307. _last_status = OpenDrive( NtDriveName,
  308. NULL, // EFI: doesn't have access permissions.
  309. ExclusiveWrite, // EFI: this will be ignored for EFI.
  310. &_block_io, // EFI: this will return an interface pointer
  311. &_disk_io,
  312. &_alignment_mask, // EFI: this will return the correct alignment mask.
  313. Message );
  314. if(!NT_SUCCESS(_last_status)) {
  315. Destroy();
  316. DEBUG((D_ERROR,(CHAR8*)"IFSUTIL: Can't open drive. Status returned = %x.\n", _last_status));
  317. MessageId = MSG_CANT_DASD;
  318. Message ? Message->Set(MessageId) : 1;
  319. Message ? Message->Display() : 1;
  320. return FALSE;
  321. }
  322. _is_writeable = !(_block_io->Media->ReadOnly);
  323. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: _is_writeable %d\n", !(_block_io->Media->ReadOnly)));
  324. _media_id = _block_io->Media->MediaId;
  325. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: _media_id %d\n", _block_io->Media->MediaId));
  326. //
  327. // Record that this is not a hosted volume:
  328. //
  329. _hosted_drive = FALSE;
  330. if( !(_block_io->Media->MediaPresent) ) {
  331. MessageId = MSG_CANT_DASD;
  332. Message ? Message->DisplayMsg(MessageId) : 1;
  333. return FALSE;
  334. }
  335. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: MediaPresent %d\n", _block_io->Media->MediaPresent));
  336. // BUGBUG in EFI we can't get the exact media type, should we care?
  337. memset(&disk_geometry, 0, sizeof(DISK_GEOMETRY));
  338. disk_geometry.MediaType = Unknown;
  339. partition = (_block_io->Media->LogicalPartition);
  340. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: IsPartition %d\n", _block_io->Media->LogicalPartition));
  341. #if 0
  342. // BUGBUG Try to read the partition entry.
  343. if (disk_geometry.MediaType == FixedMedia ||
  344. disk_geometry.MediaType == RemovableMedia) {
  345. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  346. &status_block,
  347. IOCTL_DISK_GET_PARTITION_INFO,
  348. NULL, 0, &partition_info,
  349. sizeof(PARTITION_INFORMATION));
  350. partition = (BOOLEAN) NT_SUCCESS(_last_status);
  351. if (!NT_SUCCESS(_last_status) &&
  352. _last_status != STATUS_INVALID_DEVICE_REQUEST) {
  353. DebugPrintTrace(("IFSUTIL: Can't read partition entry. Status returned = %x.\n", _last_status));
  354. Destroy();
  355. Message ? Message->DisplayMsg(MSG_READ_PARTITION_TABLE) : 1;
  356. return FALSE;
  357. }
  358. }
  359. #endif // removed for EFI
  360. disk_geometry.MediaType = (_block_io->Media->RemovableMedia) ? RemovableMedia : FixedMedia;
  361. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: MediaType %x\n", disk_geometry.MediaType));
  362. disk_geometry.BytesPerSector = _block_io->Media->BlockSize;
  363. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: blocksize %x\n", disk_geometry.BytesPerSector));
  364. // I fake the cylinder count
  365. disk_geometry.Cylinders.QuadPart = (ULONGLONG)(_block_io->Media->LastBlock)+1;
  366. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: cylcount %x\n", disk_geometry.Cylinders.QuadPart));
  367. disk_geometry.SectorsPerTrack = 1;
  368. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: sec/trk %x\n", disk_geometry.SectorsPerTrack));
  369. disk_geometry.TracksPerCylinder = 1;
  370. DEBUG((D_INFO,(CHAR8*)"DP_DRIVE::Initialize: trk/cyl %x\n", disk_geometry.TracksPerCylinder));
  371. partition_info.BootIndicator = FALSE;
  372. partition_info.HiddenSectors = 0;
  373. partition_info.PartitionLength.QuadPart = ((ULONGLONG)_block_io->Media->LastBlock+1) * (ULONGLONG)_block_io->Media->BlockSize;
  374. partition_info.PartitionNumber = 1;
  375. partition_info.PartitionType = 0xEF; // BUGBUG need a const
  376. partition_info.RecognizedPartition = TRUE;
  377. partition_info.RewritePartition = FALSE;
  378. partition_info.StartingOffset.QuadPart = (ULONGLONG)0;
  379. DEBUG((D_INFO, (CHAR8*)"DP_DRIVE:: Initialize: PartitionLength %x\n", partition_info.PartitionLength.QuadPart));
  380. // Store the information in the class.
  381. if (partition) {
  382. DiskGeometryToDriveType(&disk_geometry,
  383. partition_info.PartitionLength/
  384. disk_geometry.BytesPerSector,
  385. partition_info.HiddenSectors,
  386. &_actual);
  387. } else {
  388. DiskGeometryToDriveType(&disk_geometry, &_actual);
  389. #if 0
  390. if (IsFloppy()) {
  391. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  392. &status_block,
  393. IOCTL_DISK_GET_MEDIA_TYPES,
  394. NULL, 0, media_types,
  395. NumMediaTypes*
  396. sizeof(DISK_GEOMETRY));
  397. if (!NT_SUCCESS(_last_status)) {
  398. Destroy();
  399. if (Message) {
  400. MSGID MessageId;
  401. switch (_last_status) {
  402. case STATUS_NO_MEDIA_IN_DEVICE:
  403. MessageId = MSG_FORMAT_NO_MEDIA_IN_DRIVE;
  404. break;
  405. case STATUS_DEVICE_BUSY:
  406. case STATUS_DEVICE_NOT_READY:
  407. MessageId = MSG_DEVICE_BUSY;
  408. break;
  409. default:
  410. MessageId = MSG_BAD_IOCTL;
  411. break;
  412. }
  413. Message->DisplayMsg(MessageId);
  414. }
  415. return FALSE;
  416. }
  417. _num_supported = (INT) (status_block.Information/
  418. sizeof(DISK_GEOMETRY));
  419. if (!_num_supported) {
  420. Destroy();
  421. if (Message) {
  422. Message->DisplayMsg(MSG_BAD_IOCTL);
  423. }
  424. return FALSE;
  425. }
  426. if (!(_supported_list = NEW DRTYPE[_num_supported])) {
  427. Destroy();
  428. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  429. return FALSE;
  430. }
  431. for (i = 0; i < _num_supported; i++) {
  432. DiskGeometryToDriveType(&media_types[i], &_supported_list[i]);
  433. }
  434. }
  435. #endif
  436. }
  437. if (!_num_supported) {
  438. _num_supported = 1;
  439. if (!(_supported_list = NEW DRTYPE[1])) {
  440. Destroy();
  441. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  442. return FALSE;
  443. }
  444. _supported_list[0] = _actual;
  445. }
  446. //
  447. // Determine whether the media is a super-floppy; non-floppy
  448. // removable media which is not partitioned. Such media will
  449. // have but a single partition, normal media will have at least 4.
  450. //
  451. // BUGBUG removed for EFI
  452. #if 0
  453. if (disk_geometry.MediaType == RemovableMedia) {
  454. CONST INT EntriesPerBootRecord = 4;
  455. CONST INT MaxLogicalVolumes = 23;
  456. CONST INT Length = sizeof(DRIVE_LAYOUT_INFORMATION) +
  457. EntriesPerBootRecord * (MaxLogicalVolumes + 1) *
  458. sizeof(PARTITION_INFORMATION);
  459. UCHAR buf[Length];
  460. DRIVE_LAYOUT_INFORMATION *layout_info = (DRIVE_LAYOUT_INFORMATION *)buf;
  461. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  462. &status_block,
  463. IOCTL_DISK_GET_DRIVE_LAYOUT,
  464. NULL, 0, layout_info,
  465. Length);
  466. if (!NT_SUCCESS(_last_status)) {
  467. Destroy();
  468. if (Message) {
  469. MSGID MessageId;
  470. switch (_last_status) {
  471. case STATUS_NO_MEDIA_IN_DEVICE:
  472. MessageId = MSG_FORMAT_NO_MEDIA_IN_DRIVE;
  473. break;
  474. case STATUS_DEVICE_BUSY:
  475. case STATUS_DEVICE_NOT_READY:
  476. MessageId = MSG_DEVICE_BUSY;
  477. break;
  478. default:
  479. MessageId = MSG_BAD_IOCTL;
  480. break;
  481. }
  482. Message->DisplayMsg(MessageId);
  483. }
  484. return FALSE;
  485. }
  486. if (layout_info->PartitionCount < 4) {
  487. _super_floppy = TRUE;
  488. }
  489. }
  490. if (!IsTransient) {
  491. NtClose(_handle);
  492. _handle = 0;
  493. }
  494. #endif // removed for EFI
  495. DEBUG((D_INFO,(CHAR8*)"Leaving DP_DRIVE::Initialize\n"));
  496. return TRUE;
  497. }
  498. IFSUTIL_EXPORT
  499. BOOLEAN
  500. DP_DRIVE::Initialize(
  501. IN PCWSTRING NtDriveName,
  502. IN PCWSTRING HostFileName,
  503. IN OUT PMESSAGE Message,
  504. IN BOOLEAN IsTransient,
  505. IN BOOLEAN ExclusiveWrite
  506. )
  507. /*++
  508. Routine Description:
  509. This method initializes a hosted drive, i.e. a volume which
  510. is implemented as a file on another volume. Instead of opening
  511. this file by its actual name, we open it by the host file name,
  512. to prevent interactions with the file system.
  513. Arguments:
  514. NtDriveName - Supplies the NT name of the drive itself.
  515. HostFileName - Supplies the fully qualified name of the file
  516. which contains this drive.
  517. Message - Supplies an outlet for messages.
  518. IsTransient - Supplies whether or not to keep the handle to the
  519. drive open beyond this method.
  520. ExclusiveWrite - Supplies whether or not to open the drive for
  521. exclusive write.
  522. Return Value:
  523. TRUE upon successful completion.
  524. --*/
  525. {
  526. // removed hosted support for EFI
  527. #if 0
  528. FILE_STANDARD_INFORMATION FileStandardInfo;
  529. IO_STATUS_BLOCK StatusBlock;
  530. BIG_INT Sectors, FileSize;
  531. ULONG AlignmentMask, ExtraUlong;
  532. Destroy();
  533. if( !DRIVE::Initialize(HostFileName, Message)) {
  534. Destroy();
  535. return FALSE;
  536. }
  537. _hosted_drive = TRUE;
  538. // First, make the host file not-readonly.
  539. //
  540. if( !IFS_SYSTEM::FileSetAttributes( HostFileName,
  541. FILE_ATTRIBUTE_NORMAL,
  542. &_old_attributes ) ) {
  543. Message ? Message->DisplayMsg( MSG_CANT_DASD ) : 1;
  544. Destroy();
  545. return FALSE;
  546. }
  547. _last_status = OpenDrive( HostFileName,
  548. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA |
  549. FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
  550. ExclusiveWrite,
  551. &_handle,
  552. &_alignment_mask,
  553. Message );
  554. if( !NT_SUCCESS( _last_status ) ) {
  555. IFS_SYSTEM::FileSetAttributes( HostFileName,
  556. _old_attributes,
  557. &ExtraUlong );
  558. DEBUG((D_ERROR,(CHAR8*)"IFSUTIL: Can't open drive. Status returned = %x.\n", _last_status));
  559. Destroy();
  560. return FALSE;
  561. }
  562. if( NtDriveName ) {
  563. _last_status = OpenDrive( NtDriveName,
  564. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  565. ExclusiveWrite,
  566. &_alternate_handle,
  567. &AlignmentMask,
  568. Message );
  569. }
  570. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  571. &StatusBlock,
  572. IOCTL_DISK_IS_WRITABLE,
  573. NULL, 0, NULL, 0);
  574. _is_writeable = (_last_status != STATUS_MEDIA_WRITE_PROTECTED);
  575. // Fill in the drive type information. Everything except the
  576. // Sectors field is fixed by default. The number of Sectors
  577. // on the drive is determined from the host file's size.
  578. //
  579. _actual.MediaType = HostedDriveMediaType;
  580. _actual.SectorSize = HostedDriveSectorSize;
  581. _actual.HiddenSectors = HostedDriveHiddenSectors;
  582. _actual.SectorsPerTrack = HostedDriveSectorsPerTrack;
  583. _actual.Heads = HostedDriveHeads;
  584. _last_status = NtQueryInformationFile( _handle,
  585. &StatusBlock,
  586. &FileStandardInfo,
  587. sizeof( FileStandardInfo ),
  588. FileStandardInformation );
  589. if( !NT_SUCCESS( _last_status ) ) {
  590. Destroy();
  591. Message ? Message->DisplayMsg( MSG_DISK_TOO_LARGE_TO_FORMAT ) : 1;
  592. return FALSE;
  593. }
  594. FileSize = FileStandardInfo.EndOfFile;
  595. Sectors = FileSize / _actual.SectorSize;
  596. if( Sectors.GetHighPart() != 0 ) {
  597. Destroy();
  598. Message ? Message->DisplayMsg( MSG_BAD_IOCTL ) : 1;
  599. return FALSE;
  600. }
  601. _actual.Sectors = Sectors.GetLargeInteger();
  602. // This drive has only one supported drive type
  603. //
  604. _num_supported = 1;
  605. if (!(_supported_list = NEW DRTYPE[1])) {
  606. Destroy();
  607. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  608. return FALSE;
  609. }
  610. _supported_list[0] = _actual;
  611. // If this was a transient open, clean it up.
  612. //
  613. if (!IsTransient) {
  614. IFS_SYSTEM::FileSetAttributes( _handle, _old_attributes, &ExtraUlong );
  615. NtClose(_handle);
  616. _alternate_handle ? NtClose(_alternate_handle) : 1;
  617. _handle = 0;
  618. _alternate_handle = 0;
  619. }
  620. #endif
  621. return FALSE;
  622. }
  623. IFSUTIL_EXPORT
  624. ULONG
  625. DP_DRIVE::QuerySectorSize(
  626. ) CONST
  627. /*++
  628. Routine Description:
  629. This routine computes the number of bytes per sector.
  630. Arguments:
  631. None.
  632. Return Value:
  633. The number of bytes per sector.
  634. --*/
  635. {
  636. return _actual.SectorSize;
  637. }
  638. // BUGBUG EFI doesn't need this
  639. #if 0
  640. #if defined(FE_SB) && defined(_X86_)
  641. IFSUTIL_EXPORT
  642. ULONG
  643. DP_DRIVE::QueryPhysicalSectorSize(
  644. ) CONST
  645. /*++
  646. Routine Description:
  647. This routine computes the number of bytes per sector.
  648. Arguments:
  649. None.
  650. Return Value:
  651. The number of bytes per physical sector.
  652. --*/
  653. {
  654. return _actual.PhysicalSectorSize;
  655. }
  656. #endif
  657. #endif // removed for EFI
  658. IFSUTIL_EXPORT
  659. BIG_INT
  660. DP_DRIVE::QuerySectors(
  661. ) CONST
  662. /*++
  663. Routine Description:
  664. This routine computes the number sectors on the disk. This does not
  665. include the hidden sectors.
  666. Arguments:
  667. None.
  668. Return Value:
  669. The number of sectors on the disk.
  670. --*/
  671. {
  672. return _actual.Sectors;
  673. }
  674. IFSUTIL_EXPORT
  675. UCHAR
  676. DP_DRIVE::QueryMediaByte(
  677. ) CONST
  678. /*++
  679. Routine Description:
  680. This routine computes the media byte used by the FAT and HPFS file
  681. systems to represent the current media type.
  682. Arguments:
  683. None.
  684. Return Value:
  685. The media byte for the drive.
  686. --*/
  687. {
  688. switch (_actual.MediaType) {
  689. case F5_1Pt2_512: // 5.25", 1.2MB, 512 bytes/sector
  690. return 0xF9;
  691. case F3_1Pt44_512: // 3.5", 1.44MB, 512 bytes/sector
  692. return 0xF0;
  693. case F3_2Pt88_512: // 3.5", 2.88MB, 512 bytes/sector
  694. return 0xF0;
  695. case F3_120M_512: // 3.5", 120MB, 512 bytes/sector
  696. return 0xF0;
  697. case F3_20Pt8_512: // 3.5", 20.8MB, 512 bytes/sector
  698. return 0xF9;
  699. case F3_720_512: // 3.5", 720KB, 512 bytes/sector
  700. return 0xF9;
  701. case F5_360_512: // 5.25", 360KB, 512 bytes/sector
  702. return 0xFD;
  703. case F5_320_512: // 5.25", 320KB, 512 bytes/sector
  704. return 0xFF;
  705. case F5_180_512: // 5.25", 180KB, 512 bytes/sector
  706. return 0xFC;
  707. case F5_160_512: // 5.25", 160KB, 512 bytes/sector
  708. return 0xFE;
  709. case RemovableMedia:// Removable media other than floppy
  710. return 0xF8; // There is no better choice than this.
  711. case FixedMedia: // Fixed hard disk media
  712. #if defined(FE_SB) && defined(_X86_)
  713. // FMR Jul.13.1994 SFT KMR
  714. // Add the set up process for the fixed_hard_disk_mediaID for FMR
  715. // FMR's media id is different. Case under 64MB or not.
  716. if(IsFMR_N()) {
  717. if(_actual.SectorSize * _actual.Sectors <= 63*1024*1024) {
  718. return 0xF9;
  719. } else {
  720. return 0xFA;
  721. }
  722. } else
  723. #endif
  724. return 0xF8;
  725. #if defined(FE_SB)
  726. case F3_128Mb_512: // 3.5"MO, 128MB, 512 bytes/sector
  727. case F3_230Mb_512: // 3.3"MO, 230MB, 512 bytes/sector
  728. return 0xF0;
  729. #if defined(_X86_)
  730. // NEC Oct.15.1994
  731. // FMR Jul.14.1994 SFT KMR
  732. // For 8"1S , 256KB , 128 bytes/sector
  733. // If the media_type is 2HD, return the mediaID:FE
  734. case F8_256_128: // 8"1S , 256KB , 128 bytes/sector
  735. case F5_1Pt23_1024: // 5.25", 1.23MB, 1024 bytes/sector
  736. case F3_1Pt23_1024: // 3.5", 1.23MB, 1024 bytes/sector
  737. return 0xFE;
  738. // If the media_type is 2HC, return the mediaID:F9
  739. // If the media_type is 2DD(720KB), return the mediaID:F9
  740. case F5_720_512: // 5.25", 720KB, 512 bytes/sector
  741. case F3_1Pt2_512: // 3.5", 1.2MB, 512 bytes/sector
  742. return 0xF9;
  743. // If the media_type is 2DD(640KB), return the mediaID:FB
  744. case F5_640_512: // 5", 640KB, 512 bytes/sector
  745. case F3_640_512: // 3.5", 640KB, 512 bytes/sector
  746. return 0xFB;
  747. #endif // _X86_
  748. #endif // FE_SB
  749. case F5_320_1024:
  750. case Unknown:
  751. break;
  752. }
  753. return 0;
  754. }
  755. VOID
  756. DP_DRIVE::Destroy(
  757. )
  758. /*++
  759. Routine Description:
  760. This routine returns a DP_DRIVE to its initial state.
  761. Arguments:
  762. None.
  763. Return Value:
  764. None.
  765. --*/
  766. {
  767. memset(&_actual, 0, sizeof(DRTYPE));
  768. DELETE_ARRAY(_supported_list);
  769. _num_supported = 0;
  770. _alignment_mask = 0;
  771. // BUGBUG removed for EFI
  772. #if 0
  773. if (_hosted_drive) {
  774. IFS_SYSTEM::FileSetAttributes( _handle, _old_attributes, &ExtraUlong );
  775. }
  776. if (_alternate_handle) {
  777. NtClose(_alternate_handle);
  778. _alternate_handle = 0;
  779. }
  780. if (_handle) {
  781. NtClose(_handle);
  782. _handle = 0;
  783. }
  784. #endif
  785. _hosted_drive = FALSE;
  786. }
  787. VOID
  788. DP_DRIVE::CloseDriveHandle(
  789. )
  790. {
  791. #if 0
  792. if (_handle) {
  793. // BUGBUG removed for EFI
  794. NtClose(_handle);
  795. _handle = 0;
  796. }
  797. #endif
  798. }
  799. BOOLEAN
  800. DP_DRIVE::IsSupported(
  801. IN MEDIA_TYPE MediaType
  802. ) CONST
  803. /*++
  804. Routine Description:
  805. This routine computes whether or not the supplied media type is supported
  806. by the drive.
  807. Arguments:
  808. MediaType - Supplies the media type.
  809. Return Value:
  810. FALSE - The media type is not supported by the drive.
  811. TRUE - The media type is supported by the drive.
  812. --*/
  813. {
  814. INT i;
  815. for (i = 0; i < _num_supported; i++) {
  816. if (MediaType == _supported_list[i].MediaType) {
  817. return TRUE;
  818. }
  819. }
  820. return FALSE;
  821. }
  822. IFSUTIL_EXPORT
  823. MEDIA_TYPE
  824. DP_DRIVE::QueryRecommendedMediaType(
  825. ) CONST
  826. /*++
  827. Routine Description:
  828. This routine computes the recommended media type for
  829. drive. This media type is independant of any existing
  830. media type for the drive. It is solely based on the
  831. list of recommended media types for the drive.
  832. Arguments:
  833. None.
  834. Return Value:
  835. The recommended media type for the drive.
  836. --*/
  837. {
  838. INT i;
  839. MEDIA_TYPE media_type;
  840. SECTORCOUNT sectors;
  841. media_type = Unknown;
  842. sectors = 0;
  843. for (i = 0; i < _num_supported; i++) {
  844. // Special case 1.44. If a drive supports it then
  845. // that should be the recommended media type.
  846. if (_supported_list[i].MediaType == F3_1Pt44_512) {
  847. media_type = _supported_list[i].MediaType;
  848. break;
  849. }
  850. if (_supported_list[i].Sectors > sectors) {
  851. media_type = _supported_list[i].MediaType;
  852. }
  853. }
  854. return media_type;
  855. }
  856. BOOLEAN
  857. DP_DRIVE::SetMediaType(
  858. IN MEDIA_TYPE MediaType
  859. )
  860. /*++
  861. Routine Description:
  862. This routine alters the media type of the drive. If 'MediaType' is
  863. 'Unknown' and the current media type for the drive is also 'Unknown'
  864. then this routine selects the highest density supported by the
  865. driver. If the current media type is known then this function
  866. will have no effect if 'MediaType' is 'Unknown'.
  867. Arguments:
  868. MediaType - Supplies the new media type for the drive.
  869. Return Value:
  870. FALSE - The proposed media type is not supported by the drive.
  871. TRUE - Success.
  872. --*/
  873. {
  874. INT i;
  875. if (MediaType == Unknown) {
  876. if (_actual.MediaType != Unknown) {
  877. return TRUE;
  878. } else if (!_num_supported) {
  879. return FALSE;
  880. }
  881. for (i = 0; i < _num_supported; i++) {
  882. if (_supported_list[i].Sectors > QuerySectors()) {
  883. _actual = _supported_list[i];
  884. }
  885. }
  886. return TRUE;
  887. }
  888. for (i = 0; i < _num_supported; i++) {
  889. if (_supported_list[i].MediaType == MediaType) {
  890. _actual = _supported_list[i];
  891. return TRUE;
  892. }
  893. }
  894. return FALSE;
  895. }
  896. VOID
  897. DP_DRIVE::DiskGeometryToDriveType(
  898. IN PCDISK_GEOMETRY DiskGeometry,
  899. OUT PDRTYPE DriveType
  900. )
  901. /*++
  902. Routine Description:
  903. This routine computes the drive type given the disk geometry.
  904. Arguments:
  905. DiskGeometry - Supplies the disk geometry for the drive.
  906. DriveType - Returns the drive type for the drive.
  907. Return Value:
  908. FALSE - Failure.
  909. TRUE - Success.
  910. --*/
  911. {
  912. DriveType->MediaType = DiskGeometry->MediaType;
  913. DriveType->SectorSize = DiskGeometry->BytesPerSector;
  914. DriveType->Sectors = DiskGeometry->Cylinders*
  915. DiskGeometry->TracksPerCylinder*
  916. DiskGeometry->SectorsPerTrack;
  917. DriveType->HiddenSectors = 0;
  918. DriveType->SectorsPerTrack = DiskGeometry->SectorsPerTrack;
  919. DriveType->Heads = DiskGeometry->TracksPerCylinder;
  920. }
  921. VOID
  922. DP_DRIVE::DiskGeometryToDriveType(
  923. IN PCDISK_GEOMETRY DiskGeometry,
  924. IN BIG_INT NumSectors,
  925. IN BIG_INT NumHiddenSectors,
  926. OUT PDRTYPE DriveType
  927. )
  928. /*++
  929. Routine Description:
  930. This routine computes the drive type given the disk geometry.
  931. Arguments:
  932. DiskGeometry - Supplies the disk geometry for the drive.
  933. NumSectors - Supplies the total number of non-hidden sectors on
  934. the disk.
  935. NumHiddenSectors - Supplies the number of hidden sectors on the disk.
  936. DriveType - Returns the drive type for the drive.
  937. Return Value:
  938. FALSE - Failure.
  939. TRUE - Success.
  940. --*/
  941. {
  942. DriveType->MediaType = DiskGeometry->MediaType;
  943. DriveType->SectorSize = DiskGeometry->BytesPerSector;
  944. DriveType->Sectors = NumSectors;
  945. DriveType->HiddenSectors = NumHiddenSectors;
  946. DriveType->SectorsPerTrack = DiskGeometry->SectorsPerTrack;
  947. DriveType->Heads = DiskGeometry->TracksPerCylinder;
  948. }
  949. #if defined(FE_SB) && defined(_X86_)
  950. IFSUTIL_EXPORT
  951. BOOLEAN
  952. DP_DRIVE::IsATformat(
  953. ) CONST
  954. /*++
  955. Routine Description:
  956. This routine judged whether it is AT format.
  957. Arguments:
  958. None.
  959. Return Value:
  960. FALSE - The disk is not AT format.
  961. TRUE - The disk is AT format.
  962. History:
  963. PC98 Oct.21.1995
  964. --*/
  965. {
  966. return _next_format_type == FORMAT_MEDIA_AT;
  967. }
  968. #endif
  969. DEFINE_CONSTRUCTOR( IO_DP_DRIVE, DP_DRIVE );
  970. VOID
  971. IO_DP_DRIVE::Construct (
  972. )
  973. /*++
  974. Routine Description:
  975. Constructor for IO_DP_DRIVE.
  976. Arguments:
  977. None.
  978. Return Value:
  979. None.
  980. --*/
  981. {
  982. _is_locked = FALSE;
  983. _is_exclusive_write = FALSE;
  984. _cache = NULL;
  985. _ValidBlockLengthForVerify = 0;
  986. _message = NULL;
  987. }
  988. VOID
  989. IO_DP_DRIVE::Destroy(
  990. )
  991. /*++
  992. Routine Description:
  993. This routine returns an IO_DP_DRIVE object to its initial state.
  994. Arguments:
  995. None.
  996. Return Value:
  997. None.
  998. --*/
  999. {
  1000. DELETE(_cache);
  1001. if (_is_exclusive_write) {
  1002. Dismount();
  1003. _is_exclusive_write = FALSE;
  1004. }
  1005. if (_is_locked) {
  1006. Unlock();
  1007. _is_locked = FALSE;
  1008. }
  1009. _ValidBlockLengthForVerify = 0;
  1010. _message = NULL;
  1011. }
  1012. IO_DP_DRIVE::~IO_DP_DRIVE(
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. Destructor for IO_DP_DRIVE.
  1017. Arguments:
  1018. None.
  1019. Return Value:
  1020. None.
  1021. --*/
  1022. {
  1023. Destroy();
  1024. }
  1025. BOOLEAN
  1026. IO_DP_DRIVE::Initialize(
  1027. IN PCWSTRING NtDriveName,
  1028. IN OUT PMESSAGE Message,
  1029. IN BOOLEAN ExclusiveWrite
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. This routine initializes an IO_DP_DRIVE object.
  1034. Arguments:
  1035. NtDriveName - Supplies the drive path.
  1036. Message - Supplies an outlet for messages.
  1037. ExclusiveWrite - Supplies whether or not to open the drive for
  1038. exclusive write.
  1039. Return Value:
  1040. FALSE - Failure.
  1041. TRUE - Success.
  1042. --*/
  1043. {
  1044. Destroy();
  1045. if (!DP_DRIVE::Initialize(NtDriveName, Message, TRUE, ExclusiveWrite)) {
  1046. Destroy();
  1047. return FALSE;
  1048. }
  1049. _is_exclusive_write = ExclusiveWrite;
  1050. if (!(_cache = NEW DRIVE_CACHE) ||
  1051. !_cache->Initialize(this)) {
  1052. Destroy();
  1053. return FALSE;
  1054. }
  1055. _ValidBlockLengthForVerify = 0;
  1056. _message = Message;
  1057. return TRUE;
  1058. }
  1059. BOOLEAN
  1060. IO_DP_DRIVE::Initialize(
  1061. IN PCWSTRING NtDriveName,
  1062. IN PCWSTRING HostFileName,
  1063. IN OUT PMESSAGE Message,
  1064. IN BOOLEAN ExclusiveWrite
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. This routine initializes an IO_DP_DRIVE object for a hosted
  1069. drive, i.e. one which is implemented as a file on another
  1070. volume.
  1071. Arguments:
  1072. NtDriveName - Supplies the drive path.
  1073. HostFileName - Supplies the fully qualified name of the host file.
  1074. Message - Supplies an outlet for messages.
  1075. ExclusiveWrite - Supplies whether or not to open the drive for
  1076. exclusive write.
  1077. Return Value:
  1078. FALSE - Failure.
  1079. TRUE - Success.
  1080. --*/
  1081. {
  1082. Destroy();
  1083. if( !DP_DRIVE::Initialize(NtDriveName,
  1084. HostFileName,
  1085. Message,
  1086. TRUE,
  1087. ExclusiveWrite)) {
  1088. Destroy();
  1089. return FALSE;
  1090. }
  1091. _is_exclusive_write = ExclusiveWrite;
  1092. if (!(_cache = NEW DRIVE_CACHE) ||
  1093. !_cache->Initialize(this)) {
  1094. Destroy();
  1095. return FALSE;
  1096. }
  1097. _ValidBlockLengthForVerify = 0;
  1098. _message = Message;
  1099. return TRUE;
  1100. }
  1101. IFSUTIL_EXPORT
  1102. BOOLEAN
  1103. IO_DP_DRIVE::Read(
  1104. IN BIG_INT StartingSector,
  1105. IN SECTORCOUNT NumberOfSectors,
  1106. OUT PVOID Buffer
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This routine reads a run of sectors into the buffer pointed to by
  1111. 'Buffer'.
  1112. Arguments:
  1113. StartingSector - Supplies the first sector to be read.
  1114. NumberOfSectors - Supplies the number of sectors to be read.
  1115. Buffer - Supplies a buffer to read the run of sectors into.
  1116. Return Value:
  1117. FALSE - Failure.
  1118. TRUE - Success.
  1119. --*/
  1120. {
  1121. DebugAssert(_cache);
  1122. return _cache->Read(StartingSector, NumberOfSectors, Buffer);
  1123. }
  1124. IFSUTIL_EXPORT
  1125. BOOLEAN
  1126. IO_DP_DRIVE::Write(
  1127. BIG_INT StartingSector,
  1128. SECTORCOUNT NumberOfSectors,
  1129. PVOID Buffer
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. This routine writes a run of sectors onto the disk from the buffer pointed
  1134. to by 'Buffer'. Writing is only permitted if 'Lock' was called.
  1135. Arguments:
  1136. StartingSector - Supplies the first sector to be written.
  1137. NumberOfSectors - Supplies the number of sectors to be written.
  1138. Buffer - Supplies the buffer to write the run of sectors from.
  1139. Return Value:
  1140. FALSE - Failure.
  1141. TRUE - Success.
  1142. --*/
  1143. {
  1144. DebugAssert(_cache);
  1145. return _cache->Write(StartingSector, NumberOfSectors, Buffer);
  1146. }
  1147. IFSUTIL_EXPORT
  1148. VOID
  1149. IO_DP_DRIVE::SetCache(
  1150. IN OUT PDRIVE_CACHE Cache
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. This routine relaces the current cache with the one supplied.
  1155. The object then takes ownership of this cache and it will be
  1156. deleted by the object.
  1157. Arguments:
  1158. Cache - Supplies the new cache to install.
  1159. Return Value:
  1160. TRUE - Success.
  1161. FALSE - Failure.
  1162. --*/
  1163. {
  1164. DebugAssert(Cache);
  1165. DELETE(_cache);
  1166. _cache = Cache;
  1167. }
  1168. IFSUTIL_EXPORT
  1169. BOOLEAN
  1170. IO_DP_DRIVE::FlushCache(
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This routine flushes the cache and report returns whether any
  1175. IO error occurred during the life of the cache.
  1176. Arguments:
  1177. None.
  1178. Return Value:
  1179. FALSE - Some IO errors have occured during the life of the cache.
  1180. TRUE - Success.
  1181. --*/
  1182. {
  1183. DebugAssert(_cache);
  1184. return _cache->Flush();
  1185. }
  1186. BOOLEAN
  1187. IO_DP_DRIVE::HardRead(
  1188. IN BIG_INT StartingSector,
  1189. IN SECTORCOUNT NumberOfSectors,
  1190. OUT PVOID Buffer
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. This routine reads a run of sectors into the buffer pointed to by
  1195. 'Buffer'.
  1196. Arguments:
  1197. StartingSector - Supplies the first sector to be read.
  1198. NumberOfSectors - Supplies the number of sectors to be read.
  1199. Buffer - Supplies a buffer to read the run of sectors into.
  1200. Return Value:
  1201. FALSE - Failure.
  1202. TRUE - Success.
  1203. --*/
  1204. {
  1205. // allocate a buffer
  1206. PVOID AlignedBuffer = NULL;
  1207. PVOID AlignedBufferRaw = AllocatePool(NumberOfSectors*QuerySectorSize()+QueryAlignmentMask()+1);
  1208. if(!AlignedBufferRaw) {
  1209. DEBUG((D_ERROR,(CHAR8*)"HardRead: Aligned buffer allocation failed!!!!!!\n"));
  1210. return FALSE;
  1211. }
  1212. // align the buffer according to the mask provided
  1213. AlignedBuffer = (PVOID)(( (ULONG_PTR)AlignedBufferRaw + QueryAlignmentMask() ) & ~((ULONG_PTR)QueryAlignmentMask()));
  1214. EFI_STATUS status =
  1215. status = _disk_io->ReadDisk(
  1216. _disk_io,
  1217. _media_id,
  1218. MultU64x32(StartingSector.GetQuadPart(),_block_io->Media->BlockSize),
  1219. NumberOfSectors*QuerySectorSize(),
  1220. AlignedBuffer
  1221. );
  1222. if(status != EFI_SUCCESS) {
  1223. FreePool(AlignedBufferRaw);
  1224. DEBUG((D_ERROR,(CHAR8*)"HardRead: Read Failed %x!!!!!!\n", status));
  1225. return FALSE;
  1226. }
  1227. memcpy(Buffer,AlignedBuffer,NumberOfSectors*QuerySectorSize());
  1228. FreePool(AlignedBufferRaw);
  1229. return TRUE;
  1230. }
  1231. BOOLEAN
  1232. IO_DP_DRIVE::HardWrite(
  1233. BIG_INT StartingSector,
  1234. SECTORCOUNT NumberOfSectors,
  1235. PVOID Buffer
  1236. )
  1237. /*++
  1238. Routine Description:
  1239. This routine writes a run of sectors onto the disk from the buffer pointed
  1240. to by 'Buffer'. Writing is only permitted if 'Lock' was called.
  1241. After writing each chunk, we read it back to make sure the write
  1242. really succeeded.
  1243. Arguments:
  1244. StartingSector - Supplies the first sector to be written.
  1245. NumberOfSectors - Supplies the number of sectors to be written.
  1246. Buffer - Supplies the buffer to write the run of sectors from.
  1247. Return Value:
  1248. FALSE - Failure.
  1249. TRUE - Success.
  1250. --*/
  1251. {
  1252. // allocate a buffer
  1253. PVOID AlignedBuffer;
  1254. ULONG Length = NumberOfSectors*QuerySectorSize();
  1255. PVOID AlignedBufferRaw = NULL;
  1256. EFI_STATUS status;
  1257. DEBUG((D_INFO, (CHAR8*)"HardWrite: At %x for %x sectors\n",
  1258. StartingSector,
  1259. NumberOfSectors));
  1260. //
  1261. // Align buffer only if needed
  1262. //
  1263. if (QueryAlignmentMask()) {
  1264. DEBUG((D_INFO, (CHAR8*)"HardWrite: Buffer requires alignment\n"));
  1265. AlignedBufferRaw = AllocatePool(Length+QueryAlignmentMask()+1);
  1266. if(!AlignedBufferRaw) {
  1267. DEBUG((D_ERROR, (CHAR8*)"HardWrite: Aligned buffer allocation failed!!!!!!\n"));
  1268. return FALSE;
  1269. }
  1270. AlignedBuffer = (PVOID)(( (ULONG_PTR)AlignedBufferRaw + QueryAlignmentMask() ) &
  1271. ~((ULONG_PTR)QueryAlignmentMask()) );
  1272. memcpy(AlignedBuffer, Buffer, NumberOfSectors*QuerySectorSize());
  1273. } else {
  1274. AlignedBuffer = Buffer;
  1275. }
  1276. // align the buffer according to the mask provided
  1277. status = _disk_io->WriteDisk(
  1278. _disk_io,
  1279. _media_id,
  1280. MultU64x32 (StartingSector.GetQuadPart(),_block_io->Media->BlockSize),
  1281. Length,
  1282. AlignedBuffer
  1283. );
  1284. if (status != EFI_SUCCESS) {
  1285. DEBUG((D_ERROR,(CHAR8*)"HardWrite: Write Failed %x!!!!!!\n", status));
  1286. }
  1287. if (AlignedBufferRaw) {
  1288. FreePool(AlignedBufferRaw);
  1289. }
  1290. return (status == EFI_SUCCESS);
  1291. }
  1292. IFSUTIL_EXPORT
  1293. BOOLEAN
  1294. IO_DP_DRIVE::Verify(
  1295. IN BIG_INT StartingSector,
  1296. IN BIG_INT NumberOfSectors,
  1297. IN PVOID TestBuffer1,
  1298. IN PVOID TestBuffer2
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This routine verifies a run of sectors on the disk.
  1303. Arguments:
  1304. StartingSector - Supplies the first sector of the run to verify.
  1305. NumberOfSectors - Supplies the number of sectors in the run to verify.
  1306. TestBuffer1 - Supplies a buffer containing test write data
  1307. TestBuffer2 - Supplies a buffer containing test write data
  1308. Return Value:
  1309. FALSE - Some of the sectors in the run are bad.
  1310. TRUE - All of the sectors in the run are good.
  1311. --*/
  1312. {
  1313. BIG_INT VerifySize = QuerySectorSize() * NumberOfSectors;
  1314. ULONG Size = VerifySize.GetLowPart();
  1315. PVOID TempBuffer;
  1316. BOOLEAN result = TRUE;
  1317. DEBUG((D_INFO, (CHAR8*)"Verify: Verifying %x sectors starting at %x\n",
  1318. NumberOfSectors,
  1319. StartingSector));
  1320. DebugAssert(VerifySize.GetHighPart() == 0);
  1321. // there is no guarantee that verify cmd will not destroy data
  1322. // there may not be a need to restore the content
  1323. TempBuffer = AllocatePool(Size);
  1324. if (TempBuffer == NULL) {
  1325. DEBUG((D_ERROR, (CHAR8*)"Verify: Out of memory\n"));
  1326. return FALSE;
  1327. }
  1328. if (!HardWrite(StartingSector, NumberOfSectors.GetLowPart(), TestBuffer1) ||
  1329. !HardRead(StartingSector, NumberOfSectors.GetLowPart(), TempBuffer) ||
  1330. (CompareMem(TestBuffer1, TempBuffer, Size) != 0)) {
  1331. result = FALSE;
  1332. }
  1333. if (result) {
  1334. if (!HardWrite(StartingSector, NumberOfSectors.GetLowPart(), TestBuffer2) ||
  1335. !HardRead(StartingSector, NumberOfSectors.GetLowPart(), TempBuffer) ||
  1336. (CompareMem(TestBuffer2, TempBuffer, Size) != 0)) {
  1337. result = FALSE;
  1338. }
  1339. }
  1340. FreePool(TempBuffer);
  1341. return result;
  1342. }
  1343. IFSUTIL_EXPORT
  1344. BOOLEAN
  1345. IO_DP_DRIVE::Verify(
  1346. IN BIG_INT StartingSector,
  1347. IN BIG_INT NumberOfSectors,
  1348. IN OUT PNUMBER_SET BadSectors
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. This routine computes which sectors in the given range are bad
  1353. and adds these bad sectors to the bad sectors list.
  1354. Arguments:
  1355. StartingSector - Supplies the starting sector.
  1356. NumberOfSectors - Supplies the number of sectors.
  1357. BadSectors - Supplies the bad sectors list.
  1358. Return Value:
  1359. FALSE - Failure.
  1360. TRUE - Success.
  1361. --*/
  1362. {
  1363. ULONG MaxSectorsInVerify = 0x200;
  1364. ULONG MaxDiskHits;
  1365. BIG_INT half;
  1366. PBIG_INT starts;
  1367. PBIG_INT run_lengths;
  1368. ULONG i, n;
  1369. BIG_INT num_sectors;
  1370. PVOID TestBuffer1;
  1371. PVOID TestBuffer2;
  1372. DEBUG((D_INFO, (CHAR8*)"Entering Verify\n"));
  1373. if (NumberOfSectors == 0) {
  1374. DEBUG((D_INFO, (CHAR8*)"Leaving Verify as there is nothing to verify\n"));
  1375. return TRUE;
  1376. }
  1377. if (NumberOfSectors.GetHighPart() != 0) {
  1378. DEBUG((D_ERROR, (CHAR8*)"Verify: Number of sectors to verify exceeded 32 bits\n"));
  1379. return FALSE;
  1380. }
  1381. // Allow 20 retries so that a single bad sector in this region
  1382. // will be found accurately.
  1383. MaxDiskHits = (20 + NumberOfSectors/MaxSectorsInVerify + 1).GetLowPart();
  1384. starts = (PBIG_INT)AllocatePool(sizeof(BIG_INT)*MaxDiskHits);
  1385. if (NULL == starts) {
  1386. DEBUG((D_ERROR, (CHAR8*)"Verify: Out of memory\n"));
  1387. return FALSE;
  1388. }
  1389. run_lengths = (PBIG_INT)AllocatePool(sizeof(BIG_INT)*MaxDiskHits);
  1390. if (NULL == run_lengths) {
  1391. DEBUG((D_ERROR, (CHAR8*)"Verify: Out of memory\n"));
  1392. FreePool(starts);
  1393. return FALSE;
  1394. }
  1395. num_sectors = NumberOfSectors;
  1396. for (i = 0; num_sectors > 0; i++) {
  1397. starts[i] = StartingSector + i*MaxSectorsInVerify;
  1398. if (MaxSectorsInVerify > num_sectors) {
  1399. run_lengths[i] = num_sectors;
  1400. } else {
  1401. run_lengths[i] = MaxSectorsInVerify;
  1402. }
  1403. num_sectors -= run_lengths[i];
  1404. }
  1405. TestBuffer1 = AllocatePool(MaxSectorsInVerify);
  1406. TestBuffer2 = AllocatePool(MaxSectorsInVerify);
  1407. if (NULL == TestBuffer2 || NULL == TestBuffer1) {
  1408. DEBUG((D_ERROR, (CHAR8*)"Verify: Out of memory\n"));
  1409. FreePool(TestBuffer1);
  1410. FreePool(TestBuffer2);
  1411. FreePool(starts);
  1412. FreePool(run_lengths);
  1413. return FALSE;
  1414. }
  1415. // fill with 1010s and 0101s
  1416. SetMem(TestBuffer1, MaxSectorsInVerify, 0xAA);
  1417. SetMem(TestBuffer2, MaxSectorsInVerify, 0x55);
  1418. n = i;
  1419. for (i = 0; i < n; i++) {
  1420. if (!Verify(starts[i], run_lengths[i], TestBuffer1, TestBuffer2)) {
  1421. if (BadSectors == NULL) {
  1422. FreePool(TestBuffer1);
  1423. FreePool(TestBuffer2);
  1424. FreePool(starts);
  1425. FreePool(run_lengths);
  1426. return FALSE;
  1427. }
  1428. if (n + 2 > MaxDiskHits) {
  1429. if (!BadSectors->Add(starts[i], run_lengths[i])) {
  1430. FreePool(TestBuffer1);
  1431. FreePool(TestBuffer2);
  1432. FreePool(starts);
  1433. FreePool(run_lengths);
  1434. return FALSE;
  1435. }
  1436. } else {
  1437. if (run_lengths[i] == 1) {
  1438. if (!BadSectors->Add(starts[i])) {
  1439. FreePool(TestBuffer1);
  1440. FreePool(TestBuffer2);
  1441. FreePool(starts);
  1442. FreePool(run_lengths);
  1443. return FALSE;
  1444. }
  1445. } else {
  1446. half = run_lengths[i]/2;
  1447. starts[n] = starts[i];
  1448. run_lengths[n] = half;
  1449. starts[n + 1] = starts[i] + half;
  1450. run_lengths[n + 1] = run_lengths[i] - half;
  1451. n += 2;
  1452. }
  1453. }
  1454. }
  1455. }
  1456. FreePool(TestBuffer1);
  1457. FreePool(TestBuffer2);
  1458. FreePool(starts);
  1459. FreePool(run_lengths);
  1460. DEBUG((D_INFO, (CHAR8*)"Leaving Verify\n"));
  1461. return TRUE;
  1462. }
  1463. BOOLEAN
  1464. IO_DP_DRIVE::VerifyWithRead(
  1465. IN BIG_INT StartingSector,
  1466. IN BIG_INT NumberOfSectors
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. This routine verifies the usability of the given range of sectors
  1471. using read.
  1472. Arguments:
  1473. StartingSector - Supplies the starting sector of the verify.
  1474. Number OfSectors - Supplies the number of sectors to verify.
  1475. Return Value:
  1476. FALSE - At least one of the sectors in the given range was unreadable.
  1477. TRUE - All of the sectors in the given range are readable.
  1478. --*/
  1479. {
  1480. ULONG grab;
  1481. BIG_INT i;
  1482. CONST ULONG MaxIoSize = 0x200 * QuerySectorSize();
  1483. PVOID Buffer = AllocatePool(MaxIoSize);
  1484. DEBUG((D_INFO, (CHAR8*)"Entering VerifyWithRead\n"));
  1485. if (Buffer == NULL) {
  1486. DEBUG((D_ERROR, (CHAR8*)"VerifyWithRead: Out of memory\n"));
  1487. return FALSE;
  1488. }
  1489. grab = MaxIoSize/QuerySectorSize();
  1490. for (i = 0; i < NumberOfSectors; i += grab) {
  1491. if (NumberOfSectors - i < grab) {
  1492. grab = (NumberOfSectors - i).GetLowPart();
  1493. }
  1494. if (!HardRead(StartingSector + i, grab, Buffer)) {
  1495. return FALSE;
  1496. }
  1497. }
  1498. DEBUG((D_INFO, (CHAR8*)"Leaving VerifyWithRead\n"));
  1499. return TRUE;
  1500. }
  1501. BOOLEAN
  1502. IO_DP_DRIVE::Lock(
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routine locks the drive. If the drive is already locked then
  1507. this routine will do nothing.
  1508. Arguments:
  1509. None.
  1510. Return Value:
  1511. FALSE - Failure.
  1512. TRUE - Success.
  1513. --*/
  1514. {
  1515. // EFI can just return TRUE.
  1516. return TRUE;
  1517. }
  1518. BOOLEAN
  1519. IO_DP_DRIVE::InvalidateVolume(
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. This routine invalidates the drive.
  1524. Arguments:
  1525. None.
  1526. Return Value:
  1527. FALSE - Failure.
  1528. TRUE - Success.
  1529. --*/
  1530. {
  1531. // BUGBUG need alternate implementaiton for EFI?
  1532. return TRUE;
  1533. }
  1534. BOOLEAN
  1535. IO_DP_DRIVE::ForceDirty(
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. This routine forces the volume to be dirty, so that efichk will
  1540. run next time the system reboots.
  1541. Arguments:
  1542. None.
  1543. Return Value:
  1544. FALSE - Failure.
  1545. TRUE - Success.
  1546. --*/
  1547. {
  1548. // BUGBUG this IOCTL doesn't exist in EFI, do we need an alternate implementation?
  1549. return TRUE;
  1550. }
  1551. BOOLEAN
  1552. IO_DP_DRIVE::Unlock(
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. This routine unlocks the drive.
  1557. Arguments:
  1558. None.
  1559. Return Value:
  1560. FALSE - Failure.
  1561. TRUE - Success.
  1562. --*/
  1563. {
  1564. // EFI doesn't need this, we just stub it out
  1565. return TRUE;
  1566. }
  1567. BOOLEAN
  1568. IO_DP_DRIVE::Dismount(
  1569. )
  1570. /*++
  1571. Routine Description:
  1572. This routine dismounts the drive.
  1573. Arguments:
  1574. None.
  1575. Return Value:
  1576. FALSE - Failure.
  1577. TRUE - Success.
  1578. --*/
  1579. {
  1580. // unneeded for EFI
  1581. return TRUE;
  1582. }
  1583. BOOLEAN
  1584. IO_DP_DRIVE::DismountAndUnlock(
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine dismounts the drive and unlocks it.
  1589. Arguments:
  1590. None.
  1591. Return Value:
  1592. FALSE - Failure.
  1593. TRUE - Success.
  1594. --*/
  1595. {
  1596. // not needed for EFI
  1597. return TRUE;
  1598. }
  1599. BOOLEAN
  1600. IO_DP_DRIVE::FormatVerifyFloppy(
  1601. IN MEDIA_TYPE MediaType,
  1602. IN OUT PNUMBER_SET BadSectors,
  1603. IN OUT PMESSAGE Message,
  1604. IN BOOLEAN IsDmfFormat
  1605. )
  1606. /*++
  1607. Routine Description:
  1608. This routine low level formats an entire floppy disk to the media
  1609. type specified. If no MediaType is specified then a logical one will
  1610. be selected.
  1611. Arguments:
  1612. MediaType - Supplies an optional media type to format to.
  1613. BadSectors - Returns a list of bad sectors on the disk.
  1614. Message - Supplies a message object to route messages to.
  1615. IsDmfFormat - Supplies whether or not to perform a DMF type format.
  1616. Return Value:
  1617. FALSE - Failure.
  1618. TRUE - Success.
  1619. --*/
  1620. {
  1621. // BUGBUG temporary removal for EFI? do we need this for EFI
  1622. #if 0
  1623. IO_STATUS_BLOCK status_block;
  1624. CONST format_parameters_size = sizeof(FORMAT_EX_PARAMETERS) + 20*sizeof(USHORT);
  1625. CHAR format_parameters_buffer[format_parameters_size];
  1626. PFORMAT_EX_PARAMETERS format_parameters;
  1627. PBAD_TRACK_NUMBER bad;
  1628. ULONG num_bad, j;
  1629. ULONG i;
  1630. ULONG cyl;
  1631. ULONG percent;
  1632. ULONG sec_per_track;
  1633. ULONG sec_per_cyl;
  1634. HMEM hmem;
  1635. MSGID MessageId;
  1636. USHORT swap_buffer[3];
  1637. // We don't make sure that the volume is locked here because
  1638. // it's not strictly necessary and 'diskcopy' will format
  1639. // floppies without locking them.
  1640. if (!SetMediaType(MediaType) ||
  1641. (IsDmfFormat && QueryMediaType() != F3_1Pt44_512)) {
  1642. Message ? Message->DisplayMsg(MSG_NOT_SUPPORTED_BY_DRIVE) : 1;
  1643. return FALSE;
  1644. }
  1645. format_parameters = (PFORMAT_EX_PARAMETERS) format_parameters_buffer;
  1646. format_parameters->MediaType = QueryMediaType();
  1647. format_parameters->StartHeadNumber = 0;
  1648. format_parameters->EndHeadNumber = QueryHeads() - 1;
  1649. if (IsDmfFormat) {
  1650. sec_per_track = 21;
  1651. format_parameters->FormatGapLength = 8;
  1652. format_parameters->SectorsPerTrack = (USHORT) sec_per_track;
  1653. format_parameters->SectorNumber[0] = 12;
  1654. format_parameters->SectorNumber[1] = 2;
  1655. format_parameters->SectorNumber[2] = 13;
  1656. format_parameters->SectorNumber[3] = 3;
  1657. format_parameters->SectorNumber[4] = 14;
  1658. format_parameters->SectorNumber[5] = 4;
  1659. format_parameters->SectorNumber[6] = 15;
  1660. format_parameters->SectorNumber[7] = 5;
  1661. format_parameters->SectorNumber[8] = 16;
  1662. format_parameters->SectorNumber[9] = 6;
  1663. format_parameters->SectorNumber[10] = 17;
  1664. format_parameters->SectorNumber[11] = 7;
  1665. format_parameters->SectorNumber[12] = 18;
  1666. format_parameters->SectorNumber[13] = 8;
  1667. format_parameters->SectorNumber[14] = 19;
  1668. format_parameters->SectorNumber[15] = 9;
  1669. format_parameters->SectorNumber[16] = 20;
  1670. format_parameters->SectorNumber[17] = 10;
  1671. format_parameters->SectorNumber[18] = 21;
  1672. format_parameters->SectorNumber[19] = 11;
  1673. format_parameters->SectorNumber[20] = 1;
  1674. } else {
  1675. sec_per_track = QuerySectorsPerTrack();
  1676. }
  1677. sec_per_cyl = sec_per_track*QueryHeads();
  1678. DebugAssert(QueryCylinders().GetHighPart() == 0);
  1679. cyl = QueryCylinders().GetLowPart();
  1680. num_bad = QueryHeads();
  1681. if (num_bad == 0 || cyl == 0) {
  1682. return FALSE;
  1683. }
  1684. if (!(bad = NEW BAD_TRACK_NUMBER[num_bad])) {
  1685. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  1686. return FALSE;
  1687. }
  1688. if (!hmem.Acquire(sec_per_cyl*QuerySectorSize(), QueryAlignmentMask())) {
  1689. Message ? Message->DisplayMsg(MSG_FMT_NO_MEMORY) : 1;
  1690. return FALSE;
  1691. }
  1692. Message ? Message->DisplayMsg(MSG_PERCENT_COMPLETE, "%d", 0) : 1;
  1693. percent = 0;
  1694. for (i = 0; i < cyl; i++) {
  1695. format_parameters->StartCylinderNumber = i;
  1696. format_parameters->EndCylinderNumber = i;
  1697. if (IsDmfFormat) {
  1698. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  1699. &status_block,
  1700. IOCTL_DISK_FORMAT_TRACKS_EX,
  1701. format_parameters,
  1702. format_parameters_size,
  1703. bad, num_bad*
  1704. sizeof(BAD_TRACK_NUMBER));
  1705. // Skew the next cylinder by 3 sectors from this one.
  1706. RtlMoveMemory(swap_buffer,
  1707. &format_parameters->SectorNumber[18],
  1708. 3*sizeof(USHORT));
  1709. RtlMoveMemory(&format_parameters->SectorNumber[3],
  1710. &format_parameters->SectorNumber[0],
  1711. 18*sizeof(USHORT));
  1712. RtlMoveMemory(&format_parameters->SectorNumber[0],
  1713. swap_buffer,
  1714. 3*sizeof(USHORT));
  1715. } else {
  1716. _last_status = NtDeviceIoControlFile(_handle, 0, NULL, NULL,
  1717. &status_block,
  1718. IOCTL_DISK_FORMAT_TRACKS,
  1719. format_parameters,
  1720. sizeof(FORMAT_PARAMETERS),
  1721. bad, num_bad*
  1722. sizeof(BAD_TRACK_NUMBER));
  1723. }
  1724. if (!NT_SUCCESS(_last_status)) {
  1725. DELETE_ARRAY(bad);
  1726. switch( _last_status ) {
  1727. case STATUS_NO_MEDIA_IN_DEVICE:
  1728. MessageId = MSG_FORMAT_NO_MEDIA_IN_DRIVE;
  1729. break;
  1730. case STATUS_MEDIA_WRITE_PROTECTED:
  1731. MessageId = MSG_FMT_WRITE_PROTECTED_MEDIA ;
  1732. break;
  1733. case STATUS_DEVICE_BUSY:
  1734. case STATUS_DEVICE_NOT_READY:
  1735. MessageId = MSG_DEVICE_BUSY;
  1736. break;
  1737. default:
  1738. MessageId = MSG_BAD_IOCTL;
  1739. break;
  1740. }
  1741. Message ? Message->DisplayMsg(MessageId) : 1;
  1742. return FALSE;
  1743. }
  1744. // Verify the sectors.
  1745. if (BadSectors) {
  1746. if (!Read(i*sec_per_cyl, sec_per_cyl, hmem.GetBuf())) {
  1747. // If this is the first track then fail.
  1748. // A disk with a bad cylinder 0 is not
  1749. // worth continuing on.
  1750. //
  1751. // As of 7/29/94, formatting 2.88 floppies to 1.44
  1752. // doesn't work on Alphas; if we can't format to
  1753. // 1.44 and 2.88 is supported, try 2.88.
  1754. //
  1755. if (i == 0) {
  1756. if( !IsDmfFormat &&
  1757. QueryMediaType() == F3_1Pt44_512 &&
  1758. SetMediaType(F3_2Pt88_512) ) {
  1759. return( FormatVerifyFloppy( F3_2Pt88_512,
  1760. BadSectors,
  1761. Message,
  1762. IsDmfFormat ) );
  1763. } else {
  1764. Message ? Message->DisplayMsg(MSG_UNUSABLE_DISK) : 1;
  1765. return FALSE;
  1766. }
  1767. }
  1768. for (j = 0; j < sec_per_cyl; j++) {
  1769. if (!Read(i*sec_per_cyl + j, 1, hmem.GetBuf())) {
  1770. if (!BadSectors->Add(i*sec_per_cyl + j)) {
  1771. return FALSE;
  1772. }
  1773. }
  1774. }
  1775. }
  1776. }
  1777. if ((i + 1)*100/cyl > percent) {
  1778. percent = (i + 1)*100/cyl;
  1779. if (percent > 100) {
  1780. percent = 100;
  1781. }
  1782. // This check for success on the message object
  1783. // has to be there for FMIFS to implement CANCEL.
  1784. if (Message && !Message->DisplayMsg(MSG_PERCENT_COMPLETE, "%d", percent)) {
  1785. DELETE_ARRAY(bad);
  1786. return FALSE;
  1787. }
  1788. }
  1789. }
  1790. DELETE_ARRAY(bad);
  1791. #endif
  1792. return TRUE;
  1793. }
  1794. DEFINE_EXPORTED_CONSTRUCTOR( LOG_IO_DP_DRIVE, IO_DP_DRIVE, IFSUTIL_EXPORT );
  1795. IFSUTIL_EXPORT
  1796. LOG_IO_DP_DRIVE::~LOG_IO_DP_DRIVE(
  1797. )
  1798. /*++
  1799. Routine Description:
  1800. Destructor for LOG_IO_DP_DRIVE.
  1801. Arguments:
  1802. None.
  1803. Return Value:
  1804. None.
  1805. --*/
  1806. {
  1807. }
  1808. IFSUTIL_EXPORT
  1809. BOOLEAN
  1810. LOG_IO_DP_DRIVE::Initialize(
  1811. IN PCWSTRING NtDriveName,
  1812. IN OUT PMESSAGE Message,
  1813. IN BOOLEAN ExclusiveWrite
  1814. )
  1815. /*++
  1816. Routine Description:
  1817. This routine initializes a LOG_IO_DP_DRIVE object.
  1818. Arguments:
  1819. NtDriveName - Supplies the path of the drive object.
  1820. Message - Supplies an outlet for messages.
  1821. ExclusiveWrite - Supplies whether or not to open the drive for
  1822. exclusive write.
  1823. Return Value:
  1824. FALSE - Failure.
  1825. TRUE - Success.
  1826. --*/
  1827. {
  1828. return IO_DP_DRIVE::Initialize(NtDriveName, Message, ExclusiveWrite);
  1829. }
  1830. IFSUTIL_EXPORT
  1831. BOOLEAN
  1832. LOG_IO_DP_DRIVE::Initialize(
  1833. IN PCWSTRING NtDriveName,
  1834. IN PCWSTRING HostFileName,
  1835. IN OUT PMESSAGE Message,
  1836. IN BOOLEAN ExclusiveWrite
  1837. )
  1838. /*++
  1839. Routine Description:
  1840. This routine initializes a LOG_IO_DP_DRIVE object for a hosted
  1841. drive, i.e. one which is implemented as a file on another volume.
  1842. Arguments:
  1843. NtDriveName - Supplies the path of the drive object.
  1844. HostFileName - Supplies the fully qualified name of the host file.
  1845. Message - Supplies an outlet for messages.
  1846. ExclusiveWrite - Supplies whether or not to open the drive for
  1847. exclusive write.
  1848. Return Value:
  1849. FALSE - Failure.
  1850. TRUE - Success.
  1851. --*/
  1852. {
  1853. return IO_DP_DRIVE::Initialize(NtDriveName,
  1854. HostFileName,
  1855. Message,
  1856. ExclusiveWrite);
  1857. }
  1858. IFSUTIL_EXPORT
  1859. BOOLEAN
  1860. LOG_IO_DP_DRIVE::SetSystemId(
  1861. IN PARTITION_SYSTEM_ID SystemId
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. This routine sets the system identifier (or partition type) in the
  1866. MBR. BUGBUG doesn't currently handle extended partitions.
  1867. Arguments:
  1868. SystemId - Supplies the system id to write in the partition entry.
  1869. Return Value:
  1870. FALSE - Failure.
  1871. TRUE - Success.
  1872. --*/
  1873. {
  1874. MBR_PARTITION_RECORD *partition_info;
  1875. MASTER_BOOT_RECORD *pMbr;
  1876. EFI_STATUS status;
  1877. DEBUG((D_INFO,(CHAR8*)"Inside SetSystemId.\n" ));
  1878. //
  1879. // This operation is unnecessary on floppies, super-floppies, and
  1880. // hosted volumes.
  1881. //
  1882. if (IsFloppy() || IsSuperFloppy() || _hosted_drive) {
  1883. DEBUG((D_INFO,(CHAR8*)"No need to set partition type.\n" ));
  1884. return TRUE;
  1885. }
  1886. if( SystemId == SYSID_NONE ) {
  1887. // Note: we should never set it to zero!
  1888. DEBUG((D_INFO,(CHAR8*)"Skip setting the partition type to zero.\n" ));
  1889. return TRUE;
  1890. }
  1891. //
  1892. // Now we have to read the MBR and set the type ourselves
  1893. //
  1894. pMbr = ( MASTER_BOOT_RECORD * ) AllocatePool( sizeof( MASTER_BOOT_RECORD ) );
  1895. if ( !pMbr ) {
  1896. DEBUG((D_ERROR,(CHAR8*)"LOG_IO_DP_DRIVE::SetSystemId couldn't allocate MBR.\n"));
  1897. return FALSE;
  1898. }
  1899. //
  1900. // Now read the MBR
  1901. //
  1902. status = _device_disk_io->ReadDisk ( _device_disk_io,
  1903. _device_block_io->Media->MediaId,
  1904. 0,
  1905. sizeof( MASTER_BOOT_RECORD ),
  1906. pMbr
  1907. );
  1908. if ( EFI_ERROR( status ) ) {
  1909. DEBUG((D_ERROR,(CHAR8*)"LOG_IO_DP_DRIVE::SetSystemId couldn't read MBR.\n"));
  1910. FreePool (pMbr);
  1911. return FALSE;
  1912. }
  1913. //
  1914. // Check to see if this is a GPT disk
  1915. //
  1916. partition_info = &(pMbr->Partition[0]);
  1917. //
  1918. // According to spec, the GPT signature should be the only thing to determine if
  1919. // it is a GPT partition. There is no need to check for the partition
  1920. // type to see if it is 0xEE first. However, LDM does not appear to zap the
  1921. // signature when converting a GPT disk to MBR disk.
  1922. //
  1923. if (partition_info->OSIndicator != SYSID_EFI) {
  1924. if (_partition_number) {
  1925. DEBUG((D_INFO,(CHAR8*)"Setting partition %d id to %x\n", _partition_number, SystemId));
  1926. //
  1927. // Set the system ID in the correct partition
  1928. // of the MBR since it's not a GPT disk
  1929. //
  1930. partition_info = &( pMbr->Partition[_partition_number - 1] );
  1931. partition_info->OSIndicator = (UCHAR)SystemId;
  1932. //
  1933. // Write the MBR back out to the disk
  1934. //
  1935. status = _device_disk_io->WriteDisk( _device_disk_io,
  1936. _device_block_io->Media->MediaId,
  1937. 0,
  1938. sizeof( MASTER_BOOT_RECORD ),
  1939. pMbr
  1940. );
  1941. if ( EFI_ERROR( status ) ) {
  1942. DEBUG((D_ERROR,(CHAR8*)"LOG_IO_DP_DRIVE::SetSystemId couldn't write MBR.\n"));
  1943. FreePool (pMbr);
  1944. return FALSE;
  1945. }
  1946. _device_block_io->FlushBlocks( _device_block_io );
  1947. } else {
  1948. DEBUG((D_INFO,(CHAR8*)"Partition number is 0.\n" ));
  1949. }
  1950. } else {
  1951. DEBUG((D_INFO,(CHAR8*)"It is a GPT disk.\n" ));
  1952. }
  1953. DEBUG((D_INFO,(CHAR8*)"Leaving SetSystemId.\n" ));
  1954. FreePool (pMbr);
  1955. return TRUE;
  1956. }
  1957. #if defined(FE_SB) && defined(_X86_)
  1958. IFSUTIL_EXPORT
  1959. BOOLEAN
  1960. LOG_IO_DP_DRIVE::Read(
  1961. IN BIG_INT StartingSector,
  1962. IN SECTORCOUNT NumberOfSectors,
  1963. OUT PVOID Buffer
  1964. )
  1965. /*++
  1966. Routine Description:
  1967. This routine reads a run of sectors into the buffer pointed to by
  1968. 'Buffer'.
  1969. Arguments:
  1970. StartingSector - Supplies the first sector to be read.
  1971. NumberOfSectors - Supplies the number of sectors to be read.
  1972. Buffer - Supplies a buffer to read the run of sectors into.
  1973. Return Value:
  1974. FALSE - Failure.
  1975. TRUE - Success.
  1976. --*/
  1977. {
  1978. return IO_DP_DRIVE::Read(StartingSector, NumberOfSectors, Buffer);
  1979. }
  1980. IFSUTIL_EXPORT
  1981. BOOLEAN
  1982. LOG_IO_DP_DRIVE::Write(
  1983. BIG_INT StartingSector,
  1984. SECTORCOUNT NumberOfSectors,
  1985. PVOID Buffer
  1986. )
  1987. /*++
  1988. Routine Description:
  1989. This routine writes a run of sectors onto the disk from the buffer pointed
  1990. to by 'Buffer'. Writing is only permitted if 'Lock' was called.
  1991. Arguments:
  1992. StartingSector - Supplies the first sector to be written.
  1993. NumberOfSectors - Supplies the number of sectors to be written.
  1994. Buffer - Supplies the buffer to write the run of sectors from.
  1995. Return Value:
  1996. FALSE - Failure.
  1997. TRUE - Success.
  1998. --*/
  1999. {
  2000. return IO_DP_DRIVE::Write(StartingSector, NumberOfSectors, Buffer);
  2001. }
  2002. #endif // FE_SB && _X86_
  2003. DEFINE_CONSTRUCTOR( PHYS_IO_DP_DRIVE, IO_DP_DRIVE );
  2004. PHYS_IO_DP_DRIVE::~PHYS_IO_DP_DRIVE(
  2005. )
  2006. /*++
  2007. Routine Description:
  2008. Destructor for PHYS_IO_DP_DRIVE.
  2009. Arguments:
  2010. None.
  2011. Return Value:
  2012. None.
  2013. --*/
  2014. {
  2015. }
  2016. BOOLEAN
  2017. PHYS_IO_DP_DRIVE::Initialize(
  2018. IN PCWSTRING NtDriveName,
  2019. IN OUT PMESSAGE Message,
  2020. IN BOOLEAN ExclusiveWrite
  2021. )
  2022. /*++
  2023. Routine Description:
  2024. This routine initializes a PHYS_IO_DP_DRIVE object.
  2025. Arguments:
  2026. NtDriveName - Supplies the path of the drive object.
  2027. Message - Supplies an outlet for messages.
  2028. ExclusiveWrite - Supplies whether or not to open the drive for
  2029. exclusive write.
  2030. Return Value:
  2031. FALSE - Failure.
  2032. TRUE - Success.
  2033. --*/
  2034. {
  2035. return IO_DP_DRIVE::Initialize(NtDriveName, Message, ExclusiveWrite);
  2036. }