blob: 84a03142032afed11a82739da23c713a492d6f74 [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
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050016void 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 {
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050020 strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
21 strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
22 strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050023 strcpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC);
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -050024
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103025 vpnor_create_partition_table_from_path(context, PARTITION_FILES_RO_LOC);
Ratan Gupta3214b512017-05-11 08:58:19 +053026 }
27}
28
29void vpnor_create_partition_table_from_path(struct mbox_context *context,
30 const char *path)
31{
32 std::experimental::filesystem::path dir(path);
33
34 if (context && !context->vpnor)
35 {
36 context->vpnor = new vpnor_partition_table;
Andrew Jefferyf34db312018-03-09 15:27:03 +103037 context->vpnor->table = new openpower::virtual_pnor::partition::Table(
38 std::move(dir), 1 << context->erase_size_shift,
39 context->flash_size);
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050040 }
41}
42
43size_t vpnor_get_partition_table_size(const struct mbox_context *context)
44{
Andrew Jefferyf34db312018-03-09 15:27:03 +103045 return context && context->vpnor ? context->vpnor->table->size() : 0;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050046}
47
Andrew Jefferyf34db312018-03-09 15:27:03 +103048const struct pnor_partition_table *
49vpnor_get_partition_table(const struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050050{
Andrew Jefferyf34db312018-03-09 15:27:03 +103051 return context && context->vpnor ? &(context->vpnor->table->getHostTable())
52 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050053}
54
Andrew Jefferyf34db312018-03-09 15:27:03 +103055const struct pnor_partition *
56vpnor_get_partition(const struct mbox_context *context, const size_t offset)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050057{
Andrew Jefferyf34db312018-03-09 15:27:03 +103058 return context && context->vpnor
59 ? &(context->vpnor->table->partition(offset))
60 : nullptr;
Deepak Kodihallib6a446f2017-04-29 13:01:49 -050061}
62
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050063void vpnor_copy_bootloader_partition(const struct mbox_context *context)
64{
65 // The hostboot bootloader has certain size/offset assumptions, so
66 // we need a special partition table here.
67 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is
68 // 4K, the page size is 4K.
69 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size'
70 // offset, and first looks for the TOC here, before proceeding to move up
71 // page by page looking for the TOC. So it is optimal to place the TOC at
72 // this offset.
73 constexpr size_t eraseSize = 0x1000;
74 constexpr size_t pageSize = 0x1000;
75 constexpr size_t pnorSize = 0x4000000;
76 constexpr size_t tocMaxSize = 0x8000;
77 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize;
78 constexpr auto blPartitionName = "HBB";
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103079 namespace fs = std::experimental::filesystem;
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050080
Andrew Jefferyd976c9c2018-02-27 14:56:07 +103081 openpower::virtual_pnor::partition::Table blTable(
82 fs::path{PARTITION_FILES_RO_LOC}, eraseSize, pnorSize);
83
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050084 vpnor_partition_table vtbl{};
85 vtbl.table = &blTable;
Andrew Jefferyf34db312018-03-09 15:27:03 +103086 struct mbox_context local
87 {
88 };
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050089 local.vpnor = &vtbl;
90 local.block_size_shift = log_2(eraseSize);
91 memcpy(&local.paths, &context->paths, sizeof(local.paths));
92
93 size_t tocOffset = 0;
Deepak Kodihalli7ee307c2017-07-12 03:41:08 -050094 uint32_t tocSize = blTable.size() * eraseSize;
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -050095 using namespace phosphor::logging;
96 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
97 try
98 {
99 // Copy TOC
100 copy_flash(&local, tocOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030101 static_cast<uint8_t *>(context->mem) + tocStart, tocSize);
102 const pnor_partition &partition = blTable.partition(blPartitionName);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500103 size_t hbbOffset = partition.data.base * eraseSize;
104 uint32_t hbbSize = partition.data.actual;
105 // Copy HBB
106 copy_flash(&local, hbbOffset,
Andrew Jefferyf34db312018-03-09 15:27:03 +1030107 static_cast<uint8_t *>(context->mem) + hbbOffset, hbbSize);
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500108 }
Andrew Jefferyf34db312018-03-09 15:27:03 +1030109 catch (InternalFailure &e)
Deepak Kodihalli6e6aa3a2017-08-28 06:13:43 -0500110 {
111 commit<InternalFailure>();
112 }
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500113}
114
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500115void destroy_vpnor(struct mbox_context *context)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500116{
Andrew Jefferyf34db312018-03-09 15:27:03 +1030117 if (context && context->vpnor)
Deepak Kodihallib6a446f2017-04-29 13:01:49 -0500118 {
119 delete context->vpnor->table;
120 delete context->vpnor;
121 context->vpnor = nullptr;
122 }
123}