blob: f8c5fa3f450f8163d8a94c3a75aecebe8e14ce5c [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 {
35 MSG_ERR("Can't open the RO partition for write");
36 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 Jefferyf34db312018-03-09 15:27:03 +103064 MSG_ERR("Couldn't get the partition info for offset[0x%.8x]", offset);
Marri Devender Rao08b0a892017-11-08 03:38:27 -060065 log<level::ERR>("Request::getPartitionFilePath error in call to "
Andrew Jefferyf34db312018-03-09 15:27:03 +103066 "vpnor_get_partition",
67 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +053068 elog<InternalFailure>();
69 }
70
71 fs::path partitionFilePath;
72
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050073 // Check if partition exists in patch location
74 partitionFilePath = context->paths.patch_loc;
75 partitionFilePath /= partition->data.name;
76 if (fs::is_regular_file(partitionFilePath))
77 {
78 return partitionFilePath.string();
79 }
80
Ratan Guptac0ef9872017-06-06 14:31:37 +053081 switch (partition->data.user.data[1] &
82 (PARTITION_PRESERVED | PARTITION_READONLY))
83 {
84 case PARTITION_PRESERVED:
85 partitionFilePath = context->paths.prsv_loc;
86 break;
87
88 case PARTITION_READONLY:
89 partitionFilePath = context->paths.ro_loc;
90 break;
91
92 default:
93 partitionFilePath = context->paths.rw_loc;
94 }
95 partitionFilePath /= partition->data.name;
96 return partitionFilePath.string();
97}
98
99const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
100 uint32_t offset)
101{
102 std::string path = getPartitionFilePath(context, offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530103 ReturnCode rc = Request::open(path, O_RDONLY);
104 if (rc == ReturnCode::SUCCESS)
105 {
106 return partition;
107 }
108 // not interested in any other error except FILE_NOT_FOUND
109 if (rc != ReturnCode::FILE_NOT_FOUND)
110 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600111 log<level::ERR>("RORequest::getPartitionInfo error in opening "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030112 "partition file",
113 entry("RC=%d", rc), entry("FILE_NAME=%s", path.c_str()),
114 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530115 elog<InternalFailure>();
116 }
117
118 // if the offset lies in read only partition then throw error.
119 if (partition->data.user.data[1] & PARTITION_READONLY)
120 {
121 MSG_ERR("Can't open the partition file");
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600122 log<level::ERR>("RORequest::getPartitionInfo error offset is "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030123 "in read only partition",
124 entry("FILE_NAME=%s", path.c_str()),
125 entry("OFFSET=%d", offset),
126 entry("USER_DATA=%s", partition->data.user.data[1]));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530127 elog<InternalFailure>();
128 }
129
Ratan Guptac0ef9872017-06-06 14:31:37 +0530130 // we don't get the file in the respective partition(RW/PSRV)
131 // try to open it from RO location.
132
133 fs::path partitionFilePath = context->paths.ro_loc;
134 partitionFilePath /= partition->data.name;
135
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500136 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530137 if (rc != ReturnCode::SUCCESS)
138 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600139 log<level::ERR>("RORequest::getPartitionInfo error in opening "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030140 "partition file from read only location",
141 entry("RC=%d", rc),
142 entry("FILE_NAME=%s", partitionFilePath.c_str()));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530143 elog<InternalFailure>();
144 }
145
146 return partition;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530147}
148
149const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
150 uint32_t offset)
151{
152 std::string path = getPartitionFilePath(context, offset);
153
154 ReturnCode rc = Request::open(path, O_RDWR);
155 if (rc == ReturnCode::SUCCESS)
156 {
157 return partition;
158 }
159 // not interested in any other error except FILE_NOT_FOUND
160 if (rc != ReturnCode::FILE_NOT_FOUND)
161 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600162 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030163 "partition file",
164 entry("RC=%d", rc), entry("FILE_NAME=%s", path.c_str()),
165 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530166 elog<InternalFailure>();
167 }
168
169 // if the file is not available in the respective(RW/PSRV) partition
170 // then copy the file from RO to the respective(RW/PSRV) partition
171 // and open it for writing.
172
173 fs::path fromPath = context->paths.ro_loc;
174 fromPath /= partition->data.name;
175 if (!fs::exists(fromPath))
176 {
Andrew Jefferyf34db312018-03-09 15:27:03 +1030177 MSG_ERR("Couldn't find the file[%s]", fromPath.c_str());
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600178 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030179 "partition file from read only location",
180 entry("FILE_NAME=%s", fromPath.c_str()),
181 entry("OFFSET=%d", offset));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530182 elog<InternalFailure>();
183 }
Andrew Jefferyf34db312018-03-09 15:27:03 +1030184 // copy the file from ro to respective partition
Ratan Guptac0ef9872017-06-06 14:31:37 +0530185 fs::path toPath = context->paths.rw_loc;
186
187 if (partition->data.user.data[1] & PARTITION_PRESERVED)
188 {
189 toPath = context->paths.prsv_loc;
190 }
191
192 toPath /= partition->data.name;
193
194 MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n",
195 toPath.c_str());
196
197 if (fs::copy_file(fromPath, toPath))
198 {
Andrew Jefferyf34db312018-03-09 15:27:03 +1030199 MSG_DBG("File copied from[%s] to [%s]\n", fromPath.c_str(),
200 toPath.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530201 }
202
Andrew Jefferyf34db312018-03-09 15:27:03 +1030203 rc = Request::open(toPath.c_str(), O_RDWR);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530204
205 if (rc != ReturnCode::SUCCESS)
206 {
Marri Devender Rao08b0a892017-11-08 03:38:27 -0600207 log<level::ERR>("RWRequest::getPartitionInfo error in opening "
Andrew Jefferyf34db312018-03-09 15:27:03 +1030208 "partition file from read write location",
209 entry("RC=%d", rc),
210 entry("FILE_NAME=%s", toPath.c_str()));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530211 elog<InternalFailure>();
212 }
213
214 return partition;
215}
216
Andrew Jefferyf34db312018-03-09 15:27:03 +1030217} // namespace virtual_pnor
218} // namespace openpower