blob: cdb96338b7c8ec6ee88fe8f153310d21aab71ff1 [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
Ratan Guptac0ef9872017-06-06 14:31:37 +05303#include "pnor_partition.hpp"
4#include "config.h"
5#include "mboxd_flash.h"
6#include "mboxd_pnor_partition_table.h"
7#include "xyz/openbmc_project/Common/error.hpp"
8#include <phosphor-logging/log.hpp>
9#include <phosphor-logging/elog-errors.hpp>
10
11#include <stdint.h>
12#include <stdlib.h>
13#include <syslog.h>
14#include <sys/ioctl.h>
15#include <sys/mman.h>
16
17#include "common.h"
18
19#include <string>
20#include <exception>
21#include <stdexcept>
22#include <iostream>
23
24namespace openpower
25{
26namespace virtual_pnor
27{
28
29using namespace phosphor::logging;
30using namespace sdbusplus::xyz::openbmc_project::Common::Error;
31using namespace std::string_literals;
32
Andrew Jefferyf34db312018-03-09 15:27:03 +103033ReturnCode Request::open(const std::string& path, int mode)
Ratan Guptac0ef9872017-06-06 14:31:37 +053034{
Andrew Jefferyf34db312018-03-09 15:27:03 +103035 if (mode == O_RDWR && partition->data.user.data[1] & PARTITION_READONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053036 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103037 MSG_ERR("Can't open RO partition '%s' for write\n", path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +053038 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 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103066 MSG_ERR("Couldn't get the partition info for offset 0x%" PRIx32 "\n",
67 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 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030111 MSG_ERR(
112 "RORequest: Error opening partition file '%s' (offset 0x%" PRIx32
113 "): %u\n",
114 path.c_str(), offset, static_cast<uint8_t>(rc));
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 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030121 MSG_ERR("RORequest: Requested offset 0x%" PRIx32
122 " is in a read-only partition (%s)\n",
123 offset, path.c_str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530124 elog<InternalFailure>();
125 }
126
Ratan Guptac0ef9872017-06-06 14:31:37 +0530127 // we don't get the file in the respective partition(RW/PSRV)
128 // try to open it from RO location.
129
130 fs::path partitionFilePath = context->paths.ro_loc;
131 partitionFilePath /= partition->data.name;
132
Deepak Kodihalli96acf162017-07-12 12:21:36 -0500133 rc = Request::open(partitionFilePath, O_RDONLY);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530134 if (rc != ReturnCode::SUCCESS)
135 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030136 MSG_ERR("RORequest: Failed to open partition file '%s' at RO fallback "
137 "(offset 0x%" PRIx32 "): %u\n",
138 partitionFilePath.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530139 elog<InternalFailure>();
140 }
141
142 return partition;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530143}
144
145const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
146 uint32_t offset)
147{
148 std::string path = getPartitionFilePath(context, offset);
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030149 std::error_code ec;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530150
151 ReturnCode rc = Request::open(path, O_RDWR);
152 if (rc == ReturnCode::SUCCESS)
153 {
154 return partition;
155 }
156 // not interested in any other error except FILE_NOT_FOUND
157 if (rc != ReturnCode::FILE_NOT_FOUND)
158 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030159 MSG_ERR(
160 "RWRequest: Error opening partition file '%s' (offset 0x%" PRIx32
161 "): %d\n",
162 path.c_str(), offset, static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530163 elog<InternalFailure>();
164 }
165
166 // if the file is not available in the respective(RW/PSRV) partition
167 // then copy the file from RO to the respective(RW/PSRV) partition
168 // and open it for writing.
169
170 fs::path fromPath = context->paths.ro_loc;
171 fromPath /= partition->data.name;
172 if (!fs::exists(fromPath))
173 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030174 MSG_ERR("RWRequest: Partition '%s' for offset 0x%" PRIx32
175 " not found in RO directory '%s'\n",
176 partition->data.name, offset, context->paths.ro_loc);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530177 elog<InternalFailure>();
178 }
Andrew Jefferyf34db312018-03-09 15:27:03 +1030179 // copy the file from ro to respective partition
Ratan Guptac0ef9872017-06-06 14:31:37 +0530180 fs::path toPath = context->paths.rw_loc;
181
182 if (partition->data.user.data[1] & PARTITION_PRESERVED)
183 {
184 toPath = context->paths.prsv_loc;
185 }
186
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030187 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
188 partition->data.name, toPath.c_str(), fromPath.c_str());
189
Ratan Guptac0ef9872017-06-06 14:31:37 +0530190 toPath /= partition->data.name;
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030191 if (!fs::copy_file(fromPath, toPath, ec))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530192 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030193 MSG_ERR("RWRequest: Failed to copy file from '%s' to '%s': %d\n",
194 fromPath.c_str(), toPath.c_str(), ec.value());
195 elog<InternalFailure>();
Ratan Guptac0ef9872017-06-06 14:31:37 +0530196 }
197
Andrew Jefferyf34db312018-03-09 15:27:03 +1030198 rc = Request::open(toPath.c_str(), O_RDWR);
Ratan Guptac0ef9872017-06-06 14:31:37 +0530199
200 if (rc != ReturnCode::SUCCESS)
201 {
Andrew Jefferye8a79ff2018-02-27 10:56:32 +1030202 MSG_ERR("RWRequest: Failed to open file at '%s': %d\n", toPath.c_str(),
203 static_cast<uint8_t>(rc));
Ratan Guptac0ef9872017-06-06 14:31:37 +0530204 elog<InternalFailure>();
205 }
206
207 return partition;
208}
209
Andrew Jefferyf34db312018-03-09 15:27:03 +1030210} // namespace virtual_pnor
211} // namespace openpower