blob: 49afeb045a01fd087119942b24838a92280ff31e [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05003#include "mboxd_pnor_partition_table.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05004#include "common.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05005#include "mbox.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05006#include "mboxd_flash.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05007#include "pnor_partition_table.hpp"
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -05008#include "config.h"
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -05009#include "xyz/openbmc_project/Common/error.hpp"
10#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta3214b512017-05-11 08:58:19 +053011#include <experimental/filesystem>
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050012
13struct vpnor_partition_table
14{
Andrew Jefferyf34db312018-03-09 15:27:03 +103015 openpower::virtual_pnor::partition::Table *table = nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050016};
17
Andrew Jefferyf96bd162018-02-26 13:05:00 +103018int init_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050019{
Ratan Gupta3214b512017-05-11 08:58:19 +053020 if (context && !context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050021 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103022 int rc;
23
Andrew Jefferye4cf6ac2018-03-02 09:05:01 +103024 strncpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
25 context->paths.ro_loc[PATH_MAX - 1] = '\0';
26 strncpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
27 context->paths.rw_loc[PATH_MAX - 1] = '\0';
28 strncpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
29 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
30 strncpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
31 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050032
Andrew Jefferyf96bd162018-02-26 13:05:00 +103033 rc = vpnor_create_partition_table_from_path(context,
34 PARTITION_FILES_RO_LOC);
35 if (rc < 0)
36 return rc;
Ratan Gupta3214b512017-05-11 08:58:19 +053037 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103038
39 return 0;
Ratan Gupta3214b512017-05-11 08:58:19 +053040}
41
Andrew Jefferyf96bd162018-02-26 13:05:00 +103042int vpnor_create_partition_table_from_path(struct mbox_context *context,
43 const char *path)
Ratan Gupta3214b512017-05-11 08:58:19 +053044{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103045 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
46 namespace fs = std::experimental::filesystem;
47 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053048
49 if (context && !context->vpnor)
50 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103051 fs::path dir(path);
52 try
53 {
54 context->vpnor = new vpnor_partition_table;
55 context->vpnor->table =
56 new openpower::virtual_pnor::partition::Table(
57 std::move(dir), 1 << context->erase_size_shift,
58 context->flash_size);
59 }
60 catch (vpnor::TocEntryError &e)
61 {
62 MSG_ERR("%s\n", e.what());
63 phosphor::logging::commit<err::InternalFailure>();
64 return -MBOX_R_SYSTEM_ERROR;
65 }
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050066 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103067
68 return 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050069}
70
71size_t vpnor_get_partition_table_size(const struct mbox_context *context)
72{
Andrew Jeffery7f9c3432018-03-01 12:07:13 +103073 return context && context->vpnor ? context->vpnor->table->blocks() : 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050074}
75
Andrew Jefferyf34db312018-03-09 15:27:03 +103076const struct pnor_partition_table *
77vpnor_get_partition_table(const struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050078{
Andrew Jefferyf34db312018-03-09 15:27:03 +103079 return context && context->vpnor ? &(context->vpnor->table->getHostTable())
80 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050081}
82
Andrew Jefferyf34db312018-03-09 15:27:03 +103083const struct pnor_partition *
84vpnor_get_partition(const struct mbox_context *context, const size_t offset)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050085{
Andrew Jefferyf34db312018-03-09 15:27:03 +103086 return context && context->vpnor
87 ? &(context->vpnor->table->partition(offset))
88 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050089}
90
Andrew Jefferyf96bd162018-02-26 13:05:00 +103091int vpnor_copy_bootloader_partition(const struct mbox_context *context)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050092{
93 // The hostboot bootloader has certain size/offset assumptions, so
94 // we need a special partition table here.
95 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
96 // 4K, the page size is 4K.
97 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
98 // offset, and first looks for the TOC here, before proceeding to move up
99 // page by page looking for the TOC. So it is optimal to place the TOC at
100 // this offset.
101 constexpr size_t eraseSize = 0x1000;
102 constexpr size_t pageSize = 0x1000;
103 constexpr size_t pnorSize = 0x4000000;
104 constexpr size_t tocMaxSize = 0x8000;
105 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
106 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030107
108 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +1030109 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030110 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500111
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500112 try
113 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030114 openpower::virtual_pnor::partition::Table blTable(
115 fs::path{PARTITION_FILES_RO_LOC}, eraseSize, pnorSize);
116
117 vpnor_partition_table vtbl{};
118 vtbl.table = &blTable;
119 struct mbox_context local
120 {
121 };
122 local.vpnor = &vtbl;
123 local.block_size_shift = log_2(eraseSize);
124 memcpy(&local.paths, &context->paths, sizeof(local.paths));
125
126 size_t tocOffset = 0;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030127
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500128 // Copy TOC
129 copy_flash(&local, tocOffset,
Andrew Jeffery7f9c3432018-03-01 12:07:13 +1030130 static_cast<uint8_t *>(context->mem) + tocStart,
131 blTable.capacity());
Andrew Jefferyf34db312018-03-09 15:27:03 +1030132 const pnor_partition &partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500133 size_t hbbOffset = partition.data.base * eraseSize;
134 uint32_t hbbSize = partition.data.actual;
135 // Copy HBB
136 copy_flash(&local, hbbOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030137 static_cast<uint8_t *>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500138 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030139 catch (err::InternalFailure &e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500140 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030141 phosphor::logging::commit<err::InternalFailure>();
142 return -MBOX_R_SYSTEM_ERROR;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500143 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030144 catch (vpnor::TocEntryError &e)
145 {
146 MSG_ERR("%s\n", e.what());
147 phosphor::logging::commit<err::InternalFailure>();
148 return -MBOX_R_SYSTEM_ERROR;
149 }
150
151 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500152}
153
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500154void destroy_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500155{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030156 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500157 {
158 delete context->vpnor->table;
159 delete context->vpnor;
160 context->vpnor = nullptr;
161 }
162}