blob: 3ec4d228926d2044552d2ba627cf694cd29d741a [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
Ratan Guptac0ef9872017-06-06 14:31:37 +05307#include "pnor_partition.hpp"
Andrew Jefferyad343102018-02-28 00:35:50 +10308#include "pnor_partition_table.hpp"
Ratan Guptac0ef9872017-06-06 14:31:37 +05309#include "config.h"
Ratan Guptac0ef9872017-06-06 14:31:37 +053010#include "mboxd_pnor_partition_table.h"
11#include "xyz/openbmc_project/Common/error.hpp"
12#include <phosphor-logging/log.hpp>
13#include <phosphor-logging/elog-errors.hpp>
14
Andrew Jefferyad343102018-02-28 00:35:50 +103015#include <assert.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103016#include <fcntl.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053017#include <stdint.h>
18#include <stdlib.h>
19#include <syslog.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103020#include <sys/types.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053021#include <sys/ioctl.h>
22#include <sys/mman.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103023#include <unistd.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053024
25#include "common.h"
26
27#include <string>
28#include <exception>
29#include <stdexcept>
30#include <iostream>
31
32namespace openpower
33{
34namespace virtual_pnor
35{
36
Andrew Jefferyad343102018-02-28 00:35:50 +103037namespace fs = std::experimental::filesystem;
Ratan Guptac0ef9872017-06-06 14:31:37 +053038
Andrew Jefferyad343102018-02-28 00:35:50 +103039fs::path Request::getPartitionFilePath(int flags)
Ratan Guptac0ef9872017-06-06 14:31:37 +053040{
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050041 // Check if partition exists in patch location
Andrew Jefferyad343102018-02-28 00:35:50 +103042 auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
43 if (fs::is_regular_file(dst))
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050044 {
Andrew Jefferyad343102018-02-28 00:35:50 +103045 return dst;
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050046 }
47
Andrew Jefferyad343102018-02-28 00:35:50 +103048 switch (partition.data.user.data[1] &
Ratan Guptac0ef9872017-06-06 14:31:37 +053049 (PARTITION_PRESERVED | PARTITION_READONLY))
50 {
51 case PARTITION_PRESERVED:
Andrew Jefferyad343102018-02-28 00:35:50 +103052 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053053 break;
54
55 case PARTITION_READONLY:
Andrew Jefferyad343102018-02-28 00:35:50 +103056 dst = ctx->paths.ro_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053057 break;
58
59 default:
Andrew Jefferyad343102018-02-28 00:35:50 +103060 dst = ctx->paths.rw_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053061 }
Andrew Jefferyad343102018-02-28 00:35:50 +103062 dst /= partition.data.name;
Ratan Guptac0ef9872017-06-06 14:31:37 +053063
Andrew Jefferyad343102018-02-28 00:35:50 +103064 if (fs::exists(dst))
Ratan Guptac0ef9872017-06-06 14:31:37 +053065 {
Andrew Jefferyad343102018-02-28 00:35:50 +103066 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053067 }
Andrew Jefferyad343102018-02-28 00:35:50 +103068
69 if (flags == O_RDONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053070 {
Andrew Jefferyad343102018-02-28 00:35:50 +103071 dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
72 assert(fs::exists(dst));
73 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053074 }
75
Andrew Jefferyad343102018-02-28 00:35:50 +103076 assert(flags == O_RDWR);
77 auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
78 assert(fs::exists(src));
Ratan Guptac0ef9872017-06-06 14:31:37 +053079
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103080 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
Andrew Jefferyad343102018-02-28 00:35:50 +103081 partition.data.name, dst.c_str(), src.c_str());
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103082
Andrew Jefferyad343102018-02-28 00:35:50 +103083 dst = ctx->paths.rw_loc;
84 if (partition.data.user.data[1] & PARTITION_PRESERVED)
Ratan Guptac0ef9872017-06-06 14:31:37 +053085 {
Andrew Jefferyad343102018-02-28 00:35:50 +103086 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053087 }
88
Andrew Jefferyad343102018-02-28 00:35:50 +103089 dst /= partition.data.name;
90 fs::copy_file(src, dst);
Ratan Guptac0ef9872017-06-06 14:31:37 +053091
Andrew Jefferyad343102018-02-28 00:35:50 +103092 return dst;
93}
94
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103095size_t Request::clamp(size_t len)
96{
97 size_t maxAccess = offset + len;
98 size_t partSize = partition.data.size << ctx->block_size_shift;
99 return std::min(maxAccess, partSize) - offset;
100}
101
102void Request::resize(const fs::path &path, size_t len)
103{
104 size_t maxAccess = offset + len;
105 size_t fileSize = fs::file_size(path);
106 if (maxAccess < fileSize)
107 {
108 return;
109 }
110 MSG_DBG("Resizing %s to %zu bytes\n", path.c_str(), maxAccess);
111 int rc = truncate(path.c_str(), maxAccess);
112 if (rc == -1)
113 {
114 MSG_ERR("Failed to resize %s: %d\n", path.c_str(), errno);
115 throw std::system_error(errno, std::system_category());
116 }
117}
118
119size_t Request::fulfil(const fs::path &path, int flags, void *buf, size_t len)
Andrew Jefferyad343102018-02-28 00:35:50 +1030120{
121 if (!(flags == O_RDONLY || flags == O_RDWR))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530122 {
Andrew Jefferyad343102018-02-28 00:35:50 +1030123 std::stringstream err;
124 err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
125 << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
126 throw std::invalid_argument(err.str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530127 }
128
Andrew Jefferyad343102018-02-28 00:35:50 +1030129 int fd = ::open(path.c_str(), flags);
130 if (fd == -1)
131 {
Andrew Jeffery974507e2018-04-30 15:33:55 +0930132 MSG_ERR("Failed to open backing file at '%s': %d\n", path.c_str(),
133 errno);
Andrew Jefferyad343102018-02-28 00:35:50 +1030134 throw std::system_error(errno, std::system_category());
135 }
136
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030137 size_t fileSize = fs::file_size(path);
Andrew Jefferyad343102018-02-28 00:35:50 +1030138 int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030139 auto map = mmap(NULL, fileSize, mprot, MAP_SHARED, fd, 0);
Andrew Jefferyad343102018-02-28 00:35:50 +1030140 if (map == MAP_FAILED)
141 {
142 close(fd);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030143 MSG_ERR("Failed to map backing file '%s' for %zd bytes: %d\n",
144 path.c_str(), fileSize, errno);
Andrew Jefferyad343102018-02-28 00:35:50 +1030145 throw std::system_error(errno, std::system_category());
146 }
147
148 // copy to the reserved memory area
149 if (flags == O_RDONLY)
150 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030151 memset(buf, 0xff, len);
152 memcpy(buf, (char *)map + offset, std::min(len, fileSize));
Andrew Jefferyad343102018-02-28 00:35:50 +1030153 }
154 else
155 {
Andrew Jefferyad343102018-02-28 00:35:50 +1030156 memcpy((char *)map + offset, buf, len);
157 set_flash_bytemap(ctx, base + offset, len, FLASH_DIRTY);
158 }
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030159 munmap(map, fileSize);
Andrew Jefferyad343102018-02-28 00:35:50 +1030160 close(fd);
161
162 return len;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530163}
164
Andrew Jefferyf34db312018-03-09 15:27:03 +1030165} // namespace virtual_pnor
166} // namespace openpower