diff --git a/vpnor/Makefile.am.include b/vpnor/Makefile.am.include index d69a94beeec5cfaeaa4bbd8dcc1cd6663674f742..188e69f9ba73fe4414631b8c68dd8bf8224c58e6 100644 --- a/vpnor/Makefile.am.include +++ b/vpnor/Makefile.am.include @@ -1,5 +1,4 @@ mboxd_SOURCES += %reldir%/pnor_partition_table.cpp \ - %reldir%/mboxd_pnor_partition_table.cpp \ %reldir%/backend.cpp \ %reldir%/pnor_partition.cpp diff --git a/vpnor/backend.cpp b/vpnor/backend.cpp index 06aed57f03b75416b6b2d2714c29fb0129466aee..006104f1e8e62a1bec0aa4f25194868b64d8964c 100644 --- a/vpnor/backend.cpp +++ b/vpnor/backend.cpp @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (C) 2018 IBM Corp. +#include "config.h" + #include #include #include @@ -12,19 +14,21 @@ #include extern "C" { +#include "backend.h" #include "common.h" #include "lpc.h" #include "mboxd.h" #include "protocol.h" +#include "vpnor/backend.h" } -#include "config.h" - #include "pnor_partition.hpp" #include "pnor_partition_table.hpp" #include "xyz/openbmc_project/Common/error.hpp" +#include #include +#include #include #include #include @@ -39,6 +43,143 @@ namespace vpnor = openpower::virtual_pnor; static constexpr uint32_t VPNOR_ERASE_SIZE = 4 * 1024; +void vpnor_default_paths(vpnor_partition_paths* paths) +{ + strncpy(paths->ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX); + paths->ro_loc[PATH_MAX - 1] = '\0'; + strncpy(paths->rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX); + paths->rw_loc[PATH_MAX - 1] = '\0'; + strncpy(paths->prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX); + paths->prsv_loc[PATH_MAX - 1] = '\0'; + strncpy(paths->patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX); + paths->prsv_loc[PATH_MAX - 1] = '\0'; +} + +/** @brief Create a virtual PNOR partition table. + * + * @param[in] backend - The backend context pointer + * @param[in] paths - A paths object pointer to initialise vpnor + * + * This API should be called before calling any other APIs below. If a table + * already exists, this function will not do anything further. This function + * will not do anything if the context is NULL. + * + * The content of the paths object is copied out, ownership is retained by the + * caller. + * + * Returns 0 if the call succeeds, else a negative error code. + */ +static int vpnor_init(struct backend* backend, + const vpnor_partition_paths* paths) +{ + namespace err = sdbusplus::xyz::openbmc_project::Common::Error; + namespace fs = std::experimental::filesystem; + namespace vpnor = openpower::virtual_pnor; + + vpnor_data* priv = new vpnor_data; + assert(priv); + + priv->paths = *paths; + backend->priv = priv; + + try + { + priv->vpnor = new vpnor_partition_table; + priv->vpnor->table = + new openpower::virtual_pnor::partition::Table(backend); + } + catch (vpnor::TocEntryError& e) + { + MSG_ERR("%s\n", e.what()); + try + { + phosphor::logging::commit(); + } + catch (const std::exception& e) + { + MSG_ERR("Failed to commit InternalFailure: %s\n", e.what()); + } + return -EINVAL; + } + + return 0; +} + +/** @brief Copy bootloader partition (alongwith TOC) to LPC memory + * + * @param[in] backend - The backend context pointer + * + * @returns 0 on success, negative error code on failure + */ +int vpnor_copy_bootloader_partition(const struct backend* backend, void* buf, + uint32_t count) +{ + // The hostboot bootloader has certain size/offset assumptions, so + // we need a special partition table here. + // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is + // 4K, the page size is 4K. + // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size' + // offset, and first looks for the TOC here, before proceeding to move up + // page by page looking for the TOC. So it is optimal to place the TOC at + // this offset. + constexpr size_t eraseSize = 0x1000; + constexpr size_t pageSize = 0x1000; + constexpr size_t pnorSize = 0x4000000; + constexpr size_t tocMaxSize = 0x8000; + constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize; + constexpr auto blPartitionName = "HBB"; + + namespace err = sdbusplus::xyz::openbmc_project::Common::Error; + namespace fs = std::experimental::filesystem; + namespace vpnor = openpower::virtual_pnor; + + try + { + vpnor_partition_table vtbl{}; + struct vpnor_data priv; + struct backend local = *backend; + + priv.vpnor = &vtbl; + priv.paths = ((struct vpnor_data*)backend->priv)->paths; + local.priv = &priv; + local.block_size_shift = log_2(eraseSize); + + openpower::virtual_pnor::partition::Table blTable(&local); + + vtbl.table = &blTable; + + size_t tocOffset = 0; + + const pnor_partition& partition = blTable.partition(blPartitionName); + size_t hbbOffset = partition.data.base * eraseSize; + uint32_t hbbSize = partition.data.actual; + + if (count < tocStart + blTable.capacity() || + count < hbbOffset + hbbSize) + { + MSG_ERR("Reserved memory too small for dumb bootstrap\n"); + return -EINVAL; + } + + uint8_t* buf8 = static_cast(buf); + backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity()); + backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize); + } + catch (err::InternalFailure& e) + { + phosphor::logging::commit(); + return -EIO; + } + catch (vpnor::ReasonedError& e) + { + MSG_ERR("%s\n", e.what()); + phosphor::logging::commit(); + return -EIO; + } + + return 0; +} + int vpnor_dev_init(struct backend* backend, void* data) { vpnor_partition_paths* paths = (vpnor_partition_paths*)data; @@ -111,7 +252,17 @@ cleanup_filename: static void vpnor_free(struct backend* backend) { - vpnor_destroy(backend); + struct vpnor_data* priv = (struct vpnor_data*)backend->priv; + + if (priv) + { + if (priv->vpnor) + { + delete priv->vpnor->table; + } + delete priv->vpnor; + } + delete priv; } /* @@ -298,7 +449,7 @@ static int vpnor_reset(struct backend* backend, void* buf, uint32_t count) vpnor_partition_paths paths = priv->paths; - vpnor_destroy(backend); + vpnor_free(backend); rc = vpnor_init(backend, &paths); if (rc < 0) diff --git a/vpnor/backend.h b/vpnor/backend.h index b76aa98e1f320a7cf870b7d7f4764abc41101b20..010223842fd50b9fd5168119aa230d4bc9fd0d38 100644 --- a/vpnor/backend.h +++ b/vpnor/backend.h @@ -3,8 +3,6 @@ #pragma once #include -#include "pnor_partition_defs.h" -#include "backend.h" struct mbox_context; struct vpnor_partition_table; @@ -41,42 +39,6 @@ static inline void vpnor_default_paths(struct vpnor_partition_paths *paths) } #endif -#ifdef VIRTUAL_PNOR_ENABLED -/** @brief Create a virtual PNOR partition table. - * - * @param[in] backend - The backend context pointer - * @param[in] paths - A paths object pointer to initialise vpnor - * - * This API should be called before calling any other APIs below. If a table - * already exists, this function will not do anything further. This function - * will not do anything if the context is NULL. - * - * The content of the paths object is copied out, ownership is retained by the - * caller. - * - * Returns 0 if the call succeeds, else a negative error code. - */ - -int vpnor_init(struct backend *backend, - const struct vpnor_partition_paths *paths); - -/** @brief Copy bootloader partition (alongwith TOC) to LPC memory - * - * @param[in] backend - The backend context pointer - * - * @returns 0 on success, negative error code on failure - */ -int vpnor_copy_bootloader_partition(const struct backend *backend, void *buf, - uint32_t count); - -/** @brief Destroy partition table, if it exists. - * - * @param[in] backend - The backend context pointer - */ -void vpnor_destroy(struct backend *backend); - #ifdef __cplusplus } #endif - -#endif diff --git a/vpnor/mboxd_pnor_partition_table.cpp b/vpnor/mboxd_pnor_partition_table.cpp deleted file mode 100644 index e5f74583a52891736b870555c2dceeecb6c224a0..0000000000000000000000000000000000000000 --- a/vpnor/mboxd_pnor_partition_table.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (C) 2018 IBM Corp. -#include "config.h" - -#include - -extern "C" { -#include "backend.h" -} - -#include "pnor_partition_table.hpp" -#include "xyz/openbmc_project/Common/error.hpp" - -#include -#include - -#include "common.h" -#include "mboxd.h" -#include "vpnor/backend.h" - -void vpnor_default_paths(vpnor_partition_paths* paths) -{ - strncpy(paths->ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX); - paths->ro_loc[PATH_MAX - 1] = '\0'; - strncpy(paths->rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX); - paths->rw_loc[PATH_MAX - 1] = '\0'; - strncpy(paths->prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX); - paths->prsv_loc[PATH_MAX - 1] = '\0'; - strncpy(paths->patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX); - paths->prsv_loc[PATH_MAX - 1] = '\0'; -} - -int vpnor_init(struct backend* backend, const vpnor_partition_paths* paths) -{ - namespace err = sdbusplus::xyz::openbmc_project::Common::Error; - namespace fs = std::experimental::filesystem; - namespace vpnor = openpower::virtual_pnor; - - if (!(backend && paths)) - return -EINVAL; - - vpnor_data* priv = new vpnor_data; - assert(priv); - - priv->paths = *paths; - backend->priv = priv; - - try - { - priv->vpnor = new vpnor_partition_table; - priv->vpnor->table = - new openpower::virtual_pnor::partition::Table(backend); - } - catch (vpnor::TocEntryError& e) - { - MSG_ERR("%s\n", e.what()); - try - { - phosphor::logging::commit(); - } - catch (const std::exception& e) - { - MSG_ERR("Failed to commit InternalFailure: %s\n", e.what()); - } - return -EINVAL; - } - - return 0; -} - -int vpnor_copy_bootloader_partition(const struct backend* backend, void* buf, - uint32_t count) -{ - // The hostboot bootloader has certain size/offset assumptions, so - // we need a special partition table here. - // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is - // 4K, the page size is 4K. - // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size' - // offset, and first looks for the TOC here, before proceeding to move up - // page by page looking for the TOC. So it is optimal to place the TOC at - // this offset. - constexpr size_t eraseSize = 0x1000; - constexpr size_t pageSize = 0x1000; - constexpr size_t pnorSize = 0x4000000; - constexpr size_t tocMaxSize = 0x8000; - constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize; - constexpr auto blPartitionName = "HBB"; - - namespace err = sdbusplus::xyz::openbmc_project::Common::Error; - namespace fs = std::experimental::filesystem; - namespace vpnor = openpower::virtual_pnor; - - try - { - vpnor_partition_table vtbl{}; - struct vpnor_data priv; - struct backend local = *backend; - - priv.vpnor = &vtbl; - priv.paths = ((struct vpnor_data*)backend->priv)->paths; - local.priv = &priv; - local.block_size_shift = log_2(eraseSize); - - openpower::virtual_pnor::partition::Table blTable(&local); - - vtbl.table = &blTable; - - size_t tocOffset = 0; - - const pnor_partition& partition = blTable.partition(blPartitionName); - size_t hbbOffset = partition.data.base * eraseSize; - uint32_t hbbSize = partition.data.actual; - - if (count < tocStart + blTable.capacity() || - count < hbbOffset + hbbSize) - { - MSG_ERR("Reserved memory too small for dumb bootstrap\n"); - return -EINVAL; - } - - uint8_t* buf8 = static_cast(buf); - backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity()); - backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize); - } - catch (err::InternalFailure& e) - { - phosphor::logging::commit(); - return -EIO; - } - catch (vpnor::ReasonedError& e) - { - MSG_ERR("%s\n", e.what()); - phosphor::logging::commit(); - return -EIO; - } - - return 0; -} - -void vpnor_destroy(struct backend* backend) -{ - struct vpnor_data* priv = (struct vpnor_data*)backend->priv; - - if (priv) - { - if (priv->vpnor) - { - delete priv->vpnor->table; - } - delete priv->vpnor; - } - delete priv; -} diff --git a/vpnor/pnor_partition_table.cpp b/vpnor/pnor_partition_table.cpp index 2a9442bae50db1699621ce6707bb68779c17a5f1..64a7872f33c22d7889e6fe06ac8c324e61db2a29 100644 --- a/vpnor/pnor_partition_table.cpp +++ b/vpnor/pnor_partition_table.cpp @@ -2,8 +2,13 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "pnor_partition_table.hpp" +extern "C" { +#include "backend.h" +#include "common.h" +#include "mboxd.h" +} +#include "pnor_partition_table.hpp" #include "xyz/openbmc_project/Common/error.hpp" #include @@ -14,12 +19,6 @@ #include #include -extern "C" { -#include "backend.h" -#include "common.h" -#include "mboxd.h" -} - namespace openpower { namespace virtual_pnor diff --git a/vpnor/pnor_partition_table.hpp b/vpnor/pnor_partition_table.hpp index cfd47b55e699a294639cef1c612843c7808235fb..4309ad5525179cefcdb92bee2155690eaf6d58ae 100644 --- a/vpnor/pnor_partition_table.hpp +++ b/vpnor/pnor_partition_table.hpp @@ -10,8 +10,8 @@ extern "C" { #include "backend.h" #include "common.h" -#include "pnor_partition_defs.h" #include "vpnor/backend.h" +#include "vpnor/pnor_partition_defs.h" } struct mbox_context; @@ -97,7 +97,7 @@ class Table /** @brief Constructor accepting the path of the directory * that houses the PNOR partition files. * - * @param[in] ctx - Acquire sizes and paths relevant to the table + * @param[in] be - Acquire sizes and paths relevant to the table * * Throws MalformedTocEntry, InvalidTocEntry */ diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include index 060096995a96fc216f4524de5f80871b0942358a..0b937476c71bb94f76b88f11b59f3c5c3ac9c701 100644 --- a/vpnor/test/Makefile.am.include +++ b/vpnor/test/Makefile.am.include @@ -7,7 +7,6 @@ TEST_MBOX_VPNOR_INTEG_SRCS = \ windows.c \ lpc.c \ vpnor/backend.cpp \ - vpnor/mboxd_pnor_partition_table.cpp \ vpnor/pnor_partition.cpp \ vpnor/pnor_partition_table.cpp \ %reldir%/tmpd.cpp diff --git a/vpnor/test/create_pnor_partition_table.cpp b/vpnor/test/create_pnor_partition_table.cpp index f198f29e727bd098f4cbeccfe8efe288638baebf..7af61b768dda0863a929fbd24ffb36e381613d8a 100644 --- a/vpnor/test/create_pnor_partition_table.cpp +++ b/vpnor/test/create_pnor_partition_table.cpp @@ -1,19 +1,20 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (C) 2018 IBM Corp. -#include "config.h" - -#include "vpnor/pnor_partition_table.hpp" -#include -#include +#include "config.h" extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include +#include + static const auto BLOCK_SIZE = 4 * 1024; static const auto ERASE_SIZE = BLOCK_SIZE; static const auto PNOR_SIZE = 64 * 1024 * 1024; diff --git a/vpnor/test/create_read_window_toc.cpp b/vpnor/test/create_read_window_toc.cpp index 7571f375c168beaf14dc243771c13079af3850f7..1eda6c255df8bea4d6d80f6bfe81e5fc55810da5 100644 --- a/vpnor/test/create_read_window_toc.cpp +++ b/vpnor/test/create_read_window_toc.cpp @@ -2,20 +2,20 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" - -#include - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include + +#include +#include + static constexpr auto BLOCK_SIZE = 4 * 1024; static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; static constexpr auto MEM_SIZE = BLOCK_SIZE * 2; diff --git a/vpnor/test/force_readonly_toc.cpp b/vpnor/test/force_readonly_toc.cpp index 465adadbc0b3f40775fb606d665759ed562f55fb..026c9761c1cd6aad49b27095a694795a3c266662 100644 --- a/vpnor/test/force_readonly_toc.cpp +++ b/vpnor/test/force_readonly_toc.cpp @@ -2,22 +2,22 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" - -#include -#include - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" #include "vpnor/pnor_partition_defs.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include +#include + +#include +#include + static constexpr auto BLOCK_SIZE = 4 * 1024; static constexpr auto PNOR_SIZE = BLOCK_SIZE; static constexpr auto MEM_SIZE = BLOCK_SIZE; diff --git a/vpnor/test/toc_lookup_failed.cpp b/vpnor/test/toc_lookup_failed.cpp index cb56e518474b019f4eac8a6b9f8492c498b13c1e..b92cdff69a923a7ff6738144e457a68fbde0f0de 100644 --- a/vpnor/test/toc_lookup_failed.cpp +++ b/vpnor/test/toc_lookup_failed.cpp @@ -2,18 +2,18 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" -#include "xyz/openbmc_project/Common/error.hpp" - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include "xyz/openbmc_project/Common/error.hpp" + +#include +#include static constexpr auto BLOCK_SIZE = 0x1000; static constexpr auto ERASE_SIZE = BLOCK_SIZE; diff --git a/vpnor/test/toc_lookup_found.cpp b/vpnor/test/toc_lookup_found.cpp index b8c879c6f84f37cf53ebb07843e4a07d02f8b8c5..efe4ea415a011f0e30d94a6c09120abda6b2c88b 100644 --- a/vpnor/test/toc_lookup_found.cpp +++ b/vpnor/test/toc_lookup_found.cpp @@ -2,18 +2,18 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include +#include + static constexpr auto BLOCK_SIZE = 0x1000; static constexpr auto ERASE_SIZE = BLOCK_SIZE; static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; diff --git a/vpnor/test/toc_missing_file.cpp b/vpnor/test/toc_missing_file.cpp index 95147c09e62235c0cc9a2cd641d65e85955ad356..b19bfd84085f53f874b5e9740da0059e94ae75fc 100644 --- a/vpnor/test/toc_missing_file.cpp +++ b/vpnor/test/toc_missing_file.cpp @@ -2,18 +2,18 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include +#include + static constexpr auto BLOCK_SIZE = 0x1000; static constexpr auto ERASE_SIZE = BLOCK_SIZE; static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; diff --git a/vpnor/test/write_toc.cpp b/vpnor/test/write_toc.cpp index 8b690a149bb49dc45c886a7b7b33700ae15a938b..d8b63ce4d4eb93938992ab0cee830baee28ce45d 100644 --- a/vpnor/test/write_toc.cpp +++ b/vpnor/test/write_toc.cpp @@ -2,20 +2,20 @@ // Copyright (C) 2018 IBM Corp. #include "config.h" -#include "vpnor/pnor_partition_table.hpp" - -#include - -#include -#include - extern "C" { +#include "backend.h" #include "test/mbox.h" #include "test/system.h" } +#include "vpnor/pnor_partition_table.hpp" #include "vpnor/test/tmpd.hpp" +#include + +#include +#include + static constexpr auto BLOCK_SIZE = 4 * 1024; static constexpr auto PNOR_SIZE = 2 * BLOCK_SIZE; static constexpr auto MEM_SIZE = BLOCK_SIZE;