This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces\r
for managed ATA controllers.\r
\r
- Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
NULL,\r
NULL\r
},\r
+ 0, // EnabledPciAttributes\r
0, // OriginalAttributes\r
0, // PreviousPort\r
0, // PreviousPortMultiplier\r
0xFF, 0xFF, 0xFF, 0xFF\r
};\r
\r
+EDKII_ATA_ATAPI_POLICY_PROTOCOL *mAtaAtapiPolicy;\r
+EDKII_ATA_ATAPI_POLICY_PROTOCOL mDefaultAtaAtapiPolicy = {\r
+ EDKII_ATA_ATAPI_POLICY_VERSION,\r
+ 2, // PuisEnable\r
+ 0, // DeviceSleepEnable\r
+ 0, // AggressiveDeviceSleepEnable\r
+ 0 // Reserved\r
+};\r
+\r
/**\r
Sends an ATA command to an ATA device that is attached to the ATA controller. This function\r
supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,\r
\r
@param[in] Port The port number of the ATA device to send the command.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
- If there is no port multiplier, then specify 0.\r
+ If there is no port multiplier, then specify 0xFFFF.\r
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port\r
and PortMultiplierPort.\r
@param[in] Instance Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.\r
}\r
break;\r
case EfiAtaAhciMode :\r
+ if (PortMultiplierPort == 0xFFFF) {\r
+ //\r
+ // If there is no port multiplier, PortMultiplierPort will be 0xFFFF\r
+ // according to UEFI spec. Here, we convert its value to 0 to follow\r
+ // AHCI spec.\r
+ //\r
+ PortMultiplierPort = 0;\r
+ }\r
switch (Protocol) {\r
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:\r
Status = AhciNonDataTransfer (\r
EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInit;\r
ATA_ATAPI_PASS_THRU_INSTANCE *Instance;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINT64 Supports;\r
+ UINT64 EnabledPciAttributes;\r
UINT64 OriginalPciAttributes;\r
\r
Status = EFI_SUCCESS;\r
PciIo,\r
EfiPciIoAttributeOperationSupported,\r
0,\r
- &Supports\r
+ &EnabledPciAttributes\r
);\r
if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
Status = PciIo->Attributes (\r
PciIo,\r
EfiPciIoAttributeOperationEnable,\r
- Supports,\r
+ EnabledPciAttributes,\r
NULL\r
);\r
}\r
goto ErrorExit;\r
}\r
\r
+ Status = gBS->LocateProtocol (&gEdkiiAtaAtapiPolicyProtocolGuid, NULL, (VOID **)&mAtaAtapiPolicy);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If there is no AtaAtapiPolicy exposed, use the default policy.\r
+ //\r
+ mAtaAtapiPolicy = &mDefaultAtaAtapiPolicy;\r
+ }\r
+\r
//\r
// Allocate a buffer to store the ATA_ATAPI_PASS_THRU_INSTANCE data structure\r
//\r
Instance->ControllerHandle = Controller;\r
Instance->IdeControllerInit = IdeControllerInit;\r
Instance->PciIo = PciIo;\r
+ Instance->EnabledPciAttributes = EnabledPciAttributes;\r
Instance->OriginalPciAttributes = OriginalPciAttributes;\r
Instance->AtaPassThru.Mode = &Instance->AtaPassThruMode;\r
Instance->ExtScsiPassThru.Mode = &Instance->ExtScsiPassThruMode;\r
gBS->CloseEvent (Instance->TimerEvent);\r
}\r
\r
- //\r
- // Remove all inserted ATA devices.\r
- //\r
- DestroyDeviceInfoList(Instance);\r
-\r
if (Instance != NULL) {\r
+ //\r
+ // Remove all inserted ATA devices.\r
+ //\r
+ DestroyDeviceInfoList (Instance);\r
FreePool (Instance);\r
}\r
return EFI_UNSUPPORTED;\r
EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
EFI_AHCI_REGISTERS *AhciRegisters;\r
- UINT64 Supports;\r
\r
DEBUG ((EFI_D_INFO, "==AtaAtapiPassThru Stop== Controller = %x\n", Controller));\r
\r
//\r
DestroyDeviceInfoList (Instance);\r
\r
+ PciIo = Instance->PciIo;\r
+\r
+ //\r
+ // Disable this ATA host controller.\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationDisable,\r
+ Instance->EnabledPciAttributes,\r
+ NULL\r
+ );\r
+\r
//\r
// If the current working mode is AHCI mode, then pre-allocated resource\r
// for AHCI initialization should be released.\r
//\r
- PciIo = Instance->PciIo;\r
-\r
if (Instance->Mode == EfiAtaAhciMode) {\r
AhciRegisters = &Instance->AhciRegisters;\r
PciIo->Unmap (\r
);\r
}\r
\r
- //\r
- // Disable this ATA host controller.\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
- PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
-\r
//\r
// Restore original PCI attributes\r
//\r
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
@param[in] Port The port number of the ATA device to send the command.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
- If there is no port multiplier, then specify 0.\r
+ If there is no port multiplier, then specify 0xFFFF.\r
@param[in] DeviceType The device type of the ATA device.\r
\r
@retval The pointer to the data structure of the device info to access.\r
while (!IsNull (&Instance->DeviceList, Node)) {\r
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);\r
\r
+ //\r
+ // For CD-ROM working in the AHCI mode, only 8 bits are used to record\r
+ // the PortMultiplier information. If the CD-ROM is directly attached\r
+ // on a SATA port, the PortMultiplier should be translated from 0xFF\r
+ // to 0xFFFF according to the UEFI spec.\r
+ //\r
+ if ((Instance->Mode == EfiAtaAhciMode) &&\r
+ (DeviceInfo->Type == EfiIdeCdrom) &&\r
+ (PortMultiplier == 0xFF)) {\r
+ PortMultiplier = 0xFFFF;\r
+ }\r
+\r
if ((DeviceInfo->Type == DeviceType) &&\r
(Port == DeviceInfo->Port) &&\r
(PortMultiplier == DeviceInfo->PortMultiplier)) {\r
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
@param[in] Port The port number of the ATA device to send the command.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
- If there is no port multiplier, then specify 0.\r
+ If there is no port multiplier, then specify 0xFFFF.\r
@param[in] DeviceType The device type of the ATA device.\r
@param[in] IdentifyData The data buffer to store the output of the IDENTIFY cmd.\r
\r
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
@param[in] Port The port number of the ATA device to send the command.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
- If there is no port multiplier, then specify 0.\r
+ If there is no port multiplier, then specify 0xFFFF.\r
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port\r
and PortMultiplierPort.\r
@param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking\r
UINT32 MaxSectorCount;\r
ATA_NONBLOCK_TASK *Task;\r
EFI_TPL OldTpl;\r
+ UINT32 BlockSize;\r
\r
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);\r
\r
}\r
}\r
\r
- //\r
- // convert the transfer length from sector count to byte.\r
- //\r
- if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&\r
- (Packet->InTransferLength != 0)) {\r
- Packet->InTransferLength = Packet->InTransferLength * 0x200;\r
- }\r
-\r
- //\r
- // convert the transfer length from sector count to byte.\r
- //\r
- if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&\r
- (Packet->OutTransferLength != 0)) {\r
- Packet->OutTransferLength = Packet->OutTransferLength * 0x200;\r
- }\r
-\r
//\r
// Check whether this device needs 48-bit addressing (ATAPI-6 ata device).\r
// Per ATA-6 spec, word83: bit15 is zero and bit14 is one.\r
}\r
}\r
\r
+ BlockSize = 0x200;\r
+ if ((IdentifyData->AtaData.phy_logic_sector_support & (BIT14 | BIT15)) == BIT14) {\r
+ //\r
+ // Check logical block size\r
+ //\r
+ if ((IdentifyData->AtaData.phy_logic_sector_support & BIT12) != 0) {\r
+ BlockSize = (UINT32) (((IdentifyData->AtaData.logic_sector_size_hi << 16) | IdentifyData->AtaData.logic_sector_size_lo) * sizeof (UINT16));\r
+ }\r
+ }\r
+\r
+ //\r
+ // convert the transfer length from sector count to byte.\r
+ //\r
+ if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&\r
+ (Packet->InTransferLength != 0)) {\r
+ Packet->InTransferLength = Packet->InTransferLength * BlockSize;\r
+ }\r
+\r
+ //\r
+ // convert the transfer length from sector count to byte.\r
+ //\r
+ if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&\r
+ (Packet->OutTransferLength != 0)) {\r
+ Packet->OutTransferLength = Packet->OutTransferLength * BlockSize;\r
+ }\r
+\r
//\r
// If the data buffer described by InDataBuffer/OutDataBuffer and InTransferLength/OutTransferLength\r
// is too big to be transferred in a single command, then no data is transferred and EFI_BAD_BUFFER_SIZE\r
// is returned.\r
//\r
- if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * 0x200)) ||\r
- ((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * 0x200))) {\r
+ if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * BlockSize)) ||\r
+ ((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * BlockSize))) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
Task->Packet = Packet;\r
Task->Event = Event;\r
Task->IsStart = FALSE;\r
- Task->RetryTimes = 0;\r
+ Task->RetryTimes = DivU64x32(Packet->Timeout, 1000) + 1;\r
+ if (Packet->Timeout == 0) {\r
+ Task->InfiniteWait = TRUE;\r
+ } else {\r
+ Task->InfiniteWait = FALSE;\r
+ }\r
\r
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (*PortMultiplierPort == 0xFFFF) {\r
+ if (Instance->PreviousPortMultiplier == 0xFFFF) {\r
//\r
- // If the PortMultiplierPort is all 0xFF's, start to traverse the device list from the beginning\r
+ // If a device is directly attached on a port, previous call to this\r
+ // function will return the value 0xFFFF for PortMultiplierPort. In\r
+ // this case, there should be no more device on the port multiplier.\r
//\r
+ Instance->PreviousPortMultiplier = 0;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (*PortMultiplierPort == Instance->PreviousPortMultiplier) {\r
Node = GetFirstNode (&Instance->DeviceList);\r
\r
while (!IsNull (&Instance->DeviceList, Node)) {\r
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);\r
\r
if ((DeviceInfo->Type == EfiIdeHarddisk) &&\r
- (DeviceInfo->Port == Port)){\r
+ (DeviceInfo->Port == Port) &&\r
+ (DeviceInfo->PortMultiplier > *PortMultiplierPort)){\r
*PortMultiplierPort = DeviceInfo->PortMultiplier;\r
goto Exit;\r
}\r
}\r
\r
return EFI_NOT_FOUND;\r
- } else if (*PortMultiplierPort == Instance->PreviousPortMultiplier) {\r
+ } else if (*PortMultiplierPort == 0xFFFF) {\r
+ //\r
+ // If the PortMultiplierPort is all 0xFF's, start to traverse the device list from the beginning\r
+ //\r
Node = GetFirstNode (&Instance->DeviceList);\r
\r
while (!IsNull (&Instance->DeviceList, Node)) {\r
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);\r
\r
if ((DeviceInfo->Type == EfiIdeHarddisk) &&\r
- (DeviceInfo->Port == Port) &&\r
- (DeviceInfo->PortMultiplier > *PortMultiplierPort)){\r
+ (DeviceInfo->Port == Port)){\r
*PortMultiplierPort = DeviceInfo->PortMultiplier;\r
goto Exit;\r
}\r
device path node is to be allocated and built.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a\r
device path node is to be allocated and built. If there is no\r
- port multiplier, then specify 0.\r
+ port multiplier, then specify 0xFFFF.\r
@param[in, out] DevicePath A pointer to a single device path node that describes the ATA\r
device specified by Port and PortMultiplierPort. This function\r
is responsible for allocating the buffer DevicePath with the\r
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
@param[in] Port Port represents the port number of the ATA device to be reset.\r
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset.\r
- If there is no port multiplier, then specify 0.\r
+ If there is no port multiplier, then specify 0xFFFF.\r
@retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset.\r
@retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation.\r
@retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid.\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Submit ATAPI request sense command.\r
+\r
+ @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Target The Target is an array of size TARGET_MAX_BYTES and it represents\r
+ the id of the SCSI device to send the SCSI Request Packet. Each\r
+ transport driver may choose to utilize a subset of this size to suit the needs\r
+ of transport target representation. For example, a Fibre Channel driver\r
+ may use only 8 bytes (WWN) to represent an FC target.\r
+ @param[in] Lun The LUN of the SCSI device to send the SCSI Request Packet.\r
+ @param[in] SenseData A pointer to store sense data.\r
+ @param[in] SenseDataLength The sense data length.\r
+ @param[in] Timeout The timeout value to execute this cmd, uses 100ns as a unit.\r
+\r
+ @retval EFI_SUCCESS Send out the ATAPI packet command successfully.\r
+ @retval EFI_DEVICE_ERROR The device failed to send data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPacketRequestSense (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun,\r
+ IN VOID *SenseData,\r
+ IN UINT8 SenseDataLength,\r
+ IN UINT64 Timeout\r
+ )\r
+{\r
+ EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet;\r
+ UINT8 Cdb[12];\r
+ EFI_STATUS Status;\r
+\r
+ ZeroMem (&Packet, sizeof (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, 12);\r
+\r
+ Cdb[0] = ATA_CMD_REQUEST_SENSE;\r
+ Cdb[4] = SenseDataLength;\r
+\r
+ Packet.Timeout = Timeout;\r
+ Packet.Cdb = Cdb;\r
+ Packet.CdbLength = 12;\r
+ Packet.DataDirection = EFI_EXT_SCSI_DATA_DIRECTION_READ;\r
+ Packet.InDataBuffer = SenseData;\r
+ Packet.InTransferLength = SenseDataLength;\r
+\r
+ Status = ExtScsiPassThruPassThru (This, Target, Lun, &Packet, NULL);\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function\r
supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the\r
EFI_ATA_HC_WORK_MODE Mode;\r
LIST_ENTRY *Node;\r
EFI_ATA_DEVICE_INFO *DeviceInfo;\r
+ BOOLEAN SenseReq;\r
+ EFI_SCSI_SENSE_DATA *PtrSenseData;\r
+ UINTN SenseDataLen;\r
+ EFI_STATUS SenseStatus;\r
\r
- Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);\r
+ SenseDataLen = 0;\r
+ Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);\r
\r
if ((Packet == NULL) || (Packet->Cdb == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
if (*((UINT8*)Packet->Cdb) == ATA_CMD_IDENTIFY_DEVICE) {\r
CopyMem (Packet->InDataBuffer, DeviceInfo->IdentifyData, sizeof (EFI_IDENTIFY_DATA));\r
+ //\r
+ // For IDENTIFY DEVICE cmd, we don't need to get sense data.\r
+ //\r
+ Packet->SenseDataLength = 0;\r
return EFI_SUCCESS;\r
}\r
\r
Status = AtaPacketCommandExecute (Instance->PciIo, &Instance->IdeRegisters[Port], Port, PortMultiplier, Packet);\r
break;\r
case EfiAtaAhciMode:\r
+ if (PortMultiplier == 0xFF) {\r
+ //\r
+ // If there is no port multiplier, the PortMultiplier will be 0xFF\r
+ // Here, we convert its value to 0 to follow the AHCI spec.\r
+ //\r
+ PortMultiplier = 0;\r
+ }\r
Status = AhciPacketCommandExecute (Instance->PciIo, &Instance->AhciRegisters, Port, PortMultiplier, Packet);\r
break;\r
default :\r
break;\r
}\r
\r
+ //\r
+ // If the cmd doesn't get executed correctly, then check sense data.\r
+ //\r
+ if (EFI_ERROR (Status) && (Packet->SenseDataLength != 0) && (*((UINT8*)Packet->Cdb) != ATA_CMD_REQUEST_SENSE)) {\r
+ PtrSenseData = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)), This->Mode->IoAlign);\r
+ if (PtrSenseData == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ for (SenseReq = TRUE; SenseReq;) {\r
+ SenseStatus = AtaPacketRequestSense (\r
+ This,\r
+ Target,\r
+ Lun,\r
+ PtrSenseData,\r
+ sizeof (EFI_SCSI_SENSE_DATA),\r
+ Packet->Timeout\r
+ );\r
+ if (EFI_ERROR (SenseStatus)) {\r
+ break;\r
+ }\r
+\r
+ CopyMem ((UINT8*)Packet->SenseData + SenseDataLen, PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));\r
+ SenseDataLen += sizeof (EFI_SCSI_SENSE_DATA);\r
+\r
+ //\r
+ // no more sense key or number of sense keys exceeds predefined,\r
+ // skip the loop.\r
+ //\r
+ if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||\r
+ (SenseDataLen + sizeof (EFI_SCSI_SENSE_DATA) > Packet->SenseDataLength)) {\r
+ SenseReq = FALSE;\r
+ }\r
+ }\r
+ FreeAlignedPages (PtrSenseData, EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)));\r
+ }\r
+ //\r
+ // Update the SenseDataLength field to the data length received.\r
+ //\r
+ Packet->SenseDataLength = (UINT8)SenseDataLen;\r
return Status;\r
}\r
\r
if ((DeviceInfo->Type == EfiIdeCdrom) &&\r
((Target8[0] < DeviceInfo->Port) ||\r
((Target8[0] == DeviceInfo->Port) &&\r
- (Target8[1] < DeviceInfo->PortMultiplier)))) {\r
+ (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {\r
Target8[0] = (UINT8)DeviceInfo->Port;\r
Target8[1] = (UINT8)DeviceInfo->PortMultiplier;\r
goto Exit;\r
}\r
\r
DevicePathNode->Sata.HBAPortNumber = Port;\r
- DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplier;\r
+ //\r
+ // For CD-ROM working in the AHCI mode, only 8 bits are used to record\r
+ // the PortMultiplier information. If the CD-ROM is directly attached\r
+ // on a SATA port, the PortMultiplier should be translated from 0xFF\r
+ // to 0xFFFF according to the UEFI spec.\r
+ //\r
+ DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplier == 0xFF ? 0xFFFF : PortMultiplier;\r
DevicePathNode->Sata.Lun = (UINT16) Lun;\r
}\r
\r
if ((DeviceInfo->Type == EfiIdeCdrom) &&\r
((Target8[0] < DeviceInfo->Port) ||\r
((Target8[0] == DeviceInfo->Port) &&\r
- (Target8[1] < DeviceInfo->PortMultiplier)))) {\r
+ (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {\r
Target8[0] = (UINT8)DeviceInfo->Port;\r
Target8[1] = (UINT8)DeviceInfo->PortMultiplier;\r
goto Exit;\r