blob: 91b9880a2aa535af62d410647bf7d7f4ef534aa6 [file] [log] [blame]
Andrew Jefferyacee6832018-02-21 22:17:08 +10301/*
2 * Mailbox Daemon Window Helpers
3 *
4 * Copyright 2018 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 */
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050019#include "mboxd_pnor_partition_table.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050020#include "common.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050021#include "mbox.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050022#include "mboxd_flash.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050023#include "pnor_partition_table.hpp"
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050024#include "config.h"
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050025#include "xyz/openbmc_project/Common/error.hpp"
26#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta3214b512017-05-11 08:58:19 +053027#include <experimental/filesystem>
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050028
29struct vpnor_partition_table
30{
Andrew Jefferyf34db312018-03-09 15:27:03 +103031 openpower::virtual_pnor::partition::Table *table = nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050032};
33
Andrew Jefferyf96bd162018-02-26 13:05:00 +103034int init_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050035{
Ratan Gupta3214b512017-05-11 08:58:19 +053036 if (context && !context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050037 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103038 int rc;
39
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050040 strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
41 strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
42 strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050043 strcpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC);
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050044
Andrew Jefferyf96bd162018-02-26 13:05:00 +103045 rc = vpnor_create_partition_table_from_path(context,
46 PARTITION_FILES_RO_LOC);
47 if (rc < 0)
48 return rc;
Ratan Gupta3214b512017-05-11 08:58:19 +053049 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103050
51 return 0;
Ratan Gupta3214b512017-05-11 08:58:19 +053052}
53
Andrew Jefferyf96bd162018-02-26 13:05:00 +103054int vpnor_create_partition_table_from_path(struct mbox_context *context,
55 const char *path)
Ratan Gupta3214b512017-05-11 08:58:19 +053056{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103057 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
58 namespace fs = std::experimental::filesystem;
59 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053060
61 if (context && !context->vpnor)
62 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103063 fs::path dir(path);
64 try
65 {
66 context->vpnor = new vpnor_partition_table;
67 context->vpnor->table =
68 new openpower::virtual_pnor::partition::Table(
69 std::move(dir), 1 << context->erase_size_shift,
70 context->flash_size);
71 }
72 catch (vpnor::TocEntryError &e)
73 {
74 MSG_ERR("%s\n", e.what());
75 phosphor::logging::commit<err::InternalFailure>();
76 return -MBOX_R_SYSTEM_ERROR;
77 }
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050078 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103079
80 return 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050081}
82
83size_t vpnor_get_partition_table_size(const struct mbox_context *context)
84{
Andrew Jeffery7f9c3432018-03-01 12:07:13 +103085 return context && context->vpnor ? context->vpnor->table->blocks() : 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050086}
87
Andrew Jefferyf34db312018-03-09 15:27:03 +103088const struct pnor_partition_table *
89vpnor_get_partition_table(const struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050090{
Andrew Jefferyf34db312018-03-09 15:27:03 +103091 return context && context->vpnor ? &(context->vpnor->table->getHostTable())
92 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050093}
94
Andrew Jefferyf34db312018-03-09 15:27:03 +103095const struct pnor_partition *
96vpnor_get_partition(const struct mbox_context *context, const size_t offset)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050097{
Andrew Jefferyf34db312018-03-09 15:27:03 +103098 return context && context->vpnor
99 ? &(context->vpnor->table->partition(offset))
100 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500101}
102
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030103int vpnor_copy_bootloader_partition(const struct mbox_context *context)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500104{
105 // The hostboot bootloader has certain size/offset assumptions, so
106 // we need a special partition table here.
107 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
108 // 4K, the page size is 4K.
109 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
110 // offset, and first looks for the TOC here, before proceeding to move up
111 // page by page looking for the TOC. So it is optimal to place the TOC at
112 // this offset.
113 constexpr size_t eraseSize = 0x1000;
114 constexpr size_t pageSize = 0x1000;
115 constexpr size_t pnorSize = 0x4000000;
116 constexpr size_t tocMaxSize = 0x8000;
117 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
118 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030119
120 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +1030121 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030122 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500123
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500124 try
125 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030126 openpower::virtual_pnor::partition::Table blTable(
127 fs::path{PARTITION_FILES_RO_LOC}, eraseSize, pnorSize);
128
129 vpnor_partition_table vtbl{};
130 vtbl.table = &blTable;
131 struct mbox_context local
132 {
133 };
134 local.vpnor = &vtbl;
135 local.block_size_shift = log_2(eraseSize);
136 memcpy(&local.paths, &context->paths, sizeof(local.paths));
137
138 size_t tocOffset = 0;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030139
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500140 // Copy TOC
141 copy_flash(&local, tocOffset,
Andrew Jeffery7f9c3432018-03-01 12:07:13 +1030142 static_cast<uint8_t *>(context->mem) + tocStart,
143 blTable.capacity());
Andrew Jefferyf34db312018-03-09 15:27:03 +1030144 const pnor_partition &partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500145 size_t hbbOffset = partition.data.base * eraseSize;
146 uint32_t hbbSize = partition.data.actual;
147 // Copy HBB
148 copy_flash(&local, hbbOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030149 static_cast<uint8_t *>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500150 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030151 catch (err::InternalFailure &e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500152 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030153 phosphor::logging::commit<err::InternalFailure>();
154 return -MBOX_R_SYSTEM_ERROR;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500155 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030156 catch (vpnor::TocEntryError &e)
157 {
158 MSG_ERR("%s\n", e.what());
159 phosphor::logging::commit<err::InternalFailure>();
160 return -MBOX_R_SYSTEM_ERROR;
161 }
162
163 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500164}
165
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500166void destroy_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500167{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030168 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500169 {
170 delete context->vpnor->table;
171 delete context->vpnor;
172 context->vpnor = nullptr;
173 }
174}