blob: 394cc1839f901c0b8273d37088f0355dc95a0bca [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
William A. Kennington IIId5f1d402018-10-11 13:55:04 -07003#include "config.h"
4
Evan Lojewskif1e547c2019-03-14 14:34:33 +10305#include <assert.h>
6
7extern "C" {
8#include "backend.h"
9}
10
Andrew Jeffery2ceba892018-02-28 17:44:54 +103011#include "pnor_partition_table.hpp"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070012#include "xyz/openbmc_project/Common/error.hpp"
13
14#include <experimental/filesystem>
15#include <phosphor-logging/elog-errors.hpp>
16
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050017#include "common.h"
Andrew Jeffery26558db2018-08-10 00:22:38 +093018#include "mboxd.h"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070019#include "mboxd_pnor_partition_table.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050020
Evan Lojewskif1e547c2019-03-14 14:34:33 +103021void vpnor_default_paths(vpnor_partition_paths* paths)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050022{
Evan Lojewskif1e547c2019-03-14 14:34:33 +103023 strncpy(paths->ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
24 paths->ro_loc[PATH_MAX - 1] = '\0';
25 strncpy(paths->rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
26 paths->rw_loc[PATH_MAX - 1] = '\0';
27 strncpy(paths->prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
28 paths->prsv_loc[PATH_MAX - 1] = '\0';
29 strncpy(paths->patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
30 paths->prsv_loc[PATH_MAX - 1] = '\0';
Ratan Gupta3214b512017-05-11 08:58:19 +053031}
32
Evan Lojewskif1e547c2019-03-14 14:34:33 +103033int vpnor_init(struct backend* backend, const vpnor_partition_paths* paths)
Ratan Gupta3214b512017-05-11 08:58:19 +053034{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103035 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
36 namespace fs = std::experimental::filesystem;
37 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053038
Evan Lojewskif1e547c2019-03-14 14:34:33 +103039 if (!(backend && paths))
40 return -EINVAL;
41
42 vpnor_data* priv = new vpnor_data;
43 assert(priv);
44
45 priv->paths = *paths;
46 backend->priv = priv;
47
48 try
Ratan Gupta3214b512017-05-11 08:58:19 +053049 {
Evan Lojewskif1e547c2019-03-14 14:34:33 +103050 priv->vpnor = new vpnor_partition_table;
51 priv->vpnor->table =
52 new openpower::virtual_pnor::partition::Table(backend);
53 }
54 catch (vpnor::TocEntryError& e)
55 {
56 MSG_ERR("%s\n", e.what());
Andrew Jefferyf96bd162018-02-26 13:05:00 +103057 try
58 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103059 phosphor::logging::commit<err::InternalFailure>();
Andrew Jefferyf96bd162018-02-26 13:05:00 +103060 }
Evan Lojewskif1e547c2019-03-14 14:34:33 +103061 catch (const std::exception& e)
62 {
63 MSG_ERR("Failed to commit InternalFailure: %s\n", e.what());
64 }
65 return -EINVAL;
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
Evan Lojewskif1e547c2019-03-14 14:34:33 +103071int vpnor_copy_bootloader_partition(const struct backend* backend, void* buf,
72 uint32_t count)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050073{
74 // The hostboot bootloader has certain size/offset assumptions, so
75 // we need a special partition table here.
76 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
77 // 4K, the page size is 4K.
78 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
79 // offset, and first looks for the TOC here, before proceeding to move up
80 // page by page looking for the TOC. So it is optimal to place the TOC at
81 // this offset.
82 constexpr size_t eraseSize = 0x1000;
83 constexpr size_t pageSize = 0x1000;
84 constexpr size_t pnorSize = 0x4000000;
85 constexpr size_t tocMaxSize = 0x8000;
86 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
87 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +103088
89 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103090 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103091 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050092
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050093 try
94 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103095 vpnor_partition_table vtbl{};
Evan Lojewskif1e547c2019-03-14 14:34:33 +103096 struct vpnor_data priv;
97 struct backend local = *backend;
98
99 priv.vpnor = &vtbl;
100 priv.paths = ((struct vpnor_data*)backend->priv)->paths;
101 local.priv = &priv;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030102 local.block_size_shift = log_2(eraseSize);
Andrew Jeffery742a1f62018-03-02 09:26:03 +1030103
104 openpower::virtual_pnor::partition::Table blTable(&local);
105
106 vtbl.table = &blTable;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030107
108 size_t tocOffset = 0;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030109
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700110 const pnor_partition& partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500111 size_t hbbOffset = partition.data.base * eraseSize;
112 uint32_t hbbSize = partition.data.actual;
Andrew Jeffery4e75a272019-03-14 17:24:38 +1030113
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030114 if (count < tocStart + blTable.capacity() ||
115 count < hbbOffset + hbbSize)
Andrew Jeffery4e75a272019-03-14 17:24:38 +1030116 {
117 MSG_ERR("Reserved memory too small for dumb bootstrap\n");
118 return -EINVAL;
119 }
120
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030121 uint8_t* buf8 = static_cast<uint8_t*>(buf);
122 backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity());
123 backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500124 }
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700125 catch (err::InternalFailure& e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500126 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030127 phosphor::logging::commit<err::InternalFailure>();
Andrew Jeffery8eab2152018-08-09 23:47:29 +0930128 return -EIO;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500129 }
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700130 catch (vpnor::ReasonedError& e)
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030131 {
132 MSG_ERR("%s\n", e.what());
133 phosphor::logging::commit<err::InternalFailure>();
Andrew Jeffery8eab2152018-08-09 23:47:29 +0930134 return -EIO;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030135 }
136
137 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500138}
139
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030140void vpnor_destroy(struct backend* backend)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500141{
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030142 struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
143
144 if (priv)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500145 {
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030146 if (priv->vpnor)
147 {
148 delete priv->vpnor->table;
149 }
150 delete priv->vpnor;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500151 }
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030152 delete priv;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500153}