blob: 5563661d65d46496cc208176fccfffda60cac646 [file] [log] [blame]
John Edward Broadbent7f2ab642021-11-11 21:00:38 -08001#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
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -080018namespace estoraged
19{
20
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080021constexpr uint32_t seed = 0x6a656272;
22constexpr size_t blockSize = 4096;
23constexpr size_t blockSizeUsing32 = blockSize / sizeof(uint32_t);
24
25using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
26using stdplus::fd::ManagedFd;
27
John Edward Broadbent69786762022-01-21 14:16:23 -080028void Pattern::writePattern(const uint64_t driveSize)
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080029{
30 // static seed defines a fixed prng sequnce so it can be verified later,
31 // and validated for entropy
32 uint64_t currentIndex = 0;
Ed Tanous82897c32022-02-21 14:11:59 -080033
34 // random number generator seeded with a constant value will
35 // generate a predictable sequence of values NOLINTNEXTLINE
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080036 std::minstd_rand0 generator(seed);
Ed Tanous82897c32022-02-21 14:11:59 -080037 std::array<std::byte, blockSize> randArr{};
John Edward Broadbent69786762022-01-21 14:16:23 -080038
39 ManagedFd fd =
40 stdplus::fd::open(devPath, stdplus::fd::OpenAccess::WriteOnly);
41
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080042 while (currentIndex < driveSize)
43 {
44 // generate a 4k block of prng
45 std::array<uint32_t, blockSizeUsing32>* randArrFill =
46 reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>(&randArr);
47 for (uint32_t i = 0; i < blockSizeUsing32; i++)
48 {
49 (*randArrFill)[i] = generator();
50 }
51 // if we can write all 4k bytes do that, else write the remainder
52 size_t writeSize = currentIndex + blockSize < driveSize
53 ? blockSize
54 : driveSize - currentIndex;
55 if (fd.write({randArr.data(), writeSize}).size() != writeSize)
56 {
57 lg2::error("Estoraged erase pattern unable to write sizeof(long)",
58 "REDFISH_MESSAGE_ID",
59 std::string("eStorageD.1.0.EraseFailure"),
60 "REDFISH_MESSAGE_ARGS", std::to_string(fd.get()));
61 throw InternalFailure();
62 }
63 currentIndex = currentIndex + writeSize;
64 }
65}
66
John Edward Broadbent69786762022-01-21 14:16:23 -080067void Pattern::verifyPattern(const uint64_t driveSize)
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080068{
69
70 uint64_t currentIndex = 0;
Ed Tanous82897c32022-02-21 14:11:59 -080071 // random number generator seeded with a constant value will
72 // generate a predictable sequence of values NOLINTNEXTLINE
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080073 std::minstd_rand0 generator(seed);
Ed Tanous82897c32022-02-21 14:11:59 -080074 std::array<std::byte, blockSize> randArr{};
75 std::array<std::byte, blockSize> readArr{};
John Edward Broadbent69786762022-01-21 14:16:23 -080076
77 ManagedFd fd =
78 stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly);
79
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080080 while (currentIndex < driveSize)
81 {
82 size_t readSize = currentIndex + blockSize < driveSize
83 ? blockSize
84 : driveSize - currentIndex;
85 try
86 {
87 std::array<uint32_t, blockSizeUsing32>* randArrFill =
88 reinterpret_cast<std::array<uint32_t, blockSizeUsing32>*>(
89 &randArr);
90 for (uint32_t i = 0; i < blockSizeUsing32; i++)
91 {
92 (*randArrFill)[i] = generator();
93 }
94 fd.read({readArr.data(), readSize});
95 }
96 catch (...)
97 {
98 lg2::error("Estoraged erase pattern unable to read",
99 "REDFISH_MESSAGE_ID",
100 std::string("eStorageD.1.0.EraseFailure"),
101 "REDFISH_MESSAGE_ARGS", std::to_string(fd.get()));
102 throw InternalFailure();
103 }
104
105 if (!std::equal(randArr.begin(), randArr.begin() + readSize,
106 readArr.begin(), readArr.begin() + readSize))
107 {
108 lg2::error("Estoraged erase pattern does not match",
109 "REDFISH_MESSAGE_ID",
110 std::string("eStorageD.1.0.EraseFailure"));
111 throw InternalFailure();
112 }
113 currentIndex = currentIndex + readSize;
114 }
115}
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -0800116
117} // namespace estoraged