blob: 9a8215124b5c763be3b0da95f31690294f0de7a0 [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
Andrew Jeffery71eaa732018-08-08 16:44:24 +09303extern "C" {
4#include "flash.h"
5}
6
William A. Kennington IIId5f1d402018-10-11 13:55:04 -07007#include "config.h"
8
Andrew Jeffery2ceba892018-02-28 17:44:54 +10309#include "pnor_partition_table.hpp"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070010#include "xyz/openbmc_project/Common/error.hpp"
11
12#include <experimental/filesystem>
13#include <phosphor-logging/elog-errors.hpp>
14
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050015#include "common.h"
Andrew Jeffery26558db2018-08-10 00:22:38 +093016#include "mboxd.h"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070017#include "mboxd_pnor_partition_table.h"
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050018
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070019int init_vpnor(struct mbox_context* context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050020{
Ratan Gupta3214b512017-05-11 08:58:19 +053021 if (context && !context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050022 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103023 int rc;
24
Andrew Jefferye4cf6ac2018-03-02 09:05:01 +103025 strncpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
26 context->paths.ro_loc[PATH_MAX - 1] = '\0';
27 strncpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
28 context->paths.rw_loc[PATH_MAX - 1] = '\0';
29 strncpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
30 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
31 strncpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
32 context->paths.prsv_loc[PATH_MAX - 1] = '\0';
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050033
Andrew Jeffery742a1f62018-03-02 09:26:03 +103034 rc = init_vpnor_from_paths(context);
Andrew Jefferyf96bd162018-02-26 13:05:00 +103035 if (rc < 0)
Andrew Jeffery742a1f62018-03-02 09:26:03 +103036 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103037 return rc;
Andrew Jeffery742a1f62018-03-02 09:26:03 +103038 }
Ratan Gupta3214b512017-05-11 08:58:19 +053039 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103040
41 return 0;
Ratan Gupta3214b512017-05-11 08:58:19 +053042}
43
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070044int init_vpnor_from_paths(struct mbox_context* context)
Ratan Gupta3214b512017-05-11 08:58:19 +053045{
Andrew Jefferyf96bd162018-02-26 13:05:00 +103046 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
47 namespace fs = std::experimental::filesystem;
48 namespace vpnor = openpower::virtual_pnor;
Ratan Gupta3214b512017-05-11 08:58:19 +053049
50 if (context && !context->vpnor)
51 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103052 try
53 {
54 context->vpnor = new vpnor_partition_table;
55 context->vpnor->table =
Andrew Jeffery742a1f62018-03-02 09:26:03 +103056 new openpower::virtual_pnor::partition::Table(context);
Andrew Jefferyf96bd162018-02-26 13:05:00 +103057 }
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070058 catch (vpnor::TocEntryError& e)
Andrew Jefferyf96bd162018-02-26 13:05:00 +103059 {
60 MSG_ERR("%s\n", e.what());
61 phosphor::logging::commit<err::InternalFailure>();
Andrew Jeffery8eab2152018-08-09 23:47:29 +093062 return -EINVAL;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103063 }
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050064 }
Andrew Jefferyf96bd162018-02-26 13:05:00 +103065
66 return 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050067}
68
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070069int vpnor_copy_bootloader_partition(const struct mbox_context* context)
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050070{
71 // The hostboot bootloader has certain size/offset assumptions, so
72 // we need a special partition table here.
73 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
74 // 4K, the page size is 4K.
75 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
76 // offset, and first looks for the TOC here, before proceeding to move up
77 // page by page looking for the TOC. So it is optimal to place the TOC at
78 // this offset.
79 constexpr size_t eraseSize = 0x1000;
80 constexpr size_t pageSize = 0x1000;
81 constexpr size_t pnorSize = 0x4000000;
82 constexpr size_t tocMaxSize = 0x8000;
83 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
84 constexpr auto blPartitionName = "HBB";
Andrew Jefferyf96bd162018-02-26 13:05:00 +103085
86 namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103087 namespace fs = std::experimental::filesystem;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103088 namespace vpnor = openpower::virtual_pnor;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050089
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050090 try
91 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +103092 vpnor_partition_table vtbl{};
Andrew Jeffery742a1f62018-03-02 09:26:03 +103093 struct mbox_context local = *context;
Andrew Jefferyf96bd162018-02-26 13:05:00 +103094 local.vpnor = &vtbl;
95 local.block_size_shift = log_2(eraseSize);
Andrew Jeffery742a1f62018-03-02 09:26:03 +103096
97 openpower::virtual_pnor::partition::Table blTable(&local);
98
99 vtbl.table = &blTable;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030100
101 size_t tocOffset = 0;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030102
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500103 // Copy TOC
Andrew Jefferye0cdd3e2018-08-08 16:51:44 +0930104 flash_copy(&local, tocOffset,
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700105 static_cast<uint8_t*>(context->mem) + tocStart,
Andrew Jeffery7f9c3432018-03-01 12:07:13 +1030106 blTable.capacity());
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700107 const pnor_partition& partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500108 size_t hbbOffset = partition.data.base * eraseSize;
109 uint32_t hbbSize = partition.data.actual;
110 // Copy HBB
Andrew Jefferye0cdd3e2018-08-08 16:51:44 +0930111 flash_copy(&local, hbbOffset,
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700112 static_cast<uint8_t*>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500113 }
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700114 catch (err::InternalFailure& e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500115 {
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030116 phosphor::logging::commit<err::InternalFailure>();
Andrew Jeffery8eab2152018-08-09 23:47:29 +0930117 return -EIO;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500118 }
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700119 catch (vpnor::ReasonedError& e)
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030120 {
121 MSG_ERR("%s\n", e.what());
122 phosphor::logging::commit<err::InternalFailure>();
Andrew Jeffery8eab2152018-08-09 23:47:29 +0930123 return -EIO;
Andrew Jefferyf96bd162018-02-26 13:05:00 +1030124 }
125
126 return 0;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500127}
128
William A. Kennington IIId5f1d402018-10-11 13:55:04 -0700129void destroy_vpnor(struct mbox_context* context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500130{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030131 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500132 {
133 delete context->vpnor->table;
134 delete context->vpnor;
135 context->vpnor = nullptr;
136 }
137}