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