blob: c7154d662105d72e5bf2c96a689a32a29d1b092e [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}