backend.cpp (f4bc335b4fc899509c92c230f746fe90a5aa43d2) | backend.cpp (035ad76b8b45a01cc7fcc184e7e72eed69c0ece5) |
---|---|
1// SPDX-License-Identifier: Apache-2.0 2// Copyright (C) 2018 IBM Corp. 3 | 1// SPDX-License-Identifier: Apache-2.0 2// Copyright (C) 2018 IBM Corp. 3 |
4#include "config.h" 5 |
|
4#include <fcntl.h> 5#include <stdint.h> 6#include <stdlib.h> 7#include <sys/ioctl.h> 8#include <sys/mman.h> 9#include <syslog.h> 10#include <unistd.h> 11 12#include <algorithm> 13 14extern "C" { | 6#include <fcntl.h> 7#include <stdint.h> 8#include <stdlib.h> 9#include <sys/ioctl.h> 10#include <sys/mman.h> 11#include <syslog.h> 12#include <unistd.h> 13 14#include <algorithm> 15 16extern "C" { |
17#include "backend.h" |
|
15#include "common.h" 16#include "lpc.h" 17#include "mboxd.h" 18#include "protocol.h" | 18#include "common.h" 19#include "lpc.h" 20#include "mboxd.h" 21#include "protocol.h" |
22#include "vpnor/backend.h" |
|
19} 20 | 23} 24 |
21#include "config.h" 22 | |
23#include "pnor_partition.hpp" 24#include "pnor_partition_table.hpp" 25#include "xyz/openbmc_project/Common/error.hpp" 26 | 25#include "pnor_partition.hpp" 26#include "pnor_partition_table.hpp" 27#include "xyz/openbmc_project/Common/error.hpp" 28 |
29#include <cassert> |
|
27#include <exception> | 30#include <exception> |
31#include <experimental/filesystem> |
|
28#include <memory> 29#include <phosphor-logging/elog-errors.hpp> 30#include <phosphor-logging/log.hpp> 31#include <stdexcept> 32#include <string> 33 34#include "vpnor/backend.h" 35 36namespace err = sdbusplus::xyz::openbmc_project::Common::Error; 37namespace fs = std::experimental::filesystem; 38namespace vpnor = openpower::virtual_pnor; 39 40static constexpr uint32_t VPNOR_ERASE_SIZE = 4 * 1024; 41 | 32#include <memory> 33#include <phosphor-logging/elog-errors.hpp> 34#include <phosphor-logging/log.hpp> 35#include <stdexcept> 36#include <string> 37 38#include "vpnor/backend.h" 39 40namespace err = sdbusplus::xyz::openbmc_project::Common::Error; 41namespace fs = std::experimental::filesystem; 42namespace vpnor = openpower::virtual_pnor; 43 44static constexpr uint32_t VPNOR_ERASE_SIZE = 4 * 1024; 45 |
46void vpnor_default_paths(vpnor_partition_paths* paths) 47{ 48 strncpy(paths->ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX); 49 paths->ro_loc[PATH_MAX - 1] = '\0'; 50 strncpy(paths->rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX); 51 paths->rw_loc[PATH_MAX - 1] = '\0'; 52 strncpy(paths->prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX); 53 paths->prsv_loc[PATH_MAX - 1] = '\0'; 54 strncpy(paths->patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX); 55 paths->prsv_loc[PATH_MAX - 1] = '\0'; 56} 57 58/** @brief Create a virtual PNOR partition table. 59 * 60 * @param[in] backend - The backend context pointer 61 * @param[in] paths - A paths object pointer to initialise vpnor 62 * 63 * This API should be called before calling any other APIs below. If a table 64 * already exists, this function will not do anything further. This function 65 * will not do anything if the context is NULL. 66 * 67 * The content of the paths object is copied out, ownership is retained by the 68 * caller. 69 * 70 * Returns 0 if the call succeeds, else a negative error code. 71 */ 72static int vpnor_init(struct backend* backend, 73 const vpnor_partition_paths* paths) 74{ 75 namespace err = sdbusplus::xyz::openbmc_project::Common::Error; 76 namespace fs = std::experimental::filesystem; 77 namespace vpnor = openpower::virtual_pnor; 78 79 vpnor_data* priv = new vpnor_data; 80 assert(priv); 81 82 priv->paths = *paths; 83 backend->priv = priv; 84 85 try 86 { 87 priv->vpnor = new vpnor_partition_table; 88 priv->vpnor->table = 89 new openpower::virtual_pnor::partition::Table(backend); 90 } 91 catch (vpnor::TocEntryError& e) 92 { 93 MSG_ERR("%s\n", e.what()); 94 try 95 { 96 phosphor::logging::commit<err::InternalFailure>(); 97 } 98 catch (const std::exception& e) 99 { 100 MSG_ERR("Failed to commit InternalFailure: %s\n", e.what()); 101 } 102 return -EINVAL; 103 } 104 105 return 0; 106} 107 108/** @brief Copy bootloader partition (alongwith TOC) to LPC memory 109 * 110 * @param[in] backend - The backend context pointer 111 * 112 * @returns 0 on success, negative error code on failure 113 */ 114int vpnor_copy_bootloader_partition(const struct backend* backend, void* buf, 115 uint32_t count) 116{ 117 // The hostboot bootloader has certain size/offset assumptions, so 118 // we need a special partition table here. 119 // It assumes the PNOR is 64M, the TOC size is 32K, the erase block is 120 // 4K, the page size is 4K. 121 // It also assumes the TOC is at the 'end of pnor - toc size - 1 page size' 122 // offset, and first looks for the TOC here, before proceeding to move up 123 // page by page looking for the TOC. So it is optimal to place the TOC at 124 // this offset. 125 constexpr size_t eraseSize = 0x1000; 126 constexpr size_t pageSize = 0x1000; 127 constexpr size_t pnorSize = 0x4000000; 128 constexpr size_t tocMaxSize = 0x8000; 129 constexpr size_t tocStart = pnorSize - tocMaxSize - pageSize; 130 constexpr auto blPartitionName = "HBB"; 131 132 namespace err = sdbusplus::xyz::openbmc_project::Common::Error; 133 namespace fs = std::experimental::filesystem; 134 namespace vpnor = openpower::virtual_pnor; 135 136 try 137 { 138 vpnor_partition_table vtbl{}; 139 struct vpnor_data priv; 140 struct backend local = *backend; 141 142 priv.vpnor = &vtbl; 143 priv.paths = ((struct vpnor_data*)backend->priv)->paths; 144 local.priv = &priv; 145 local.block_size_shift = log_2(eraseSize); 146 147 openpower::virtual_pnor::partition::Table blTable(&local); 148 149 vtbl.table = &blTable; 150 151 size_t tocOffset = 0; 152 153 const pnor_partition& partition = blTable.partition(blPartitionName); 154 size_t hbbOffset = partition.data.base * eraseSize; 155 uint32_t hbbSize = partition.data.actual; 156 157 if (count < tocStart + blTable.capacity() || 158 count < hbbOffset + hbbSize) 159 { 160 MSG_ERR("Reserved memory too small for dumb bootstrap\n"); 161 return -EINVAL; 162 } 163 164 uint8_t* buf8 = static_cast<uint8_t*>(buf); 165 backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity()); 166 backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize); 167 } 168 catch (err::InternalFailure& e) 169 { 170 phosphor::logging::commit<err::InternalFailure>(); 171 return -EIO; 172 } 173 catch (vpnor::ReasonedError& e) 174 { 175 MSG_ERR("%s\n", e.what()); 176 phosphor::logging::commit<err::InternalFailure>(); 177 return -EIO; 178 } 179 180 return 0; 181} 182 |
|
42int vpnor_dev_init(struct backend* backend, void* data) 43{ 44 vpnor_partition_paths* paths = (vpnor_partition_paths*)data; 45 struct mtd_info_user mtd_info; 46 const char* filename = NULL; 47 int fd; 48 int rc = 0; 49 --- 56 unchanged lines hidden (view full) --- 106cleanup_filename: 107 free((void*)filename); 108 109 return rc; 110} 111 112static void vpnor_free(struct backend* backend) 113{ | 183int vpnor_dev_init(struct backend* backend, void* data) 184{ 185 vpnor_partition_paths* paths = (vpnor_partition_paths*)data; 186 struct mtd_info_user mtd_info; 187 const char* filename = NULL; 188 int fd; 189 int rc = 0; 190 --- 56 unchanged lines hidden (view full) --- 247cleanup_filename: 248 free((void*)filename); 249 250 return rc; 251} 252 253static void vpnor_free(struct backend* backend) 254{ |
114 vpnor_destroy(backend); | 255 struct vpnor_data* priv = (struct vpnor_data*)backend->priv; 256 257 if (priv) 258 { 259 if (priv->vpnor) 260 { 261 delete priv->vpnor->table; 262 } 263 delete priv->vpnor; 264 } 265 delete priv; |
115} 116 117/* 118 * vpnor_copy() - Copy data from the virtual pnor into a provided buffer 119 * @context: The backend context pointer 120 * @offset: The pnor offset to copy from (bytes) 121 * @mem: The buffer to copy into (must be of atleast 'size' bytes) 122 * @size: The number of bytes to copy --- 170 unchanged lines hidden (view full) --- 293 */ 294static int vpnor_reset(struct backend* backend, void* buf, uint32_t count) 295{ 296 const struct vpnor_data* priv = (const struct vpnor_data*)backend->priv; 297 int rc; 298 299 vpnor_partition_paths paths = priv->paths; 300 | 266} 267 268/* 269 * vpnor_copy() - Copy data from the virtual pnor into a provided buffer 270 * @context: The backend context pointer 271 * @offset: The pnor offset to copy from (bytes) 272 * @mem: The buffer to copy into (must be of atleast 'size' bytes) 273 * @size: The number of bytes to copy --- 170 unchanged lines hidden (view full) --- 444 */ 445static int vpnor_reset(struct backend* backend, void* buf, uint32_t count) 446{ 447 const struct vpnor_data* priv = (const struct vpnor_data*)backend->priv; 448 int rc; 449 450 vpnor_partition_paths paths = priv->paths; 451 |
301 vpnor_destroy(backend); | 452 vpnor_free(backend); |
302 303 rc = vpnor_init(backend, &paths); 304 if (rc < 0) 305 return rc; 306 307 rc = vpnor_copy_bootloader_partition(backend, buf, count); 308 if (rc < 0) 309 return rc; --- 34 unchanged lines hidden --- | 453 454 rc = vpnor_init(backend, &paths); 455 if (rc < 0) 456 return rc; 457 458 rc = vpnor_copy_bootloader_partition(backend, buf, count); 459 if (rc < 0) 460 return rc; --- 34 unchanged lines hidden --- |