blob: ba0ac20904b1a23ffd5d216a61525a7fa2428145 [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
Ratan Guptac0ef9872017-06-06 14:31:37 +0530112 // we don't get the file in the respective partition(RW/PSRV)
113 // try to open it from RO location.
114
115 fs::path partitionFilePath = context->paths.ro_loc;
116 partitionFilePath /= partition->data.name;
117
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500118 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530119 if (rc != ReturnCode::SUCCESS)
120 {
121 elog<InternalFailure>();
122 }
123
124 return partition;
125
126}
127
128const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
129 uint32_t offset)
130{
131 std::string path = getPartitionFilePath(context, offset);
132
133 ReturnCode rc = Request::open(path, O_RDWR);
134 if (rc == ReturnCode::SUCCESS)
135 {
136 return partition;
137 }
138 // not interested in any other error except FILE_NOT_FOUND
139 if (rc != ReturnCode::FILE_NOT_FOUND)
140 {
141 elog<InternalFailure>();
142 }
143
144 // if the file is not available in the respective(RW/PSRV) partition
145 // then copy the file from RO to the respective(RW/PSRV) partition
146 // and open it for writing.
147
148 fs::path fromPath = context->paths.ro_loc;
149 fromPath /= partition->data.name;
150 if (!fs::exists(fromPath))
151 {
152 MSG_ERR("Couldn't find the file[%s]",fromPath.c_str());
153 elog<InternalFailure>();
154 }
155 //copy the file from ro to respective partition
156 fs::path toPath = context->paths.rw_loc;
157
158 if (partition->data.user.data[1] & PARTITION_PRESERVED)
159 {
160 toPath = context->paths.prsv_loc;
161 }
162
163 toPath /= partition->data.name;
164
165 MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n",
166 toPath.c_str());
167
168 if (fs::copy_file(fromPath, toPath))
169 {
170 MSG_DBG("File copied from[%s] to [%s]\n",
171 fromPath.c_str(), toPath.c_str());
172 }
173
174 rc = Request::open(toPath.c_str(), O_RDWR);
175
176 if (rc != ReturnCode::SUCCESS)
177 {
178 elog<InternalFailure>();
179 }
180
181 return partition;
182}
183
184}// namespace virtual_pnor
185}// namespace openpower