blob: 613ee26fcd83b67811a7df1488b1d5de57b9c1fb [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
Andrew Jeffery71eaa732018-08-08 16:44:24 +09303extern "C" {
4#include "flash.h"
5}
6
William A. Kennington IIId5f1d402018-10-11 13:55:04 -07007#include "config.h"
8
Ratan Guptac0ef9872017-06-06 14:31:37 +05309#include "pnor_partition.hpp"
Andrew Jefferyad343102018-02-28 00:35:50 +103010#include "pnor_partition_table.hpp"
Ratan Guptac0ef9872017-06-06 14:31:37 +053011#include "xyz/openbmc_project/Common/error.hpp"
Ratan Guptac0ef9872017-06-06 14:31:37 +053012
Andrew Jefferyad343102018-02-28 00:35:50 +103013#include <assert.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103014#include <fcntl.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053015#include <stdint.h>
16#include <stdlib.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053017#include <sys/ioctl.h>
18#include <sys/mman.h>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070019#include <sys/types.h>
20#include <syslog.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103021#include <unistd.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053022
Ratan Guptac0ef9872017-06-06 14:31:37 +053023#include <exception>
Ratan Guptac0ef9872017-06-06 14:31:37 +053024#include <iostream>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070025#include <phosphor-logging/elog-errors.hpp>
26#include <phosphor-logging/log.hpp>
27#include <stdexcept>
28#include <string>
29
30#include "common.h"
31#include "mboxd_pnor_partition_table.h"
Ratan Guptac0ef9872017-06-06 14:31:37 +053032
33namespace openpower
34{
35namespace virtual_pnor
36{
37
Andrew Jefferyad343102018-02-28 00:35:50 +103038namespace fs = std::experimental::filesystem;
Ratan Guptac0ef9872017-06-06 14:31:37 +053039
Andrew Jefferyad343102018-02-28 00:35:50 +103040fs::path Request::getPartitionFilePath(int flags)
Ratan Guptac0ef9872017-06-06 14:31:37 +053041{
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050042 // Check if partition exists in patch location
Andrew Jefferyad343102018-02-28 00:35:50 +103043 auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
44 if (fs::is_regular_file(dst))
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050045 {
Andrew Jefferyad343102018-02-28 00:35:50 +103046 return dst;
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050047 }
48
Andrew Jefferyad343102018-02-28 00:35:50 +103049 switch (partition.data.user.data[1] &
Ratan Guptac0ef9872017-06-06 14:31:37 +053050 (PARTITION_PRESERVED | PARTITION_READONLY))
51 {
52 case PARTITION_PRESERVED:
Andrew Jefferyad343102018-02-28 00:35:50 +103053 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053054 break;
55
56 case PARTITION_READONLY:
Andrew Jefferyad343102018-02-28 00:35:50 +103057 dst = ctx->paths.ro_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053058 break;
59
60 default:
Andrew Jefferyad343102018-02-28 00:35:50 +103061 dst = ctx->paths.rw_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053062 }
Andrew Jefferyad343102018-02-28 00:35:50 +103063 dst /= partition.data.name;
Ratan Guptac0ef9872017-06-06 14:31:37 +053064
Andrew Jefferyad343102018-02-28 00:35:50 +103065 if (fs::exists(dst))
Ratan Guptac0ef9872017-06-06 14:31:37 +053066 {
Andrew Jefferyad343102018-02-28 00:35:50 +103067 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053068 }
Andrew Jefferyad343102018-02-28 00:35:50 +103069
70 if (flags == O_RDONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053071 {
Andrew Jefferyad343102018-02-28 00:35:50 +103072 dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
73 assert(fs::exists(dst));
74 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053075 }
76
Andrew Jefferyad343102018-02-28 00:35:50 +103077 assert(flags == O_RDWR);
78 auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
79 assert(fs::exists(src));
Ratan Guptac0ef9872017-06-06 14:31:37 +053080
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103081 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
Andrew Jefferyad343102018-02-28 00:35:50 +103082 partition.data.name, dst.c_str(), src.c_str());
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103083
Andrew Jefferyad343102018-02-28 00:35:50 +103084 dst = ctx->paths.rw_loc;
85 if (partition.data.user.data[1] & PARTITION_PRESERVED)
Ratan Guptac0ef9872017-06-06 14:31:37 +053086 {
Andrew Jefferyad343102018-02-28 00:35:50 +103087 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053088 }
89
Andrew Jefferyad343102018-02-28 00:35:50 +103090 dst /= partition.data.name;
91 fs::copy_file(src, dst);
Ratan Guptac0ef9872017-06-06 14:31:37 +053092
Andrew Jefferyad343102018-02-28 00:35:50 +103093 return dst;
94}
95
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103096size_t Request::clamp(size_t len)
97{
98 size_t maxAccess = offset + len;
99 size_t partSize = partition.data.size << ctx->block_size_shift;
100 return std::min(maxAccess, partSize) - offset;
101}
102
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700103void Request::resize(const fs::path& path, size_t len)
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030104{
105 size_t maxAccess = offset + len;
106 size_t fileSize = fs::file_size(path);
107 if (maxAccess < fileSize)
108 {
109 return;
110 }
111 MSG_DBG("Resizing %s to %zu bytes\n", path.c_str(), maxAccess);
112 int rc = truncate(path.c_str(), maxAccess);
113 if (rc == -1)
114 {
115 MSG_ERR("Failed to resize %s: %d\n", path.c_str(), errno);
116 throw std::system_error(errno, std::system_category());
117 }
118}
119
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700120size_t Request::fulfil(const fs::path& path, int flags, void* buf, size_t len)
Andrew Jefferyad343102018-02-28 00:35:50 +1030121{
122 if (!(flags == O_RDONLY || flags == O_RDWR))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530123 {
Andrew Jefferyad343102018-02-28 00:35:50 +1030124 std::stringstream err;
125 err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
126 << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
127 throw std::invalid_argument(err.str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530128 }
129
Andrew Jefferyad343102018-02-28 00:35:50 +1030130 int fd = ::open(path.c_str(), flags);
131 if (fd == -1)
132 {
Andrew Jeffery974507e2018-04-30 15:33:55 +0930133 MSG_ERR("Failed to open backing file at '%s': %d\n", path.c_str(),
134 errno);
Andrew Jefferyad343102018-02-28 00:35:50 +1030135 throw std::system_error(errno, std::system_category());
136 }
137
Andrew Jefferycc650612018-08-30 12:17:59 +0930138 if (flags == O_RDONLY)
139 {
140 MSG_INFO("Fulfilling read request against %s at offset 0x%zx into %p "
141 "for %zu\n",
142 path.c_str(), offset, buf, len);
143 }
144 else
145 {
146 MSG_INFO("Fulfilling write request against %s at offset 0x%zx from %p "
147 "for %zu\n",
148 path.c_str(), offset, buf, len);
149 }
150
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030151 size_t fileSize = fs::file_size(path);
Andrew Jefferyad343102018-02-28 00:35:50 +1030152 int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030153 auto map = mmap(NULL, fileSize, mprot, MAP_SHARED, fd, 0);
Andrew Jefferyad343102018-02-28 00:35:50 +1030154 if (map == MAP_FAILED)
155 {
156 close(fd);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030157 MSG_ERR("Failed to map backing file '%s' for %zd bytes: %d\n",
158 path.c_str(), fileSize, errno);
Andrew Jefferyad343102018-02-28 00:35:50 +1030159 throw std::system_error(errno, std::system_category());
160 }
161
162 // copy to the reserved memory area
163 if (flags == O_RDONLY)
164 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030165 memset(buf, 0xff, len);
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700166 memcpy(buf, (char*)map + offset, std::min(len, fileSize));
Andrew Jefferyad343102018-02-28 00:35:50 +1030167 }
168 else
169 {
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700170 memcpy((char*)map + offset, buf, len);
Andrew Jefferyf953f792018-08-08 16:56:03 +0930171 flash_set_bytemap(ctx, base + offset, len, FLASH_DIRTY);
Andrew Jefferyad343102018-02-28 00:35:50 +1030172 }
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030173 munmap(map, fileSize);
Andrew Jefferyad343102018-02-28 00:35:50 +1030174 close(fd);
175
176 return len;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530177}
178
Andrew Jefferyf34db312018-03-09 15:27:03 +1030179} // namespace virtual_pnor
180} // namespace openpower