blob: 84aeb3fcd78ed700fc1e9bbf0bd1e5fb0963707d [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"
Andrew Jefferyad343102018-02-28 00:35:50 +10304#include "pnor_partition_table.hpp"
Ratan Guptac0ef9872017-06-06 14:31:37 +05305#include "config.h"
6#include "mboxd_flash.h"
7#include "mboxd_pnor_partition_table.h"
8#include "xyz/openbmc_project/Common/error.hpp"
9#include <phosphor-logging/log.hpp>
10#include <phosphor-logging/elog-errors.hpp>
11
Andrew Jefferyad343102018-02-28 00:35:50 +103012#include <assert.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103013#include <fcntl.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053014#include <stdint.h>
15#include <stdlib.h>
16#include <syslog.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103017#include <sys/types.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053018#include <sys/ioctl.h>
19#include <sys/mman.h>
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103020#include <unistd.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053021
22#include "common.h"
23
24#include <string>
25#include <exception>
26#include <stdexcept>
27#include <iostream>
28
29namespace openpower
30{
31namespace virtual_pnor
32{
33
Andrew Jefferyad343102018-02-28 00:35:50 +103034namespace fs = std::experimental::filesystem;
Ratan Guptac0ef9872017-06-06 14:31:37 +053035
Andrew Jefferyad343102018-02-28 00:35:50 +103036fs::path Request::getPartitionFilePath(int flags)
Ratan Guptac0ef9872017-06-06 14:31:37 +053037{
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050038 // Check if partition exists in patch location
Andrew Jefferyad343102018-02-28 00:35:50 +103039 auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
40 if (fs::is_regular_file(dst))
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050041 {
Andrew Jefferyad343102018-02-28 00:35:50 +103042 return dst;
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050043 }
44
Andrew Jefferyad343102018-02-28 00:35:50 +103045 switch (partition.data.user.data[1] &
Ratan Guptac0ef9872017-06-06 14:31:37 +053046 (PARTITION_PRESERVED | PARTITION_READONLY))
47 {
48 case PARTITION_PRESERVED:
Andrew Jefferyad343102018-02-28 00:35:50 +103049 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053050 break;
51
52 case PARTITION_READONLY:
Andrew Jefferyad343102018-02-28 00:35:50 +103053 dst = ctx->paths.ro_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053054 break;
55
56 default:
Andrew Jefferyad343102018-02-28 00:35:50 +103057 dst = ctx->paths.rw_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053058 }
Andrew Jefferyad343102018-02-28 00:35:50 +103059 dst /= partition.data.name;
Ratan Guptac0ef9872017-06-06 14:31:37 +053060
Andrew Jefferyad343102018-02-28 00:35:50 +103061 if (fs::exists(dst))
Ratan Guptac0ef9872017-06-06 14:31:37 +053062 {
Andrew Jefferyad343102018-02-28 00:35:50 +103063 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053064 }
Andrew Jefferyad343102018-02-28 00:35:50 +103065
66 if (flags == O_RDONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053067 {
Andrew Jefferyad343102018-02-28 00:35:50 +103068 dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
69 assert(fs::exists(dst));
70 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053071 }
72
Andrew Jefferyad343102018-02-28 00:35:50 +103073 assert(flags == O_RDWR);
74 auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
75 assert(fs::exists(src));
Ratan Guptac0ef9872017-06-06 14:31:37 +053076
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103077 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
Andrew Jefferyad343102018-02-28 00:35:50 +103078 partition.data.name, dst.c_str(), src.c_str());
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103079
Andrew Jefferyad343102018-02-28 00:35:50 +103080 dst = ctx->paths.rw_loc;
81 if (partition.data.user.data[1] & PARTITION_PRESERVED)
Ratan Guptac0ef9872017-06-06 14:31:37 +053082 {
Andrew Jefferyad343102018-02-28 00:35:50 +103083 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053084 }
85
Andrew Jefferyad343102018-02-28 00:35:50 +103086 dst /= partition.data.name;
87 fs::copy_file(src, dst);
Ratan Guptac0ef9872017-06-06 14:31:37 +053088
Andrew Jefferyad343102018-02-28 00:35:50 +103089 return dst;
90}
91
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103092size_t Request::clamp(size_t len)
93{
94 size_t maxAccess = offset + len;
95 size_t partSize = partition.data.size << ctx->block_size_shift;
96 return std::min(maxAccess, partSize) - offset;
97}
98
99void Request::resize(const fs::path &path, size_t len)
100{
101 size_t maxAccess = offset + len;
102 size_t fileSize = fs::file_size(path);
103 if (maxAccess < fileSize)
104 {
105 return;
106 }
107 MSG_DBG("Resizing %s to %zu bytes\n", path.c_str(), maxAccess);
108 int rc = truncate(path.c_str(), maxAccess);
109 if (rc == -1)
110 {
111 MSG_ERR("Failed to resize %s: %d\n", path.c_str(), errno);
112 throw std::system_error(errno, std::system_category());
113 }
114}
115
116size_t Request::fulfil(const fs::path &path, int flags, void *buf, size_t len)
Andrew Jefferyad343102018-02-28 00:35:50 +1030117{
118 if (!(flags == O_RDONLY || flags == O_RDWR))
Ratan Guptac0ef9872017-06-06 14:31:37 +0530119 {
Andrew Jefferyad343102018-02-28 00:35:50 +1030120 std::stringstream err;
121 err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
122 << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
123 throw std::invalid_argument(err.str());
Ratan Guptac0ef9872017-06-06 14:31:37 +0530124 }
125
Andrew Jefferyad343102018-02-28 00:35:50 +1030126 int fd = ::open(path.c_str(), flags);
127 if (fd == -1)
128 {
129 MSG_ERR("Failed to open backing file at '%s': %d\n",
130 path.c_str(), errno);
131 throw std::system_error(errno, std::system_category());
132 }
133
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030134 size_t fileSize = fs::file_size(path);
Andrew Jefferyad343102018-02-28 00:35:50 +1030135 int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030136 auto map = mmap(NULL, fileSize, mprot, MAP_SHARED, fd, 0);
Andrew Jefferyad343102018-02-28 00:35:50 +1030137 if (map == MAP_FAILED)
138 {
139 close(fd);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030140 MSG_ERR("Failed to map backing file '%s' for %zd bytes: %d\n",
141 path.c_str(), fileSize, errno);
Andrew Jefferyad343102018-02-28 00:35:50 +1030142 throw std::system_error(errno, std::system_category());
143 }
144
145 // copy to the reserved memory area
146 if (flags == O_RDONLY)
147 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030148 memset(buf, 0xff, len);
149 memcpy(buf, (char *)map + offset, std::min(len, fileSize));
Andrew Jefferyad343102018-02-28 00:35:50 +1030150 }
151 else
152 {
Andrew Jefferyad343102018-02-28 00:35:50 +1030153 memcpy((char *)map + offset, buf, len);
154 set_flash_bytemap(ctx, base + offset, len, FLASH_DIRTY);
155 }
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030156 munmap(map, fileSize);
Andrew Jefferyad343102018-02-28 00:35:50 +1030157 close(fd);
158
159 return len;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530160}
161
Andrew Jefferyf34db312018-03-09 15:27:03 +1030162} // namespace virtual_pnor
163} // namespace openpower