| Ratan Gupta | c0ef987 | 2017-06-06 14:31:37 +0530 | [diff] [blame] | 1 | #include "pnor_partition.hpp" | 
|  | 2 | #include "config.h" | 
|  | 3 | #include "mboxd_flash.h" | 
|  | 4 | #include "mboxd_pnor_partition_table.h" | 
|  | 5 | #include "xyz/openbmc_project/Common/error.hpp" | 
|  | 6 | #include <phosphor-logging/log.hpp> | 
|  | 7 | #include <phosphor-logging/elog-errors.hpp> | 
|  | 8 |  | 
|  | 9 | #include <stdint.h> | 
|  | 10 | #include <stdlib.h> | 
|  | 11 | #include <syslog.h> | 
|  | 12 | #include <sys/ioctl.h> | 
|  | 13 | #include <sys/mman.h> | 
|  | 14 |  | 
|  | 15 | #include "common.h" | 
|  | 16 |  | 
|  | 17 | #include <string> | 
|  | 18 | #include <exception> | 
|  | 19 | #include <stdexcept> | 
|  | 20 | #include <iostream> | 
|  | 21 |  | 
|  | 22 | namespace openpower | 
|  | 23 | { | 
|  | 24 | namespace virtual_pnor | 
|  | 25 | { | 
|  | 26 |  | 
|  | 27 | using namespace phosphor::logging; | 
|  | 28 | using namespace sdbusplus::xyz::openbmc_project::Common::Error; | 
|  | 29 | using namespace std::string_literals; | 
|  | 30 |  | 
|  | 31 | ReturnCode Request::open(const std::string& path, | 
|  | 32 | int mode) | 
|  | 33 | { | 
|  | 34 | if (mode == O_RDWR && | 
|  | 35 | partition->data.user.data[1] & PARTITION_READONLY) | 
|  | 36 | { | 
|  | 37 | MSG_ERR("Can't open the RO partition for write"); | 
|  | 38 | 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 |  | 
|  | 60 | std::string Request::getPartitionFilePath(struct mbox_context* context, | 
|  | 61 | uint32_t offset) | 
|  | 62 | { | 
|  | 63 | partition = vpnor_get_partition(context, offset); | 
|  | 64 | if (!partition) | 
|  | 65 | { | 
|  | 66 | MSG_ERR("Couldn't get the partition info for offset[0x%.8x]",offset); | 
|  | 67 | elog<InternalFailure>(); | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | fs::path partitionFilePath; | 
|  | 71 |  | 
|  | 72 | switch (partition->data.user.data[1] & | 
|  | 73 | (PARTITION_PRESERVED | PARTITION_READONLY)) | 
|  | 74 | { | 
|  | 75 | case PARTITION_PRESERVED: | 
|  | 76 | partitionFilePath = context->paths.prsv_loc; | 
|  | 77 | break; | 
|  | 78 |  | 
|  | 79 | case PARTITION_READONLY: | 
|  | 80 | partitionFilePath = context->paths.ro_loc; | 
|  | 81 | break; | 
|  | 82 |  | 
|  | 83 | default: | 
|  | 84 | partitionFilePath = context->paths.rw_loc; | 
|  | 85 | } | 
|  | 86 | partitionFilePath /= partition->data.name; | 
|  | 87 | return partitionFilePath.string(); | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context, | 
|  | 91 | uint32_t offset) | 
|  | 92 | { | 
|  | 93 | std::string path = getPartitionFilePath(context, offset); | 
| Ratan Gupta | c0ef987 | 2017-06-06 14:31:37 +0530 | [diff] [blame] | 94 | ReturnCode rc = Request::open(path, O_RDONLY); | 
|  | 95 | if (rc == ReturnCode::SUCCESS) | 
|  | 96 | { | 
|  | 97 | return partition; | 
|  | 98 | } | 
|  | 99 | // not interested in any other error except FILE_NOT_FOUND | 
|  | 100 | if (rc != ReturnCode::FILE_NOT_FOUND) | 
|  | 101 | { | 
|  | 102 | elog<InternalFailure>(); | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | // if the offset lies in read only partition then throw error. | 
|  | 106 | if (partition->data.user.data[1] & PARTITION_READONLY) | 
|  | 107 | { | 
|  | 108 | MSG_ERR("Can't open the partition file"); | 
|  | 109 | elog<InternalFailure>(); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | MSG_DBG("Couldn't open the file[%s]", path.c_str()); | 
| Ratan Gupta | 6a98e18 | 2017-06-06 15:04:23 +0530 | [diff] [blame] | 113 |  | 
| Ratan Gupta | c0ef987 | 2017-06-06 14:31:37 +0530 | [diff] [blame] | 114 | // we don't get the file in the respective partition(RW/PSRV) | 
|  | 115 | // try to open it from RO location. | 
|  | 116 |  | 
|  | 117 | fs::path partitionFilePath = context->paths.ro_loc; | 
|  | 118 | partitionFilePath /= partition->data.name; | 
|  | 119 |  | 
|  | 120 | rc = Request::open(path, O_RDONLY); | 
|  | 121 | if (rc != ReturnCode::SUCCESS) | 
|  | 122 | { | 
|  | 123 | elog<InternalFailure>(); | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | return partition; | 
|  | 127 |  | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context, | 
|  | 131 | uint32_t offset) | 
|  | 132 | { | 
|  | 133 | std::string path = getPartitionFilePath(context, offset); | 
|  | 134 |  | 
|  | 135 | ReturnCode rc = Request::open(path, O_RDWR); | 
|  | 136 | if (rc == ReturnCode::SUCCESS) | 
|  | 137 | { | 
|  | 138 | return partition; | 
|  | 139 | } | 
|  | 140 | // not interested in any other error except FILE_NOT_FOUND | 
|  | 141 | if (rc != ReturnCode::FILE_NOT_FOUND) | 
|  | 142 | { | 
|  | 143 | elog<InternalFailure>(); | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | // if the file is not available in the respective(RW/PSRV) partition | 
|  | 147 | // then copy the file from RO to the respective(RW/PSRV) partition | 
|  | 148 | // and open it for writing. | 
|  | 149 |  | 
|  | 150 | fs::path fromPath = context->paths.ro_loc; | 
|  | 151 | fromPath /= partition->data.name; | 
|  | 152 | if (!fs::exists(fromPath)) | 
|  | 153 | { | 
|  | 154 | MSG_ERR("Couldn't find the file[%s]",fromPath.c_str()); | 
|  | 155 | elog<InternalFailure>(); | 
|  | 156 | } | 
|  | 157 | //copy the file from ro to respective partition | 
|  | 158 | fs::path toPath = context->paths.rw_loc; | 
|  | 159 |  | 
|  | 160 | if (partition->data.user.data[1] & PARTITION_PRESERVED) | 
|  | 161 | { | 
|  | 162 | toPath = context->paths.prsv_loc; | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | toPath /= partition->data.name; | 
|  | 166 |  | 
|  | 167 | MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n", | 
|  | 168 | toPath.c_str()); | 
|  | 169 |  | 
|  | 170 | if (fs::copy_file(fromPath, toPath)) | 
|  | 171 | { | 
|  | 172 | MSG_DBG("File copied from[%s] to [%s]\n", | 
|  | 173 | fromPath.c_str(), toPath.c_str()); | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | rc  = Request::open(toPath.c_str(), O_RDWR); | 
|  | 177 |  | 
|  | 178 | if (rc != ReturnCode::SUCCESS) | 
|  | 179 | { | 
|  | 180 | elog<InternalFailure>(); | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | return partition; | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | }// namespace virtual_pnor | 
|  | 187 | }// namespace openpower |