blob: 40d2ea6f4800ca5b1d3a6f8f9a5826da9680ff9b [file] [log] [blame]
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05001#include "mboxd_pnor_partition_table.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05002#include "common.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05003#include "mbox.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05004#include "mboxd_flash.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05005#include "pnor_partition_table.hpp"
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -05006#include "config.h"
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -05007#include "xyz/openbmc_project/Common/error.hpp"
8#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta3214b512017-05-11 08:58:19 +05309#include <experimental/filesystem>
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050010
11struct vpnor_partition_table
12{
Andrew Jefferyf34db312018-03-09 15:27:03 +103013 openpower::virtual_pnor::partition::Table *table = nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050014};
15
Andrew Jefferyf96bd162018-02-26 13:05:00 +103016int init_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050017{
Ratan Gupta3214b512017-05-11 08:58:19 +053018 if (context && !context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050019 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103020 int rc;
21
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050022 strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
23 strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
24 strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050025 strcpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC);
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050026
Andrew Jefferyf96bd162018-02-26 13:05:00 +103027 rc = vpnor_create_partition_table_from_path(context,
28 PARTITION_FILES_RO_LOC);
29 if (rc < 0)
30 return rc;
Ratan Gupta3214b512017-05-11 08:58:19 +053031 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103032
33 return 0;
Ratan Gupta3214b512017-05-11 08:58:19 +053034}
35
Andrew Jefferyf96bd162018-02-26 13:05:00 +103036int vpnor_create_partition_table_from_path(struct mbox_context *context,
37 const char *path)
Ratan Gupta3214b512017-05-11 08:58:19 +053038{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103039 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
40 namespace fs = std::experimental::filesystem;
41 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053042
43 if (context && !context->vpnor)
44 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103045 fs::path dir(path);
46 try
47 {
48 context->vpnor = new vpnor_partition_table;
49 context->vpnor->table =
50 new openpower::virtual_pnor::partition::Table(
51 std::move(dir), 1 << context->erase_size_shift,
52 context->flash_size);
53 }
54 catch (vpnor::TocEntryError &e)
55 {
56 MSG_ERR("%s\n", e.what());
57 phosphor::logging::commit<err::InternalFailure>();
58 return -MBOX_R_SYSTEM_ERROR;
59 }
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050060 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103061
62 return 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050063}
64
65size_t vpnor_get_partition_table_size(const struct mbox_context *context)
66{
Andrew Jefferyf34db312018-03-09 15:27:03 +103067 return context && context->vpnor ? context->vpnor->table->size() : 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050068}
69
Andrew Jefferyf34db312018-03-09 15:27:03 +103070const struct pnor_partition_table *
71vpnor_get_partition_table(const struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050072{
Andrew Jefferyf34db312018-03-09 15:27:03 +103073 return context && context->vpnor ? &(context->vpnor->table->getHostTable())
74 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050075}
76
Andrew Jefferyf34db312018-03-09 15:27:03 +103077const struct pnor_partition *
78vpnor_get_partition(const struct mbox_context *context, const size_t offset)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050079{
Andrew Jefferyf34db312018-03-09 15:27:03 +103080 return context && context->vpnor
81 ? &(context->vpnor->table->partition(offset))
82 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050083}
84
Andrew Jefferyf96bd162018-02-26 13:05:00 +103085int vpnor_copy_bootloader_partition(const struct mbox_context *context)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050086{
87 // The hostboot bootloader has certain size/offset assumptions, so
88 // we need a special partition table here.
89 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
90 // 4K, the page size is 4K.
91 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
92 // offset, and first looks for the TOC here, before proceeding to move up
93 // page by page looking for the TOC. So it is optimal to place the TOC at
94 // this offset.
95 constexpr size_t eraseSize = 0x1000;
96 constexpr size_t pageSize = 0x1000;
97 constexpr size_t pnorSize = 0x4000000;
98 constexpr size_t tocMaxSize = 0x8000;
99 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
100 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030101
102 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +1030103 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030104 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500105
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500106 try
107 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030108 openpower::virtual_pnor::partition::Table blTable(
109 fs::path{PARTITION_FILES_RO_LOC}, eraseSize, pnorSize);
110
111 vpnor_partition_table vtbl{};
112 vtbl.table = &blTable;
113 struct mbox_context local
114 {
115 };
116 local.vpnor = &vtbl;
117 local.block_size_shift = log_2(eraseSize);
118 memcpy(&local.paths, &context->paths, sizeof(local.paths));
119
120 size_t tocOffset = 0;
121 uint32_t tocSize = blTable.size() * eraseSize;
122
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500123 // Copy TOC
124 copy_flash(&local, tocOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030125 static_cast<uint8_t *>(context->mem) + tocStart, tocSize);
126 const pnor_partition &partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500127 size_t hbbOffset = partition.data.base * eraseSize;
128 uint32_t hbbSize = partition.data.actual;
129 // Copy HBB
130 copy_flash(&local, hbbOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030131 static_cast<uint8_t *>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500132 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030133 catch (err::InternalFailure &e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500134 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030135 phosphor::logging::commit<err::InternalFailure>();
136 return -MBOX_R_SYSTEM_ERROR;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500137 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030138 catch (vpnor::TocEntryError &e)
139 {
140 MSG_ERR("%s\n", e.what());
141 phosphor::logging::commit<err::InternalFailure>();
142 return -MBOX_R_SYSTEM_ERROR;
143 }
144
145 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500146}
147
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500148void destroy_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500149{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030150 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500151 {
152 delete context->vpnor->table;
153 delete context->vpnor;
154 context->vpnor = nullptr;
155 }
156}