blob: 3c83f02731d2ba8afa550767b7ccff55d0f53a83 [file] [log] [blame]
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -05001/*
2 * Mailbox Daemon Window Helpers
3 *
4 * Copyright 2017 IBM
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
Ratan Gupta8441a392017-05-05 21:42:53 +053020#include <fcntl.h>
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050021#include <stdint.h>
22#include <stdlib.h>
23#include <syslog.h>
Ratan Gupta8441a392017-05-05 21:42:53 +053024#include <sys/mman.h>
25#include <unistd.h>
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050026
27extern "C" {
28#include "common.h"
29}
30
Ratan Gupta8441a392017-05-05 21:42:53 +053031#include "config.h"
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050032#include "mboxd_flash.h"
33#include "mboxd_pnor_partition_table.h"
Ratan Gupta6a98e182017-06-06 15:04:23 +053034#include "pnor_partition.hpp"
35#include "xyz/openbmc_project/Common/error.hpp"
36#include <phosphor-logging/log.hpp>
37#include <phosphor-logging/elog-errors.hpp>
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050038
Ratan Gupta8441a392017-05-05 21:42:53 +053039#include <string>
40#include <exception>
41#include <stdexcept>
Ratan Gupta8441a392017-05-05 21:42:53 +053042
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050043/*
44 * copy_flash() - Copy data from the virtual pnor into a provided buffer
45 * @context: The mbox context pointer
46 * @offset: The pnor offset to copy from (bytes)
47 * @mem: The buffer to copy into (must be of atleast 'size' bytes)
48 * @size: The number of bytes to copy
49 *
50 * Return: 0 on success otherwise negative error code
51 */
52int copy_flash(struct mbox_context* context, uint32_t offset, void* mem,
53 uint32_t size)
54{
Ratan Gupta6a98e182017-06-06 15:04:23 +053055 using namespace phosphor::logging;
56 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
57 using namespace std::string_literals;
58
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050059 int rc = 0;
60
61 MSG_DBG("Copy virtual pnor to %p for size 0x%.8x from offset 0x%.8x\n",
62 mem, size, offset);
63
64 /* The virtual PNOR partition table starts at offset 0 in the virtual
65 * pnor image. Check if host asked for an offset that lies within the
66 * partition table.
67 */
Ratan Gupta8441a392017-05-05 21:42:53 +053068 try
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050069 {
Ratan Gupta8441a392017-05-05 21:42:53 +053070 size_t sz =
71 vpnor_get_partition_table_size(context) << context->block_size_shift;
72 if (offset < sz)
73 {
74 const struct pnor_partition_table* table =
75 vpnor_get_partition_table(context);
76 memcpy(mem,
77 ((uint8_t*)table) + offset,
78 min_u32(sz - offset, size));
79 }
80 else
81 {
Ratan Gupta6a98e182017-06-06 15:04:23 +053082 openpower::virtual_pnor::RORequest roRequest;
83 auto partitionInfo = roRequest.getPartitionInfo(context, offset);
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -050084
Ratan Gupta6a98e182017-06-06 15:04:23 +053085 auto mapped_mem = mmap(NULL, partitionInfo->data.actual,
86 PROT_READ, MAP_PRIVATE, roRequest.fd(), 0);
Ratan Gupta8441a392017-05-05 21:42:53 +053087
Ratan Gupta8441a392017-05-05 21:42:53 +053088 if (mem == MAP_FAILED)
89 {
Ratan Gupta6a98e182017-06-06 15:04:23 +053090 MSG_ERR("Failed to map partition=%s:Error=%s\n",
91 partitionInfo->data.name, strerror(errno));
92
93 elog<InternalFailure>();
94 }
95
96 // if the asked offset + no of bytes to read is greater
97 // then size of the partition file then throw error.
98
99 uint32_t baseOffset = partitionInfo->data.base << context->block_size_shift;
100
101 if ((offset + size) > (baseOffset + partitionInfo->data.actual))
102 {
103 MSG_ERR("Offset is beyond the partition file length[0x%.8x]\n",
104 partitionInfo->data.actual);
105 munmap(mapped_mem, partitionInfo->data.actual);
106 elog<InternalFailure>();
Ratan Gupta8441a392017-05-05 21:42:53 +0530107 }
108
109 //copy to the reserved memory area
Ratan Gupta6a98e182017-06-06 15:04:23 +0530110 auto diffOffset = offset - baseOffset;
111 memcpy(mem, (char*)mapped_mem + diffOffset , size);
112 munmap(mapped_mem, partitionInfo->data.actual);
Ratan Gupta8441a392017-05-05 21:42:53 +0530113 }
114 }
Ratan Gupta6a98e182017-06-06 15:04:23 +0530115 catch (InternalFailure& e)
Ratan Gupta8441a392017-05-05 21:42:53 +0530116 {
Ratan Gupta6a98e182017-06-06 15:04:23 +0530117 commit<InternalFailure>();
Ratan Gupta8441a392017-05-05 21:42:53 +0530118 rc = -1;
119 }
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -0500120 return rc;
121}
Ratan Guptadc50ce52017-05-31 15:47:55 +0530122
123/*
124 * write_flash() - Write to the virtual pnor from a provided buffer
125 * @context: The mbox context pointer
126 * @offset: The flash offset to write to (bytes)
127 * @buf: The buffer to write from (must be of atleast size)
128 * @size: The number of bytes to write
129 *
130 * Return: 0 on success otherwise negative error code
131 */
132
133int write_flash(struct mbox_context* context, uint32_t offset, void* buf,
134 uint32_t count)
135{
136 using namespace phosphor::logging;
137 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
138 using namespace std::string_literals;
139
140 int rc = 0;
141 MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count, buf);
142 try
143 {
144 openpower::virtual_pnor::RWRequest rwRequest;
145 auto partitionInfo = rwRequest.getPartitionInfo(context, offset);
146
147
148 auto mapped_mem = mmap(NULL, partitionInfo->data.actual,
149 PROT_READ | PROT_WRITE,
150 MAP_SHARED, rwRequest.fd(), 0);
151 if (mapped_mem == MAP_FAILED)
152 {
153 MSG_ERR("Failed to map partition=%s:Error=%s\n",
154 partitionInfo->data.name, strerror(errno));
155
156 elog<InternalFailure>();
157 }
158 //copy to the mapped memory.
159
160 uint32_t baseOffset = partitionInfo->data.base << context->block_size_shift;
161
162 // if the asked offset + no of bytes to write is greater
163 // then size of the partition file then throw error.
164 if ((offset + count) > (baseOffset + partitionInfo->data.actual))
165 {
166 MSG_ERR("Offset is beyond the partition file length[0x%.8x]\n",
167 partitionInfo->data.actual);
168 munmap(mapped_mem, partitionInfo->data.actual);
169 elog<InternalFailure>();
170 }
171
172 auto diffOffset = offset - baseOffset;
173 memcpy((char*)mapped_mem + diffOffset , buf, count);
174 munmap(mapped_mem, partitionInfo->data.actual);
175
176 set_flash_bytemap(context, offset, count, FLASH_DIRTY);
177 }
178 catch (InternalFailure & e)
179 {
180 rc = -1;
181 }
182 return rc;
183}