blob: 390c4d55572184ad44fdb586691945062e206016 [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>
Ratan Guptac0ef9872017-06-06 14:31:37 +053013#include <stdint.h>
14#include <stdlib.h>
15#include <syslog.h>
16#include <sys/ioctl.h>
17#include <sys/mman.h>
18
19#include "common.h"
20
21#include <string>
22#include <exception>
23#include <stdexcept>
24#include <iostream>
25
26namespace openpower
27{
28namespace virtual_pnor
29{
30
Andrew Jefferyad343102018-02-28 00:35:50 +103031namespace fs = std::experimental::filesystem;
Ratan Guptac0ef9872017-06-06 14:31:37 +053032
Andrew Jefferyad343102018-02-28 00:35:50 +103033fs::path Request::getPartitionFilePath(int flags)
Ratan Guptac0ef9872017-06-06 14:31:37 +053034{
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050035 // Check if partition exists in patch location
Andrew Jefferyad343102018-02-28 00:35:50 +103036 auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
37 if (fs::is_regular_file(dst))
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050038 {
Andrew Jefferyad343102018-02-28 00:35:50 +103039 return dst;
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050040 }
41
Andrew Jefferyad343102018-02-28 00:35:50 +103042 switch (partition.data.user.data[1] &
Ratan Guptac0ef9872017-06-06 14:31:37 +053043 (PARTITION_PRESERVED | PARTITION_READONLY))
44 {
45 case PARTITION_PRESERVED:
Andrew Jefferyad343102018-02-28 00:35:50 +103046 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053047 break;
48
49 case PARTITION_READONLY:
Andrew Jefferyad343102018-02-28 00:35:50 +103050 dst = ctx->paths.ro_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053051 break;
52
53 default:
Andrew Jefferyad343102018-02-28 00:35:50 +103054 dst = ctx->paths.rw_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053055 }
Andrew Jefferyad343102018-02-28 00:35:50 +103056 dst /= partition.data.name;
Ratan Guptac0ef9872017-06-06 14:31:37 +053057
Andrew Jefferyad343102018-02-28 00:35:50 +103058 if (fs::exists(dst))
Ratan Guptac0ef9872017-06-06 14:31:37 +053059 {
Andrew Jefferyad343102018-02-28 00:35:50 +103060 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053061 }
Andrew Jefferyad343102018-02-28 00:35:50 +103062
63 if (flags == O_RDONLY)
Ratan Guptac0ef9872017-06-06 14:31:37 +053064 {
Andrew Jefferyad343102018-02-28 00:35:50 +103065 dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
66 assert(fs::exists(dst));
67 return dst;
Ratan Guptac0ef9872017-06-06 14:31:37 +053068 }
69
Andrew Jefferyad343102018-02-28 00:35:50 +103070 assert(flags == O_RDWR);
71 auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
72 assert(fs::exists(src));
Ratan Guptac0ef9872017-06-06 14:31:37 +053073
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103074 MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
Andrew Jefferyad343102018-02-28 00:35:50 +103075 partition.data.name, dst.c_str(), src.c_str());
Andrew Jefferye8a79ff2018-02-27 10:56:32 +103076
Andrew Jefferyad343102018-02-28 00:35:50 +103077 dst = ctx->paths.rw_loc;
78 if (partition.data.user.data[1] & PARTITION_PRESERVED)
Ratan Guptac0ef9872017-06-06 14:31:37 +053079 {
Andrew Jefferyad343102018-02-28 00:35:50 +103080 dst = ctx->paths.prsv_loc;
Ratan Guptac0ef9872017-06-06 14:31:37 +053081 }
82
Andrew Jefferyad343102018-02-28 00:35:50 +103083 dst /= partition.data.name;
84 fs::copy_file(src, dst);
Ratan Guptac0ef9872017-06-06 14:31:37 +053085
Andrew Jefferyad343102018-02-28 00:35:50 +103086 return dst;
87}
88
89ssize_t Request::fulfil(void *buf, size_t len, int flags)
90{
91 if (!(flags == O_RDONLY || flags == O_RDWR))
Ratan Guptac0ef9872017-06-06 14:31:37 +053092 {
Andrew Jefferyad343102018-02-28 00:35:50 +103093 std::stringstream err;
94 err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
95 << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
96 throw std::invalid_argument(err.str());
Ratan Guptac0ef9872017-06-06 14:31:37 +053097 }
98
Andrew Jefferyad343102018-02-28 00:35:50 +103099 fs::path path = getPartitionFilePath(flags);
100
101 int fd = ::open(path.c_str(), flags);
102 if (fd == -1)
103 {
104 MSG_ERR("Failed to open backing file at '%s': %d\n",
105 path.c_str(), errno);
106 throw std::system_error(errno, std::system_category());
107 }
108
109 int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
110 auto map = mmap(NULL, partition.data.actual, mprot, MAP_SHARED, fd, 0);
111 if (map == MAP_FAILED)
112 {
113 close(fd);
114 MSG_ERR("Failed to map backing file '%s' for %d bytes: %d\n",
115 path.c_str(), partition.data.actual, errno);
116 throw std::system_error(errno, std::system_category());
117 }
118
119 // copy to the reserved memory area
120 if (flags == O_RDONLY)
121 {
122 len = std::min(partition.data.actual - offset, len);
123 memcpy(buf, (char *)map + offset, len);
124 }
125 else
126 {
127 // if the asked offset + no of bytes to read is greater
128 // then size of the partition file then throw error.
129 //
130 // FIXME: Don't use .actual, use (.size << ctx->block_size_shift),
131 // otherwise we can't grow the size of the data to fill the partition
132 if ((base + offset + len) > (base + partition.data.actual))
133 {
134 munmap(map, partition.data.actual);
135 close(fd);
136
137 /* FIXME: offset calculation */
138 std::stringstream err;
139 err << "Request size 0x" << std::hex << len << " from offset 0x"
140 << std::hex << offset << " exceeds the partition size 0x"
141 << std::hex << partition.data.actual;
142 throw OutOfBoundsOffset(err.str());
143 }
144 memcpy((char *)map + offset, buf, len);
145 set_flash_bytemap(ctx, base + offset, len, FLASH_DIRTY);
146 }
147 munmap(map, partition.data.actual);
148 close(fd);
149
150 return len;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530151}
152
Andrew Jefferyf34db312018-03-09 15:27:03 +1030153} // namespace virtual_pnor
154} // namespace openpower