Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,68 @@ ScsiDiskDriverBindingSupported (
return Status;
}

// MU_CHANGE Begin: Add function to check whether the disk is write protected

/**
y * Check whether the SCSI disk is write protected.
*
* @param ScsiDiskDevice The SCSI disk device.
* @param WriteProtectionEnabled A pointer to a boolean that will be set to TRUE if the disk is write protected, FALSE otherwise.
*
* @return EFI_SUCCESS The operation completed successfully.
* @return EFI_INVALID_PARAMETER One of the input parameters was invalid.
* @return other An error occurred while executing the SCSI command.
*/
STATIC
EFI_STATUS
IsWriteProtected (
IN OUT SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *WriteProtectionEnabled
)
{
EFI_STATUS Status;
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
UINT8 Cdb[6];
UINT8 DataBuffer[64];

if ((ScsiDiskDevice == NULL) || (WriteProtectionEnabled == NULL) || (ScsiDiskDevice->ScsiIo == NULL)) {
return EFI_INVALID_PARAMETER;
}

//
// Initialize SCSI REQUEST_PACKET and 6-byte Cdb
//
ZeroMem (&CommandPacket, sizeof (CommandPacket));
ZeroMem (Cdb, sizeof (Cdb));

// Initialize output parameter to default value
*WriteProtectionEnabled = FALSE;

Cdb[0] = ATA_CMD_MODE_SENSE6;
Cdb[1] = 0b1000; // Setting the bit for Disable Block Descriptor
Cdb[2] = ATA_PAGE_CODE_RETURN_ALL_PAGES;
Cdb[4] = sizeof (DataBuffer);

CommandPacket.Timeout = SCSI_DISK_TIMEOUT;
CommandPacket.Cdb = Cdb;
CommandPacket.CdbLength = (UINT8)sizeof (Cdb);
CommandPacket.InDataBuffer = &DataBuffer;
CommandPacket.InTransferLength = sizeof (DataBuffer);

Status = ScsiDiskDevice->ScsiIo->ExecuteScsiCommand (ScsiDiskDevice->ScsiIo, &CommandPacket, NULL);

if (EFI_ERROR (Status)) {
return Status;
}

// Mode Sense 6 Byte Command returns the Write Protection status in the 3rd byte
// Bit 7 of the 3rd byte indicates the Write Protection status
*WriteProtectionEnabled = (DataBuffer[2] & 0x80) != 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where do you find this definition? I did a quick search and couldn't find it defined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spbrogan the SCSI stuff is not easily searchable, but copilot does a good job finding the write docs :). https://www.t10.org/ftp/t10/document.05/05-344r0.pdf see section 6.3.1.

return EFI_SUCCESS;
}

// MU_CHANGE End: Add function to check whether the disk is write protected

/**
Start this driver on ControllerHandle.

Expand Down Expand Up @@ -234,6 +296,8 @@ ScsiDiskDriverBindingStart (
CHAR8 VendorStr[VENDOR_IDENTIFICATION_LENGTH + 1];
CHAR8 ProductStr[PRODUCT_IDENTIFICATION_LENGTH + 1];
CHAR16 DeviceStr[VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2];
// MU_CHANGE: Add variable to check whether the disk is write protected
BOOLEAN WriteProtectionEnabled = FALSE;

MustReadCapacity = TRUE;

Expand Down Expand Up @@ -297,6 +361,20 @@ ScsiDiskDriverBindingStart (
break;
}

// MU_CHANGE Begin: Check whether the disk is write protected and set the ReadOnly flag accordingly
if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {
Status = IsWriteProtected (ScsiDiskDevice, &WriteProtectionEnabled);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "ScsiDisk: IsWriteProtected() fails. Status = %r\n", Status));
}

if (WriteProtectionEnabled) {
ScsiDiskDevice->BlkIo.Media->ReadOnly = TRUE;
}
}

// MU_CHANGE End: Check whether the disk is write protected and set the ReadOnly flag accordingly

//
// The Sense Data Array's initial size is 6
//
Expand Down
2 changes: 2 additions & 0 deletions MdePkg/Include/IndustryStandard/Atapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ typedef union {
#define ATA_CMD_PREVENT_ALLOW_MEDIA_REMOVAL 0x1E ///< defined in ATAPI Removable Rewritable Media Devices
#define ATA_CMD_MODE_SELECT 0x55 ///< defined in ATAPI Removable Rewritable Media Devices

// MU_CHANGE: Add some definitions for MODE SENSE (6-Byte) command
#define ATA_CMD_MODE_SENSE6 0x1A ///< defined in ATAPI Removable Rewritable Media Devices
#define ATA_CMD_MODE_SENSE 0x5A ///< defined in ATAPI Removable Rewritable Media Devices
#define ATA_PAGE_CODE_READ_WRITE_ERROR 0x01 ///< defined in ATAPI Removable Rewritable Media Devices
#define ATA_PAGE_CODE_CACHING_PAGE 0x08 ///< defined in ATAPI Removable Rewritable Media Devices
Expand Down