Commit 035ad76b authored by Andrew Jeffery's avatar Andrew Jeffery

vpnor: Consolidate backend and mboxd_pnor_partition_table sources

Change-Id: Ibf66c3a86c2a50e2304fb968f8c912ede84cf719
Signed-off-by: Andrew Jeffery's avatarAndrew Jeffery <andrew@aj.id.au>
parent f4bc335b
mboxd_SOURCES += %reldir%/pnor_partition_table.cpp \
%reldir%/mboxd_pnor_partition_table.cpp \
%reldir%/backend.cpp \
%reldir%/pnor_partition.cpp
......
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
......@@ -12,19 +14,21 @@
#include <algorithm>
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 <cassert>
#include <exception>
#include <experimental/filesystem>
#include <memory>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
......@@ -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<err::InternalFailure>();
}
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<uint8_t*>(buf);
backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity());
backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize);
}
catch (err::InternalFailure& e)
{
phosphor::logging::commit<err::InternalFailure>();
return -EIO;
}
catch (vpnor::ReasonedError& e)
{
MSG_ERR("%s\n", e.what());
phosphor::logging::commit<err::InternalFailure>();
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)
......
......@@ -3,8 +3,6 @@
#pragma once
#include <limits.h>
#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
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include <assert.h>
extern "C" {
#include "backend.h"
}
#include "pnor_partition_table.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <experimental/filesystem>
#include <phosphor-logging/elog-errors.hpp>
#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<err::InternalFailure>();
}
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<uint8_t*>(buf);
backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity());
backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize);
}
catch (err::InternalFailure& e)
{
phosphor::logging::commit<err::InternalFailure>();
return -EIO;
}
catch (vpnor::ReasonedError& e)
{
MSG_ERR("%s\n", e.what());
phosphor::logging::commit<err::InternalFailure>();
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;
}
......@@ -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 <endian.h>
......@@ -14,12 +19,6 @@
#include <phosphor-logging/elog-errors.hpp>
#include <regex>
extern "C" {
#include "backend.h"
#include "common.h"
#include "mboxd.h"
}
namespace openpower
{
namespace virtual_pnor
......
......@@ -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
*/
......
......@@ -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
......
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <cassert>
#include <cstring>
#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 <cassert>
#include <cstring>
static const auto BLOCK_SIZE = 4 * 1024;
static const auto ERASE_SIZE = BLOCK_SIZE;
static const auto PNOR_SIZE = 64 * 1024 * 1024;
......
......@@ -2,20 +2,20 @@
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <sys/mman.h>
#include <cassert>
#include <cstring>
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 <sys/mman.h>
#include <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 4 * 1024;
static constexpr auto PNOR_SIZE = 64 * 1024 * 1024;
static constexpr auto MEM_SIZE = BLOCK_SIZE * 2;
......
......@@ -2,22 +2,22 @@
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <endian.h>
#include <sys/mman.h>
#include <cassert>
#include <cstring>
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 <endian.h>
#include <sys/mman.h>
#include <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 4 * 1024;
static constexpr auto PNOR_SIZE = BLOCK_SIZE;
static constexpr auto MEM_SIZE = BLOCK_SIZE;
......
......@@ -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 <cassert>
#include <cstring>
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 <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 0x1000;
static constexpr auto ERASE_SIZE = BLOCK_SIZE;
......
......@@ -2,18 +2,18 @@
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <cassert>
#include <cstring>
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 <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 0x1000;
static constexpr auto ERASE_SIZE = BLOCK_SIZE;
static constexpr auto PNOR_SIZE = 64 * 1024 * 1024;
......
......@@ -2,18 +2,18 @@
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <cassert>
#include <cstring>
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 <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 0x1000;
static constexpr auto ERASE_SIZE = BLOCK_SIZE;
static constexpr auto PNOR_SIZE = 64 * 1024 * 1024;
......
......@@ -2,20 +2,20 @@
// Copyright (C) 2018 IBM Corp.
#include "config.h"
#include "vpnor/pnor_partition_table.hpp"
#include <sys/mman.h>
#include <cassert>
#include <cstring>
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 <sys/mman.h>
#include <cassert>
#include <cstring>
static constexpr auto BLOCK_SIZE = 4 * 1024;
static constexpr auto PNOR_SIZE = 2 * BLOCK_SIZE;
static constexpr auto MEM_SIZE = BLOCK_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment