blob: 9fee49681ecb7db32c401ccfed3779f4fbb87e4d [file] [log] [blame]
Ratan Guptac0ef9872017-06-06 14:31:37 +05301#include "pnor_partition.hpp"
2#include "config.h"
3#include "mboxd_flash.h"
4#include "mboxd_pnor_partition_table.h"
5#include "xyz/openbmc_project/Common/error.hpp"
6#include <phosphor-logging/log.hpp>
7#include <phosphor-logging/elog-errors.hpp>
8
9#include <stdint.h>
10#include <stdlib.h>
11#include <syslog.h>
12#include <sys/ioctl.h>
13#include <sys/mman.h>
14
15#include "common.h"
16
17#include <string>
18#include <exception>
19#include <stdexcept>
20#include <iostream>
21
22namespace openpower
23{
24namespace virtual_pnor
25{
26
27using namespace phosphor::logging;
28using namespace sdbusplus::xyz::openbmc_project::Common::Error;
29using namespace std::string_literals;
30
Andrew Jefferyf34db312018-03-09 15:27:03 +103031ReturnCode Request::open(const std::string& path, int mode)
Ratan Guptac0ef9872017-06-06 14:31:37 +053032{
Andrew Jefferyf34db312018-03-09 15:27:03 +103033 if (mode == O_RDWR && partition->data.user.data[1] & PARTITION_READONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053034 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103035 MSG_ERR("Can't open RO partition '%s' for write\n", path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +053036 return ReturnCode::PARTITION_READ_ONLY;
37 }
38
39 fs::path partitionFilePath = path;
40
41 if (!fs::exists(partitionFilePath))
42 {
43 return ReturnCode::FILE_NOT_FOUND;
44 }
45
46 auto descriptor = ::open(partitionFilePath.c_str(), mode);
47 if (descriptor < 0)
48 {
49 return ReturnCode::FILE_OPEN_FAILURE;
50 }
51
52 fd.set(descriptor);
53 descriptor = -1;
54
55 return ReturnCode::SUCCESS;
56}
57
58std::string Request::getPartitionFilePath(struct mbox_context* context,
59 uint32_t offset)
60{
61 partition = vpnor_get_partition(context, offset);
62 if (!partition)
63 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103064 MSG_ERR("Couldn't get the partition info for offset 0x%" PRIx32 "\n",
65 offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +053066 elog<InternalFailure>();
67 }
68
69 fs::path partitionFilePath;
70
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050071 // Check if partition exists in patch location
72 partitionFilePath = context->paths.patch_loc;
73 partitionFilePath /= partition->data.name;
74 if (fs::is_regular_file(partitionFilePath))
75 {
76 return partitionFilePath.string();
77 }
78
Ratan Guptac0ef9872017-06-06 14:31:37 +053079 switch (partition->data.user.data[1] &
80 (PARTITION_PRESERVED | PARTITION_READONLY))
81 {
82 case PARTITION_PRESERVED:
83 partitionFilePath = context->paths.prsv_loc;
84 break;
85
86 case PARTITION_READONLY:
87 partitionFilePath = context->paths.ro_loc;
88 break;
89
90 default:
91 partitionFilePath = context->paths.rw_loc;
92 }
93 partitionFilePath /= partition->data.name;
94 return partitionFilePath.string();
95}
96
97const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
98 uint32_t offset)
99{
100 std::string path = getPartitionFilePath(context, offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530101 ReturnCode rc = Request::open(path, O_RDONLY);
102 if (rc == ReturnCode::SUCCESS)
103 {
104 return partition;
105 }
106 // not interested in any other error except FILE_NOT_FOUND
107 if (rc != ReturnCode::FILE_NOT_FOUND)
108 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030109 MSG_ERR(
110 "RORequest: Error opening partition file '%s' (offset 0x%" PRIx32
111 "): %u\n",
112 path.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530113 elog<InternalFailure>();
114 }
115
116 // if the offset lies in read only partition then throw error.
117 if (partition->data.user.data[1] & PARTITION_READONLY)
118 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030119 MSG_ERR("RORequest: Requested offset 0x%" PRIx32
120 " is in a read-only partition (%s)\n",
121 offset, path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530122 elog<InternalFailure>();
123 }
124
Ratan Guptac0ef9872017-06-06 14:31:37 +0530125 // we don't get the file in the respective partition(RW/PSRV)
126 // try to open it from RO location.
127
128 fs::path partitionFilePath = context->paths.ro_loc;
129 partitionFilePath /= partition->data.name;
130
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500131 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530132 if (rc != ReturnCode::SUCCESS)
133 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030134 MSG_ERR("RORequest: Failed to open partition file '%s' at RO fallback "
135 "(offset 0x%" PRIx32 "): %u\n",
136 partitionFilePath.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530137 elog<InternalFailure>();
138 }
139
140 return partition;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530141}
142
143const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
144 uint32_t offset)
145{
146 std::string path = getPartitionFilePath(context, offset);
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030147 std::error_code ec;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530148
149 ReturnCode rc = Request::open(path, O_RDWR);
150 if (rc == ReturnCode::SUCCESS)
151 {
152 return partition;
153 }
154 // not interested in any other error except FILE_NOT_FOUND
155 if (rc != ReturnCode::FILE_NOT_FOUND)
156 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030157 MSG_ERR(
158 "RWRequest: Error opening partition file '%s' (offset 0x%" PRIx32
159 "): %d\n",
160 path.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530161 elog<InternalFailure>();
162 }
163
164 // if the file is not available in the respective(RW/PSRV) partition
165 // then copy the file from RO to the respective(RW/PSRV) partition
166 // and open it for writing.
167
168 fs::path fromPath = context->paths.ro_loc;
169 fromPath /= partition->data.name;
170 if (!fs::exists(fromPath))
171 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030172 MSG_ERR("RWRequest: Partition '%s' for offset 0x%" PRIx32
173 " not found in RO directory '%s'\n",
174 partition->data.name, offset, context->paths.ro_loc);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530175 elog<InternalFailure>();
176 }
Andrew Jefferyf34db312018-03-09 15:27:03 +1030177 // copy the file from ro to respective partition
Ratan Guptac0ef9872017-06-06 14:31:37 +0530178 fs::path toPath = context->paths.rw_loc;
179
180 if (partition->data.user.data[1] & PARTITION_PRESERVED)
181 {
182 toPath = context->paths.prsv_loc;
183 }
184
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030185 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
186 partition->data.name, toPath.c_str(), fromPath.c_str());
187
Ratan Guptac0ef9872017-06-06 14:31:37 +0530188 toPath /= partition->data.name;
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030189 if (!fs::copy_file(fromPath, toPath, ec))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530190 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030191 MSG_ERR("RWRequest: Failed to copy file from '%s' to '%s': %d\n",
192 fromPath.c_str(), toPath.c_str(), ec.value());
193 elog<InternalFailure>();
Ratan Guptac0ef9872017-06-06 14:31:37 +0530194 }
195
Andrew Jefferyf34db312018-03-09 15:27:03 +1030196 rc = Request::open(toPath.c_str(), O_RDWR);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530197
198 if (rc != ReturnCode::SUCCESS)
199 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030200 MSG_ERR("RWRequest: Failed to open file at '%s': %d\n", toPath.c_str(),
201 static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530202 elog<InternalFailure>();
203 }
204
205 return partition;
206}
207
Andrew Jefferyf34db312018-03-09 15:27:03 +1030208} // namespace virtual_pnor
209} // namespace openpower