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