xref: /openbmc/estoraged/src/erase/pattern.cpp (revision d4554f2a17686e36a77ac4a3619efd685fcbb15c)
17f2ab643SJohn Edward Broadbent #include "pattern.hpp"
27f2ab643SJohn Edward Broadbent 
37f2ab643SJohn Edward Broadbent #include "erase.hpp"
47f2ab643SJohn Edward Broadbent 
57f2ab643SJohn Edward Broadbent #include <unistd.h>
67f2ab643SJohn Edward Broadbent 
77f2ab643SJohn Edward Broadbent #include <phosphor-logging/lg2.hpp>
87f2ab643SJohn Edward Broadbent #include <stdplus/fd/create.hpp>
97f2ab643SJohn Edward Broadbent #include <stdplus/fd/managed.hpp>
107f2ab643SJohn Edward Broadbent #include <xyz/openbmc_project/Common/error.hpp>
117f2ab643SJohn Edward Broadbent 
127f2ab643SJohn Edward Broadbent #include <array>
13d6071fc2SJohn Edward Broadbent #include <chrono>
147f2ab643SJohn Edward Broadbent #include <iostream>
157f2ab643SJohn Edward Broadbent #include <random>
167f2ab643SJohn Edward Broadbent #include <span>
177f2ab643SJohn Edward Broadbent #include <string>
18d6071fc2SJohn Edward Broadbent #include <thread>
197f2ab643SJohn Edward Broadbent 
20d3bfa7bbSJohn Edward Broadbent namespace estoraged
21d3bfa7bbSJohn Edward Broadbent {
22d3bfa7bbSJohn Edward Broadbent 
237f2ab643SJohn Edward Broadbent using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24d6071fc2SJohn Edward Broadbent using stdplus::fd::Fd;
257f2ab643SJohn Edward Broadbent 
writePattern(const uint64_t driveSize,Fd & fd)26d6071fc2SJohn Edward Broadbent void Pattern::writePattern(const uint64_t driveSize, Fd& fd)
277f2ab643SJohn Edward Broadbent {
28*d4554f2aSManojkiran Eda     // static seed defines a fixed prng sequence so it can be verified later,
297f2ab643SJohn Edward Broadbent     // and validated for entropy
307f2ab643SJohn Edward Broadbent     uint64_t currentIndex = 0;
3182897c35SEd Tanous 
3282897c35SEd Tanous     // random number generator seeded with a constant value will
3382897c35SEd Tanous     // generate a predictable sequence of values NOLINTNEXTLINE
347f2ab643SJohn Edward Broadbent     std::minstd_rand0 generator(seed);
3582897c35SEd Tanous     std::array<std::byte, blockSize> randArr{};
3669786761SJohn Edward Broadbent 
377f2ab643SJohn Edward Broadbent     while (currentIndex < driveSize)
387f2ab643SJohn Edward Broadbent     {
397f2ab643SJohn Edward Broadbent         // generate a 4k block of prng
407f2ab643SJohn Edward Broadbent         std::array<uint32_t, blockSizeUsing32>* randArrFill =
417f2ab643SJohn Edward Broadbent             reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>(&randArr);
427f2ab643SJohn Edward Broadbent         for (uint32_t i = 0; i < blockSizeUsing32; i++)
437f2ab643SJohn Edward Broadbent         {
447f2ab643SJohn Edward Broadbent             (*randArrFill)[i] = generator();
457f2ab643SJohn Edward Broadbent         }
467f2ab643SJohn Edward Broadbent         // if we can write all 4k bytes do that, else write the remainder
477f2ab643SJohn Edward Broadbent         size_t writeSize = currentIndex + blockSize < driveSize
487f2ab643SJohn Edward Broadbent                                ? blockSize
497f2ab643SJohn Edward Broadbent                                : driveSize - currentIndex;
50d6071fc2SJohn Edward Broadbent         size_t written = 0;
51d6071fc2SJohn Edward Broadbent         size_t retry = 0;
52d6071fc2SJohn Edward Broadbent         while (written < writeSize)
537f2ab643SJohn Edward Broadbent         {
54d6071fc2SJohn Edward Broadbent             written += fd.write({randArr.data() + written, writeSize - written})
55d6071fc2SJohn Edward Broadbent                            .size();
56d6071fc2SJohn Edward Broadbent             if (written == writeSize)
57d6071fc2SJohn Edward Broadbent             {
58d6071fc2SJohn Edward Broadbent                 break;
59d6071fc2SJohn Edward Broadbent             }
60d6071fc2SJohn Edward Broadbent             if (written > writeSize)
61d6071fc2SJohn Edward Broadbent             {
627f2ab643SJohn Edward Broadbent                 throw InternalFailure();
637f2ab643SJohn Edward Broadbent             }
64d6071fc2SJohn Edward Broadbent             retry++;
65d6071fc2SJohn Edward Broadbent             if (retry > maxRetry)
66d6071fc2SJohn Edward Broadbent             {
67d6071fc2SJohn Edward Broadbent                 lg2::error("Unable to do full write", "REDFISH_MESSAGE_ID",
68d6071fc2SJohn Edward Broadbent                            std::string("eStorageD.1.0.EraseFailure"));
69d6071fc2SJohn Edward Broadbent                 throw InternalFailure();
70d6071fc2SJohn Edward Broadbent             }
71d6071fc2SJohn Edward Broadbent             std::this_thread::sleep_for(delay);
72d6071fc2SJohn Edward Broadbent         }
737f2ab643SJohn Edward Broadbent         currentIndex = currentIndex + writeSize;
747f2ab643SJohn Edward Broadbent     }
757f2ab643SJohn Edward Broadbent }
767f2ab643SJohn Edward Broadbent 
verifyPattern(const uint64_t driveSize,Fd & fd)77d6071fc2SJohn Edward Broadbent void Pattern::verifyPattern(const uint64_t driveSize, Fd& fd)
787f2ab643SJohn Edward Broadbent {
797f2ab643SJohn Edward Broadbent     uint64_t currentIndex = 0;
8082897c35SEd Tanous     // random number generator seeded with a constant value will
8182897c35SEd Tanous     // generate a predictable sequence of values NOLINTNEXTLINE
827f2ab643SJohn Edward Broadbent     std::minstd_rand0 generator(seed);
8382897c35SEd Tanous     std::array<std::byte, blockSize> randArr{};
8482897c35SEd Tanous     std::array<std::byte, blockSize> readArr{};
8569786761SJohn Edward Broadbent 
867f2ab643SJohn Edward Broadbent     while (currentIndex < driveSize)
877f2ab643SJohn Edward Broadbent     {
887f2ab643SJohn Edward Broadbent         size_t readSize = currentIndex + blockSize < driveSize
897f2ab643SJohn Edward Broadbent                               ? blockSize
907f2ab643SJohn Edward Broadbent                               : driveSize - currentIndex;
917f2ab643SJohn Edward Broadbent         try
927f2ab643SJohn Edward Broadbent         {
937f2ab643SJohn Edward Broadbent             std::array<uint32_t, blockSizeUsing32>* randArrFill =
947f2ab643SJohn Edward Broadbent                 reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>(
957f2ab643SJohn Edward Broadbent                     &randArr);
967f2ab643SJohn Edward Broadbent             for (uint32_t i = 0; i < blockSizeUsing32; i++)
977f2ab643SJohn Edward Broadbent             {
987f2ab643SJohn Edward Broadbent                 (*randArrFill)[i] = generator();
997f2ab643SJohn Edward Broadbent             }
100d6071fc2SJohn Edward Broadbent             size_t read = 0;
101d6071fc2SJohn Edward Broadbent             size_t retry = 0;
102d6071fc2SJohn Edward Broadbent             while (read < readSize)
103d6071fc2SJohn Edward Broadbent             {
104d6071fc2SJohn Edward Broadbent                 read +=
105d6071fc2SJohn Edward Broadbent                     fd.read({readArr.data() + read, readSize - read}).size();
106d6071fc2SJohn Edward Broadbent                 if (read == readSize)
107d6071fc2SJohn Edward Broadbent                 {
108d6071fc2SJohn Edward Broadbent                     break;
109d6071fc2SJohn Edward Broadbent                 }
110d6071fc2SJohn Edward Broadbent                 if (read > readSize)
111d6071fc2SJohn Edward Broadbent                 {
112d6071fc2SJohn Edward Broadbent                     throw InternalFailure();
113d6071fc2SJohn Edward Broadbent                 }
114d6071fc2SJohn Edward Broadbent                 retry++;
115d6071fc2SJohn Edward Broadbent                 if (retry > maxRetry)
116d6071fc2SJohn Edward Broadbent                 {
117d6071fc2SJohn Edward Broadbent                     lg2::error("Unable to do full read", "REDFISH_MESSAGE_ID",
118d6071fc2SJohn Edward Broadbent                                std::string("eStorageD.1.0.EraseFailure"));
119d6071fc2SJohn Edward Broadbent                     throw InternalFailure();
120d6071fc2SJohn Edward Broadbent                 }
121d6071fc2SJohn Edward Broadbent                 std::this_thread::sleep_for(delay);
122d6071fc2SJohn Edward Broadbent             }
1237f2ab643SJohn Edward Broadbent         }
1247f2ab643SJohn Edward Broadbent         catch (...)
1257f2ab643SJohn Edward Broadbent         {
1267f2ab643SJohn Edward Broadbent             lg2::error("Estoraged erase pattern unable to read",
1277f2ab643SJohn Edward Broadbent                        "REDFISH_MESSAGE_ID",
128d6071fc2SJohn Edward Broadbent                        std::string("eStorageD.1.0.EraseFailure"));
1297f2ab643SJohn Edward Broadbent             throw InternalFailure();
1307f2ab643SJohn Edward Broadbent         }
1317f2ab643SJohn Edward Broadbent 
1327f2ab643SJohn Edward Broadbent         if (!std::equal(randArr.begin(), randArr.begin() + readSize,
1337f2ab643SJohn Edward Broadbent                         readArr.begin(), readArr.begin() + readSize))
1347f2ab643SJohn Edward Broadbent         {
1357f2ab643SJohn Edward Broadbent             lg2::error("Estoraged erase pattern does not match",
1367f2ab643SJohn Edward Broadbent                        "REDFISH_MESSAGE_ID",
1377f2ab643SJohn Edward Broadbent                        std::string("eStorageD.1.0.EraseFailure"));
1387f2ab643SJohn Edward Broadbent             throw InternalFailure();
1397f2ab643SJohn Edward Broadbent         }
1407f2ab643SJohn Edward Broadbent         currentIndex = currentIndex + readSize;
1417f2ab643SJohn Edward Broadbent     }
1427f2ab643SJohn Edward Broadbent }
143d3bfa7bbSJohn Edward Broadbent 
144d3bfa7bbSJohn Edward Broadbent } // namespace estoraged
145