xref: /openbmc/estoraged/src/erase/pattern.cpp (revision 0c2808f0)
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