Skip to content

Commit c6be3e4

Browse files
mayank-microsoftos-d
authored andcommitted
MdeModulePkg: ScsiDiskDxe: Query Write Protected State
Currently, only SCSI attached CDROMs are marked as read only SCSI devices. Write failures have been seen to occur when a read only disk is attached as a SCSI device, because the device is never queried for its write protected state and the disk is listed as writeable. This adds a new mode sense query to determine if a SCSI disk is write protected. If so, the proper BlockIO media property is set to read only, to ensure that all layers know this is a read only disk. Signed-off-by: Oliver Smith-Denny <[email protected]>
1 parent c9672ff commit c6be3e4

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,65 @@ ScsiDiskDriverBindingSupported (
196196
return Status;
197197
}
198198

199+
/**
200+
Check whether the SCSI disk is write protected.
201+
202+
@param[in] ScsiDiskDevice The SCSI disk device.
203+
@param[out] WriteProtectionEnabled A pointer to a Boolean that will be set to TRUE if the disk is write protected,
204+
FALSE otherwise.
205+
206+
@retval EFI_SUCCESS The operation completed successfully.
207+
@retval other An error occurred while executing the SCSI command.
208+
*/
209+
STATIC
210+
EFI_STATUS
211+
IsWriteProtected (
212+
IN OUT SCSI_DISK_DEV *ScsiDiskDevice,
213+
OUT BOOLEAN *WriteProtectionEnabled
214+
)
215+
{
216+
EFI_STATUS Status;
217+
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
218+
UINT8 Cdb[6];
219+
UINT8 DataBuffer[64];
220+
221+
if ((ScsiDiskDevice == NULL) || (ScsiDiskDevice->ScsiIo == NULL) || (WriteProtectionEnabled == NULL)) {
222+
return EFI_INVALID_PARAMETER;
223+
}
224+
225+
//
226+
// Initialize SCSI REQUEST_PACKET and 6-byte Cdb
227+
//
228+
ZeroMem (&CommandPacket, sizeof (CommandPacket));
229+
ZeroMem (Cdb, sizeof (Cdb));
230+
231+
// Initialize output parameter to default value
232+
*WriteProtectionEnabled = FALSE;
233+
234+
Cdb[0] = ATA_CMD_MODE_SENSE6;
235+
Cdb[1] = BIT3; // Setting the bit for Disable Block Descriptor
236+
Cdb[2] = ATA_PAGE_CODE_RETURN_ALL_PAGES;
237+
Cdb[4] = sizeof (DataBuffer);
238+
239+
CommandPacket.Timeout = SCSI_DISK_TIMEOUT;
240+
CommandPacket.Cdb = Cdb;
241+
CommandPacket.CdbLength = (UINT8)sizeof (Cdb);
242+
CommandPacket.InDataBuffer = &DataBuffer;
243+
CommandPacket.InTransferLength = sizeof (DataBuffer);
244+
245+
Status = ScsiDiskDevice->ScsiIo->ExecuteScsiCommand (ScsiDiskDevice->ScsiIo, &CommandPacket, NULL);
246+
247+
if (EFI_ERROR (Status)) {
248+
return Status;
249+
}
250+
251+
// Mode Sense 6 Byte Command returns the Write Protection status in the 3rd byte
252+
// Bit 7 of the 3rd byte indicates the Write Protection status
253+
// See SCSI Block Commands - 3 section 6.3.1 and SCSI-2 Spec, 8.3.3.
254+
*WriteProtectionEnabled = (DataBuffer[2] & BIT7) != 0;
255+
return EFI_SUCCESS;
256+
}
257+
199258
/**
200259
Start this driver on ControllerHandle.
201260
@@ -234,6 +293,7 @@ ScsiDiskDriverBindingStart (
234293
CHAR8 VendorStr[VENDOR_IDENTIFICATION_LENGTH + 1];
235294
CHAR8 ProductStr[PRODUCT_IDENTIFICATION_LENGTH + 1];
236295
CHAR16 DeviceStr[VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2];
296+
BOOLEAN WriteProtectionEnabled = FALSE;
237297

238298
MustReadCapacity = TRUE;
239299

@@ -297,6 +357,17 @@ ScsiDiskDriverBindingStart (
297357
break;
298358
}
299359

360+
if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {
361+
Status = IsWriteProtected (ScsiDiskDevice, &WriteProtectionEnabled);
362+
if (EFI_ERROR (Status)) {
363+
DEBUG ((DEBUG_ERROR, "ScsiDisk: IsWriteProtected() fails. Status = %r\n", Status));
364+
}
365+
366+
if (WriteProtectionEnabled) {
367+
ScsiDiskDevice->BlkIo.Media->ReadOnly = TRUE;
368+
}
369+
}
370+
300371
//
301372
// The Sense Data Array's initial size is 6
302373
//

0 commit comments

Comments
 (0)