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