1 #include "sanitize.hpp" 2 3 #include "estoraged_conf.hpp" 4 5 #include <linux/mmc/ioctl.h> 6 #include <sys/ioctl.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 #include <stdplus/fd/create.hpp> 10 #include <stdplus/fd/managed.hpp> 11 #include <stdplus/handle/managed.hpp> 12 #include <xyz/openbmc_project/Common/error.hpp> 13 14 #include <array> 15 #include <cstddef> 16 #include <span> 17 #include <string> 18 #include <string_view> 19 20 namespace 21 { 22 23 constexpr uint32_t mmcSwitch = 6; 24 constexpr uint32_t mmcSwitchModeWriteByte = 0x03; 25 constexpr uint32_t extCsdSanitizeStart = 165; 26 constexpr uint32_t extCsdCmdSetNormal = (1 << 0); 27 28 constexpr uint32_t mmcRspPresent = (1 << 0); 29 constexpr uint32_t mmcRspCrc = (1 << 2); 30 constexpr uint32_t mmcRspBusy = (1 << 3); 31 constexpr uint32_t mmcRspOpcode = (1 << 4); 32 33 constexpr uint32_t mmcCmdAc = (0 << 5); 34 35 constexpr uint32_t mmcRspSpiS1 = (1 << 7); 36 constexpr uint32_t mmcRspSpiBusy = (1 << 10); 37 38 constexpr uint32_t mmcRspSpiR1 = (mmcRspSpiS1); 39 constexpr uint32_t mmcRspSpiR1B = (mmcRspSpiS1 | mmcRspSpiBusy); 40 41 constexpr uint32_t mmcRspR1B = 42 (mmcRspPresent | mmcRspCrc | mmcRspOpcode | mmcRspBusy); 43 44 constexpr uint32_t mmcRspR1 = (mmcRspPresent | mmcRspCrc | mmcRspOpcode); 45 46 constexpr uint32_t mmcEraseGroupStart = 35; 47 constexpr uint32_t mmcEraseGroupEnd = 36; 48 constexpr uint32_t mmcErase = 38; 49 } // namespace 50 51 namespace estoraged 52 { 53 54 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 55 using stdplus::fd::ManagedFd; 56 57 void Sanitize::doSanitize(uint64_t driveSize) 58 { 59 try 60 { 61 emmcErase(driveSize); 62 emmcSanitize(); 63 } 64 catch (...) 65 { 66 lg2::error("eStorageD erase sanitize failure", "REDFISH_MESSAGE_ID", 67 std::string("eStorageD.1.0.EraseFailure")); 68 throw InternalFailure(); 69 } 70 lg2::info("eStorageD successfully erase sanitize", "REDFISH_MESSAGE_ID", 71 std::string("eStorageD.1.0.EraseSuccessful")); 72 } 73 74 void Sanitize::emmcErase(uint64_t driveSize) 75 { 76 77 uint64_t sectorSize = 0x200; // default value see eMMC spec 6.6.34. 78 // NOTE: 0x200 is only valid for eMMC greater 79 // then 2 GB 80 struct mmc_io_multi_cmd_erase eraseCmd = {}; 81 82 eraseCmd.num_of_cmds = 3; 83 eraseCmd.cmds[0].opcode = mmcEraseGroupStart; 84 eraseCmd.cmds[0].arg = 0; 85 eraseCmd.cmds[0].flags = mmcRspSpiR1 | mmcRspR1 | mmcCmdAc; 86 eraseCmd.cmds[0].write_flag = 1; 87 88 eraseCmd.cmds[1].opcode = mmcEraseGroupEnd; 89 eraseCmd.cmds[1].arg = (driveSize / sectorSize) - 1; 90 eraseCmd.cmds[1].flags = mmcRspSpiR1 | mmcRspR1 | mmcCmdAc; 91 eraseCmd.cmds[1].write_flag = 1; 92 93 /* Send Erase Command */ 94 eraseCmd.cmds[2].opcode = mmcErase; 95 eraseCmd.cmds[2].arg = 0x00000000; 96 eraseCmd.cmds[2].cmd_timeout_ms = 0x0FFFFFFF; 97 eraseCmd.cmds[2].flags = mmcRspSpiR1B | mmcRspR1B | mmcCmdAc; 98 eraseCmd.cmds[2].write_flag = 1; 99 100 if (ioctlWrapper->doIoctlMulti(devPath, MMC_IOC_MULTI_CMD, eraseCmd) != 0) 101 { 102 throw InternalFailure(); 103 } 104 } 105 106 void Sanitize::emmcSanitize() 107 { 108 109 struct mmc_ioc_cmd idata = {}; 110 idata.write_flag = 1; 111 idata.opcode = mmcSwitch; 112 idata.arg = (mmcSwitchModeWriteByte << 24) | (extCsdSanitizeStart << 16) | 113 (1 << 8) | extCsdCmdSetNormal; 114 idata.flags = mmcRspSpiR1B | mmcRspR1B | mmcCmdAc; 115 116 // make the eMMC sanitize ioctl 117 if (ioctlWrapper->doIoctl(devPath, MMC_IOC_CMD, idata) != 0) 118 { 119 throw InternalFailure(); 120 } 121 } 122 123 int IOCTLWrapperImpl::doIoctl(std::string_view devPath, unsigned long request, 124 struct mmc_ioc_cmd data) 125 126 { 127 ManagedFd fd = stdplus::fd::open(std::string(devPath).c_str(), 128 stdplus::fd::OpenAccess::ReadOnly); 129 130 return fd.ioctl(request, static_cast<void*>(&data)); 131 } 132 133 int IOCTLWrapperImpl::doIoctlMulti(std::string_view devPath, 134 unsigned long request, 135 struct mmc_io_multi_cmd_erase data) 136 { 137 ManagedFd fd = stdplus::fd::open(std::string(devPath).c_str(), 138 stdplus::fd::OpenAccess::ReadOnly); 139 140 return fd.ioctl(request, static_cast<void*>(&data)); 141 } 142 143 } // namespace estoraged 144