blob: 015a9516c0fda9211d13adc5a7ff70063cd424fc [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);
67 elog<InternalFailure>();
68 }
69
70 fs::path partitionFilePath;
71
72 switch (partition->data.user.data[1] &
73 (PARTITION_PRESERVED | PARTITION_READONLY))
74 {
75 case PARTITION_PRESERVED:
76 partitionFilePath = context->paths.prsv_loc;
77 break;
78
79 case PARTITION_READONLY:
80 partitionFilePath = context->paths.ro_loc;
81 break;
82
83 default:
84 partitionFilePath = context->paths.rw_loc;
85 }
86 partitionFilePath /= partition->data.name;
87 return partitionFilePath.string();
88}
89
90const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
91 uint32_t offset)
92{
93 std::string path = getPartitionFilePath(context, offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +053094 ReturnCode rc = Request::open(path, O_RDONLY);
95 if (rc == ReturnCode::SUCCESS)
96 {
97 return partition;
98 }
99 // not interested in any other error except FILE_NOT_FOUND
100 if (rc != ReturnCode::FILE_NOT_FOUND)
101 {
102 elog<InternalFailure>();
103 }
104
105 // if the offset lies in read only partition then throw error.
106 if (partition->data.user.data[1] & PARTITION_READONLY)
107 {
108 MSG_ERR("Can't open the partition file");
109 elog<InternalFailure>();
110 }
111
112 MSG_DBG("Couldn't open the file[%s]", path.c_str());
Ratan Gupta6a98e182017-06-06 15:04:23 +0530113
Ratan Guptac0ef9872017-06-06 14:31:37 +0530114 // we don't get the file in the respective partition(RW/PSRV)
115 // try to open it from RO location.
116
117 fs::path partitionFilePath = context->paths.ro_loc;
118 partitionFilePath /= partition->data.name;
119
120 rc = Request::open(path, O_RDONLY);
121 if (rc != ReturnCode::SUCCESS)
122 {
123 elog<InternalFailure>();
124 }
125
126 return partition;
127
128}
129
130const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
131 uint32_t offset)
132{
133 std::string path = getPartitionFilePath(context, offset);
134
135 ReturnCode rc = Request::open(path, O_RDWR);
136 if (rc == ReturnCode::SUCCESS)
137 {
138 return partition;
139 }
140 // not interested in any other error except FILE_NOT_FOUND
141 if (rc != ReturnCode::FILE_NOT_FOUND)
142 {
143 elog<InternalFailure>();
144 }
145
146 // if the file is not available in the respective(RW/PSRV) partition
147 // then copy the file from RO to the respective(RW/PSRV) partition
148 // and open it for writing.
149
150 fs::path fromPath = context->paths.ro_loc;
151 fromPath /= partition->data.name;
152 if (!fs::exists(fromPath))
153 {
154 MSG_ERR("Couldn't find the file[%s]",fromPath.c_str());
155 elog<InternalFailure>();
156 }
157 //copy the file from ro to respective partition
158 fs::path toPath = context->paths.rw_loc;
159
160 if (partition->data.user.data[1] & PARTITION_PRESERVED)
161 {
162 toPath = context->paths.prsv_loc;
163 }
164
165 toPath /= partition->data.name;
166
167 MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n",
168 toPath.c_str());
169
170 if (fs::copy_file(fromPath, toPath))
171 {
172 MSG_DBG("File copied from[%s] to [%s]\n",
173 fromPath.c_str(), toPath.c_str());
174 }
175
176 rc = Request::open(toPath.c_str(), O_RDWR);
177
178 if (rc != ReturnCode::SUCCESS)
179 {
180 elog<InternalFailure>();
181 }
182
183 return partition;
184}
185
186}// namespace virtual_pnor
187}// namespace openpower