+/**\r
+ Execute READ CAPACITY 16 bytes command to request information regarding\r
+ the capacity of the installed medium of the device.\r
+\r
+ This function executes READ CAPACITY 16 bytes command to get the capacity\r
+ of the USB mass storage media, including the presence, block size,\r
+ and last block number.\r
+\r
+ @param UsbMass The device to retireve disk gemotric.\r
+\r
+ @retval EFI_SUCCESS The disk geometry is successfully retrieved.\r
+ @retval EFI_NOT_READY The returned block size is zero.\r
+ @retval Other READ CAPACITY 16 bytes command execution failed.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbBootReadCapacity16 (\r
+ IN USB_MASS_DEVICE *UsbMass\r
+ )\r
+{\r
+ UINT8 CapacityCmd[16];\r
+ EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData;\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+\r
+ Media = &UsbMass->BlockIoMedia;\r
+\r
+ Media->MediaPresent = FALSE;\r
+ Media->LastBlock = 0;\r
+ Media->BlockSize = 0;\r
+\r
+ ZeroMem (CapacityCmd, sizeof (CapacityCmd));\r
+ ZeroMem (&CapacityData, sizeof (CapacityData));\r
+\r
+ CapacityCmd[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
+ CapacityCmd[1] = 0x10;\r
+ //\r
+ // Partial medium indicator, set the bytes 2 ~ 9 of the Cdb as ZERO.\r
+ //\r
+ ZeroMem ((CapacityCmd + 2), 8);\r
+\r
+ CapacityCmd[13] = sizeof (CapacityData);\r
+\r
+ Status = UsbBootExecCmdWithRetry (\r
+ UsbMass,\r
+ CapacityCmd,\r
+ (UINT8) sizeof (CapacityCmd),\r
+ EfiUsbDataIn,\r
+ &CapacityData,\r
+ sizeof (CapacityData),\r
+ USB_BOOT_GENERAL_CMD_TIMEOUT\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the information on media presence, block size, and last block number\r
+ // from READ CAPACITY data.\r
+ //\r
+ Media->MediaPresent = TRUE;\r
+ Media->LastBlock = SwapBytes64 (ReadUnaligned64 ((CONST UINT64 *) &(CapacityData.LastLba7)));\r
+\r
+ BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) &(CapacityData.BlockSize3)));\r
+\r
+ Media->LowestAlignedLba = (CapacityData.LowestAlignLogic2 << 8) |\r
+ CapacityData.LowestAlignLogic1;\r
+ Media->LogicalBlocksPerPhysicalBlock = (1 << CapacityData.LogicPerPhysical);\r
+ if (BlockSize == 0) {\r
+ //\r
+ // Get sense data\r
+ //\r
+ return UsbBootRequestSense (UsbMass);\r
+ } else {\r
+ Media->BlockSize = BlockSize;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r