blob: 1868ed757dc1924133659cb1f6e31482eb2b4652 [file] [log] [blame]
Andrew Jefferyacee6832018-02-21 22:17:08 +10301/*
2 * Mailbox Daemon Implementation
3 *
4 * Copyright 2018 IBM
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
Ratan Guptac0ef9872017-06-06 14:31:37 +053019#include "pnor_partition.hpp"
20#include "config.h"
21#include "mboxd_flash.h"
22#include "mboxd_pnor_partition_table.h"
23#include "xyz/openbmc_project/Common/error.hpp"
24#include <phosphor-logging/log.hpp>
25#include <phosphor-logging/elog-errors.hpp>
26
27#include <stdint.h>
28#include <stdlib.h>
29#include <syslog.h>
30#include <sys/ioctl.h>
31#include <sys/mman.h>
32
33#include "common.h"
34
35#include <string>
36#include <exception>
37#include <stdexcept>
38#include <iostream>
39
40namespace openpower
41{
42namespace virtual_pnor
43{
44
45using namespace phosphor::logging;
46using namespace sdbusplus::xyz::openbmc_project::Common::Error;
47using namespace std::string_literals;
48
Andrew Jefferyf34db312018-03-09 15:27:03 +103049ReturnCode Request::open(const std::string& path, int mode)
Ratan Guptac0ef9872017-06-06 14:31:37 +053050{
Andrew Jefferyf34db312018-03-09 15:27:03 +103051 if (mode == O_RDWR && partition->data.user.data[1] & PARTITION_READONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053052 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103053 MSG_ERR("Can't open RO partition '%s' for write\n", path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +053054 return ReturnCode::PARTITION_READ_ONLY;
55 }
56
57 fs::path partitionFilePath = path;
58
59 if (!fs::exists(partitionFilePath))
60 {
61 return ReturnCode::FILE_NOT_FOUND;
62 }
63
64 auto descriptor = ::open(partitionFilePath.c_str(), mode);
65 if (descriptor < 0)
66 {
67 return ReturnCode::FILE_OPEN_FAILURE;
68 }
69
70 fd.set(descriptor);
71 descriptor = -1;
72
73 return ReturnCode::SUCCESS;
74}
75
76std::string Request::getPartitionFilePath(struct mbox_context* context,
77 uint32_t offset)
78{
79 partition = vpnor_get_partition(context, offset);
80 if (!partition)
81 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103082 MSG_ERR("Couldn't get the partition info for offset 0x%" PRIx32 "\n",
83 offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +053084 elog<InternalFailure>();
85 }
86
87 fs::path partitionFilePath;
88
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050089 // Check if partition exists in patch location
90 partitionFilePath = context->paths.patch_loc;
91 partitionFilePath /= partition->data.name;
92 if (fs::is_regular_file(partitionFilePath))
93 {
94 return partitionFilePath.string();
95 }
96
Ratan Guptac0ef9872017-06-06 14:31:37 +053097 switch (partition->data.user.data[1] &
98 (PARTITION_PRESERVED | PARTITION_READONLY))
99 {
100 case PARTITION_PRESERVED:
101 partitionFilePath = context->paths.prsv_loc;
102 break;
103
104 case PARTITION_READONLY:
105 partitionFilePath = context->paths.ro_loc;
106 break;
107
108 default:
109 partitionFilePath = context->paths.rw_loc;
110 }
111 partitionFilePath /= partition->data.name;
112 return partitionFilePath.string();
113}
114
115const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
116 uint32_t offset)
117{
118 std::string path = getPartitionFilePath(context, offset);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530119 ReturnCode rc = Request::open(path, O_RDONLY);
120 if (rc == ReturnCode::SUCCESS)
121 {
122 return partition;
123 }
124 // not interested in any other error except FILE_NOT_FOUND
125 if (rc != ReturnCode::FILE_NOT_FOUND)
126 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030127 MSG_ERR(
128 "RORequest: Error opening partition file '%s' (offset 0x%" PRIx32
129 "): %u\n",
130 path.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530131 elog<InternalFailure>();
132 }
133
134 // if the offset lies in read only partition then throw error.
135 if (partition->data.user.data[1] & PARTITION_READONLY)
136 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030137 MSG_ERR("RORequest: Requested offset 0x%" PRIx32
138 " is in a read-only partition (%s)\n",
139 offset, path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530140 elog<InternalFailure>();
141 }
142
Ratan Guptac0ef9872017-06-06 14:31:37 +0530143 // we don't get the file in the respective partition(RW/PSRV)
144 // try to open it from RO location.
145
146 fs::path partitionFilePath = context->paths.ro_loc;
147 partitionFilePath /= partition->data.name;
148
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500149 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530150 if (rc != ReturnCode::SUCCESS)
151 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030152 MSG_ERR("RORequest: Failed to open partition file '%s' at RO fallback "
153 "(offset 0x%" PRIx32 "): %u\n",
154 partitionFilePath.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530155 elog<InternalFailure>();
156 }
157
158 return partition;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530159}
160
161const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
162 uint32_t offset)
163{
164 std::string path = getPartitionFilePath(context, offset);
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030165 std::error_code ec;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530166
167 ReturnCode rc = Request::open(path, O_RDWR);
168 if (rc == ReturnCode::SUCCESS)
169 {
170 return partition;
171 }
172 // not interested in any other error except FILE_NOT_FOUND
173 if (rc != ReturnCode::FILE_NOT_FOUND)
174 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030175 MSG_ERR(
176 "RWRequest: Error opening partition file '%s' (offset 0x%" PRIx32
177 "): %d\n",
178 path.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530179 elog<InternalFailure>();
180 }
181
182 // if the file is not available in the respective(RW/PSRV) partition
183 // then copy the file from RO to the respective(RW/PSRV) partition
184 // and open it for writing.
185
186 fs::path fromPath = context->paths.ro_loc;
187 fromPath /= partition->data.name;
188 if (!fs::exists(fromPath))
189 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030190 MSG_ERR("RWRequest: Partition '%s' for offset 0x%" PRIx32
191 " not found in RO directory '%s'\n",
192 partition->data.name, offset, context->paths.ro_loc);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530193 elog<InternalFailure>();
194 }
Andrew Jefferyf34db312018-03-09 15:27:03 +1030195 // copy the file from ro to respective partition
Ratan Guptac0ef9872017-06-06 14:31:37 +0530196 fs::path toPath = context->paths.rw_loc;
197
198 if (partition->data.user.data[1] & PARTITION_PRESERVED)
199 {
200 toPath = context->paths.prsv_loc;
201 }
202
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030203 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
204 partition->data.name, toPath.c_str(), fromPath.c_str());
205
Ratan Guptac0ef9872017-06-06 14:31:37 +0530206 toPath /= partition->data.name;
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030207 if (!fs::copy_file(fromPath, toPath, ec))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530208 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030209 MSG_ERR("RWRequest: Failed to copy file from '%s' to '%s': %d\n",
210 fromPath.c_str(), toPath.c_str(), ec.value());
211 elog<InternalFailure>();
Ratan Guptac0ef9872017-06-06 14:31:37 +0530212 }
213
Andrew Jefferyf34db312018-03-09 15:27:03 +1030214 rc = Request::open(toPath.c_str(), O_RDWR);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530215
216 if (rc != ReturnCode::SUCCESS)
217 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030218 MSG_ERR("RWRequest: Failed to open file at '%s': %d\n", toPath.c_str(),
219 static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530220 elog<InternalFailure>();
221 }
222
223 return partition;
224}
225
Andrew Jefferyf34db312018-03-09 15:27:03 +1030226} // namespace virtual_pnor
227} // namespace openpower