blob: 1756516aebaaf79649c22933dbc79c7202eb7cd9 [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"
Andrew Jeffery2ceba892018-02-28 17:44:54 +10304#include "pnor_partition_table.hpp"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05005#include "common.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05006#include "mbox.h"
Deepak Kodihalli017e45c2017-07-12 01:06:30 -05007#include "mboxd_flash.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -05008#include "pnor_partition_table.hpp"
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -05009#include "config.h"
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050010#include "xyz/openbmc_project/Common/error.hpp"
11#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta3214b512017-05-11 08:58:19 +053012#include <experimental/filesystem>
Andrew Jeffery943aba02018-03-26 15:37:33 +103013#include "vpnor/mboxd_msg.hpp"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050014
Andrew Jefferyf96bd162018-02-26 13:05:00 +103015int init_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050016{
Ratan Gupta3214b512017-05-11 08:58:19 +053017 if (context && !context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050018 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103019 int rc;
20
Andrew Jefferye4cf6ac2018-03-02 09:05:01 +103021 strncpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
22 context->paths.ro_loc[PATH_MAX - 1] = '\0';
23 strncpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
24 context->paths.rw_loc[PATH_MAX - 1] = '\0';
25 strncpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
26 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
27 strncpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
28 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050029
Andrew Jeffery742a1f62018-03-02 09:26:03 +103030 rc = init_vpnor_from_paths(context);
Andrew Jefferyf96bd162018-02-26 13:05:00 +103031 if (rc < 0)
Andrew Jeffery742a1f62018-03-02 09:26:03 +103032 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103033 return rc;
Andrew Jeffery742a1f62018-03-02 09:26:03 +103034 }
Ratan Gupta3214b512017-05-11 08:58:19 +053035 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103036
37 return 0;
Ratan Gupta3214b512017-05-11 08:58:19 +053038}
39
Andrew Jeffery742a1f62018-03-02 09:26:03 +103040int init_vpnor_from_paths(struct mbox_context *context)
Ratan Gupta3214b512017-05-11 08:58:19 +053041{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103042 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
43 namespace fs = std::experimental::filesystem;
44 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053045
46 if (context && !context->vpnor)
47 {
Andrew Jeffery943aba02018-03-26 15:37:33 +103048 context->handlers = vpnor_mbox_handlers;
49
Andrew Jefferyf96bd162018-02-26 13:05:00 +103050 try
51 {
52 context->vpnor = new vpnor_partition_table;
53 context->vpnor->table =
Andrew Jeffery742a1f62018-03-02 09:26:03 +103054 new openpower::virtual_pnor::partition::Table(context);
Andrew Jefferyf96bd162018-02-26 13:05:00 +103055 }
56 catch (vpnor::TocEntryError &e)
57 {
58 MSG_ERR("%s\n", e.what());
59 phosphor::logging::commit<err::InternalFailure>();
60 return -MBOX_R_SYSTEM_ERROR;
61 }
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050062 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103063
64 return 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050065}
66
Andrew Jefferyf96bd162018-02-26 13:05:00 +103067int vpnor_copy_bootloader_partition(const struct mbox_context *context)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050068{
69 // The hostboot bootloader has certain size/offset assumptions, so
70 // we need a special partition table here.
71 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
72 // 4K, the page size is 4K.
73 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
74 // offset, and first looks for the TOC here, before proceeding to move up
75 // page by page looking for the TOC. So it is optimal to place the TOC at
76 // this offset.
77 constexpr size_t eraseSize = 0x1000;
78 constexpr size_t pageSize = 0x1000;
79 constexpr size_t pnorSize = 0x4000000;
80 constexpr size_t tocMaxSize = 0x8000;
81 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
82 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +103083
84 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103085 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103086 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050087
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050088 try
89 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103090 vpnor_partition_table vtbl{};
Andrew Jeffery742a1f62018-03-02 09:26:03 +103091 struct mbox_context local = *context;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103092 local.vpnor = &vtbl;
93 local.block_size_shift = log_2(eraseSize);
Andrew Jeffery742a1f62018-03-02 09:26:03 +103094
95 openpower::virtual_pnor::partition::Table blTable(&local);
96
97 vtbl.table = &blTable;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103098
99 size_t tocOffset = 0;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030100
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500101 // Copy TOC
102 copy_flash(&local, tocOffset,
Andrew Jeffery7f9c3432018-03-01 12:07:13 +1030103 static_cast<uint8_t *>(context->mem) + tocStart,
104 blTable.capacity());
Andrew Jefferyf34db312018-03-09 15:27:03 +1030105 const pnor_partition &partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500106 size_t hbbOffset = partition.data.base * eraseSize;
107 uint32_t hbbSize = partition.data.actual;
108 // Copy HBB
109 copy_flash(&local, hbbOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030110 static_cast<uint8_t *>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500111 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030112 catch (err::InternalFailure &e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500113 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030114 phosphor::logging::commit<err::InternalFailure>();
115 return -MBOX_R_SYSTEM_ERROR;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500116 }
Andrew Jeffery8fe809e2018-05-17 09:54:32 +0930117 catch (vpnor::ReasonedError &e)
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030118 {
119 MSG_ERR("%s\n", e.what());
120 phosphor::logging::commit<err::InternalFailure>();
121 return -MBOX_R_SYSTEM_ERROR;
122 }
123
124 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500125}
126
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500127void destroy_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500128{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030129 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500130 {
131 delete context->vpnor->table;
132 delete context->vpnor;
133 context->vpnor = nullptr;
134 }
135}