blob: 52a1275248f16780caba624e0e49ee54a66366aa [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
31ReturnCode Request::open(const std::string& path,
32 int mode)
33{
34 if (mode == O_RDWR &&
35 partition->data.user.data[1] & PARTITION_READONLY)
36 {
37 MSG_ERR("Can't open the RO partition for write");
38 return ReturnCode::PARTITION_READ_ONLY;
39 }
40
41 fs::path partitionFilePath = path;
42
43 if (!fs::exists(partitionFilePath))
44 {
45 return ReturnCode::FILE_NOT_FOUND;
46 }
47
48 auto descriptor = ::open(partitionFilePath.c_str(), mode);
49 if (descriptor < 0)
50 {
51 return ReturnCode::FILE_OPEN_FAILURE;
52 }
53
54 fd.set(descriptor);
55 descriptor = -1;
56
57 return ReturnCode::SUCCESS;
58}
59
60std::string Request::getPartitionFilePath(struct mbox_context* context,
61 uint32_t offset)
62{
63 partition = vpnor_get_partition(context, offset);
64 if (!partition)
65 {
66 MSG_ERR("Couldn't get the partition info for offset[0x%.8x]",offset);
Marri Devender Rao08b0a892017-11-08 03:38:27 -060067 log<level::ERR>("Request::getPartitionFilePath error in call to "
68 "vpnor_get_partition",
69 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +053070 elog<InternalFailure>();
71 }
72
73 fs::path partitionFilePath;
74
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050075 // Check if partition exists in patch location
76 partitionFilePath = context->paths.patch_loc;
77 partitionFilePath /= partition->data.name;
78 if (fs::is_regular_file(partitionFilePath))
79 {
80 return partitionFilePath.string();
81 }
82
Ratan Guptac0ef9872017-06-06 14:31:37 +053083 switch (partition->data.user.data[1] &
84 (PARTITION_PRESERVED | PARTITION_READONLY))
85 {
86 case PARTITION_PRESERVED:
87 partitionFilePath = context->paths.prsv_loc;
88 break;
89
90 case PARTITION_READONLY:
91 partitionFilePath = context->paths.ro_loc;
92 break;
93
94 default:
95 partitionFilePath = context->paths.rw_loc;
96 }
97 partitionFilePath /= partition->data.name;
98 return partitionFilePath.string();
99}
100
101const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
102 uint32_t offset)
103{
104 std::string path = getPartitionFilePath(context, offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530105 ReturnCode rc = Request::open(path, O_RDONLY);
106 if (rc == ReturnCode::SUCCESS)
107 {
108 return partition;
109 }
110 // not interested in any other error except FILE_NOT_FOUND
111 if (rc != ReturnCode::FILE_NOT_FOUND)
112 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600113 log<level::ERR>("RORequest::getPartitionInfo error in opening "
114 "partition file",
115 entry("RC=%d", rc),
116 entry("FILE_NAME=%s", path.c_str()),
117 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530118 elog<InternalFailure>();
119 }
120
121 // if the offset lies in read only partition then throw error.
122 if (partition->data.user.data[1] & PARTITION_READONLY)
123 {
124 MSG_ERR("Can't open the partition file");
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600125 log<level::ERR>("RORequest::getPartitionInfo error offset is "
126 "in read only partition",
127 entry("FILE_NAME=%s", path.c_str()),
128 entry("OFFSET=%d", offset),
129 entry("USER_DATA=%s", partition->data.user.data[1]));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530130 elog<InternalFailure>();
131 }
132
Ratan Guptac0ef9872017-06-06 14:31:37 +0530133 // we don't get the file in the respective partition(RW/PSRV)
134 // try to open it from RO location.
135
136 fs::path partitionFilePath = context->paths.ro_loc;
137 partitionFilePath /= partition->data.name;
138
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500139 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530140 if (rc != ReturnCode::SUCCESS)
141 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600142 log<level::ERR>("RORequest::getPartitionInfo error in opening "
143 "partition file from read only location",
144 entry("RC=%d", rc),
145 entry("FILE_NAME=%s", partitionFilePath.c_str()));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530146 elog<InternalFailure>();
147 }
148
149 return partition;
150
151}
152
153const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
154 uint32_t offset)
155{
156 std::string path = getPartitionFilePath(context, offset);
157
158 ReturnCode rc = Request::open(path, O_RDWR);
159 if (rc == ReturnCode::SUCCESS)
160 {
161 return partition;
162 }
163 // not interested in any other error except FILE_NOT_FOUND
164 if (rc != ReturnCode::FILE_NOT_FOUND)
165 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600166 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
167 "partition file",
168 entry("RC=%d", rc),
169 entry("FILE_NAME=%s", path.c_str()),
170 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530171 elog<InternalFailure>();
172 }
173
174 // if the file is not available in the respective(RW/PSRV) partition
175 // then copy the file from RO to the respective(RW/PSRV) partition
176 // and open it for writing.
177
178 fs::path fromPath = context->paths.ro_loc;
179 fromPath /= partition->data.name;
180 if (!fs::exists(fromPath))
181 {
182 MSG_ERR("Couldn't find the file[%s]",fromPath.c_str());
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600183 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
184 "partition file from read only location",
185 entry("FILE_NAME=%s", fromPath.c_str()),
186 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530187 elog<InternalFailure>();
188 }
189 //copy the file from ro to respective partition
190 fs::path toPath = context->paths.rw_loc;
191
192 if (partition->data.user.data[1] & PARTITION_PRESERVED)
193 {
194 toPath = context->paths.prsv_loc;
195 }
196
197 toPath /= partition->data.name;
198
199 MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n",
200 toPath.c_str());
201
202 if (fs::copy_file(fromPath, toPath))
203 {
204 MSG_DBG("File copied from[%s] to [%s]\n",
205 fromPath.c_str(), toPath.c_str());
206 }
207
208 rc = Request::open(toPath.c_str(), O_RDWR);
209
210 if (rc != ReturnCode::SUCCESS)
211 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600212 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
213 "partition file from read write location",
214 entry("RC=%d", rc),
215 entry("FILE_NAME=%s", toPath.c_str()));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530216 elog<InternalFailure>();
217 }
218
219 return partition;
220}
221
222}// namespace virtual_pnor
223}// namespace openpower