1 #include "pattern.hpp" 2 3 #include "erase.hpp" 4 5 #include <unistd.h> 6 7 #include <phosphor-logging/lg2.hpp> 8 #include <stdplus/fd/create.hpp> 9 #include <stdplus/fd/managed.hpp> 10 #include <xyz/openbmc_project/Common/error.hpp> 11 12 #include <array> 13 #include <iostream> 14 #include <random> 15 #include <span> 16 #include <string> 17 18 namespace estoraged 19 { 20 21 constexpr uint32_t seed = 0x6a656272; 22 constexpr size_t blockSize = 4096; 23 constexpr size_t blockSizeUsing32 = blockSize / sizeof(uint32_t); 24 25 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 26 using stdplus::fd::ManagedFd; 27 28 void Pattern::writePattern(const uint64_t driveSize) 29 { 30 // static seed defines a fixed prng sequnce so it can be verified later, 31 // and validated for entropy 32 uint64_t currentIndex = 0; 33 std::minstd_rand0 generator(seed); 34 std::array<std::byte, blockSize> randArr; 35 36 ManagedFd fd = 37 stdplus::fd::open(devPath, stdplus::fd::OpenAccess::WriteOnly); 38 39 while (currentIndex < driveSize) 40 { 41 // generate a 4k block of prng 42 std::array<uint32_t, blockSizeUsing32>* randArrFill = 43 reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>(&randArr); 44 for (uint32_t i = 0; i < blockSizeUsing32; i++) 45 { 46 (*randArrFill)[i] = generator(); 47 } 48 // if we can write all 4k bytes do that, else write the remainder 49 size_t writeSize = currentIndex + blockSize < driveSize 50 ? blockSize 51 : driveSize - currentIndex; 52 if (fd.write({randArr.data(), writeSize}).size() != writeSize) 53 { 54 lg2::error("Estoraged erase pattern unable to write sizeof(long)", 55 "REDFISH_MESSAGE_ID", 56 std::string("eStorageD.1.0.EraseFailure"), 57 "REDFISH_MESSAGE_ARGS", std::to_string(fd.get())); 58 throw InternalFailure(); 59 } 60 currentIndex = currentIndex + writeSize; 61 } 62 } 63 64 void Pattern::verifyPattern(const uint64_t driveSize) 65 { 66 67 uint64_t currentIndex = 0; 68 std::minstd_rand0 generator(seed); 69 std::array<std::byte, blockSize> randArr; 70 std::array<std::byte, blockSize> readArr; 71 72 ManagedFd fd = 73 stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly); 74 75 while (currentIndex < driveSize) 76 { 77 size_t readSize = currentIndex + blockSize < driveSize 78 ? blockSize 79 : driveSize - currentIndex; 80 try 81 { 82 std::array<uint32_t, blockSizeUsing32>* randArrFill = 83 reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>( 84 &randArr); 85 for (uint32_t i = 0; i < blockSizeUsing32; i++) 86 { 87 (*randArrFill)[i] = generator(); 88 } 89 fd.read({readArr.data(), readSize}); 90 } 91 catch (...) 92 { 93 lg2::error("Estoraged erase pattern unable to read", 94 "REDFISH_MESSAGE_ID", 95 std::string("eStorageD.1.0.EraseFailure"), 96 "REDFISH_MESSAGE_ARGS", std::to_string(fd.get())); 97 throw InternalFailure(); 98 } 99 100 if (!std::equal(randArr.begin(), randArr.begin() + readSize, 101 readArr.begin(), readArr.begin() + readSize)) 102 { 103 lg2::error("Estoraged erase pattern does not match", 104 "REDFISH_MESSAGE_ID", 105 std::string("eStorageD.1.0.EraseFailure")); 106 throw InternalFailure(); 107 } 108 currentIndex = currentIndex + readSize; 109 } 110 } 111 112 } // namespace estoraged 113