summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2017-07-12 01:06:30 -0500
committerPatrick Williams <patrick@stwcx.xyz>2017-07-19 22:59:37 +0000
commit017e45c3f202116ad09d5abdcaeb88f5b5f52594 (patch)
treebe589e2398aa46815813fc789591b348f5621c58
parent8a89969d635a8ac8f7b21bb673ec03a19d76cd4d (diff)
downloadphosphor-mboxd-017e45c3f202116ad09d5abdcaeb88f5b5f52594.tar.gz
phosphor-mboxd-017e45c3f202116ad09d5abdcaeb88f5b5f52594.zip
vpnor: create hostboot bootloader partition
The hostboot bootloader code doesn't use mbox. It has specific requirements: - The PNOR TOC should be at the 'PNOR end - TOC size - page size' offset. It searches for the TOC here, if not found, the search moves down page by page. - The PNOR should be 64M. The page size and erase block should be 4K. The TOC should be 32K. Copy what the bootloader expects to the LPC memory when mboxd starts up. The same needs to be done in the case of an mbox reset (irrespective of where the reset comes from). Skiboot expects that the TOC should be at offset 0, but it uses mbox to read the TOC. So this commit doesn't impact skiboot requirements. Change-Id: I7de556dccfea85f2faa5f401177006a3a562494e Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r--Makefile.am8
-rw-r--r--mboxd.c26
-rw-r--r--mboxd_dbus.c8
-rw-r--r--mboxd_lpc.h9
-rw-r--r--mboxd_lpc_physical.c34
-rw-r--r--mboxd_lpc_virtual.cpp34
-rw-r--r--mboxd_msg.c5
-rw-r--r--mboxd_pnor_partition_table.cpp40
-rw-r--r--mboxd_pnor_partition_table.h7
9 files changed, 149 insertions, 22 deletions
diff --git a/Makefile.am b/Makefile.am
index af44432..f182f1a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,14 +16,16 @@ if VIRTUAL_PNOR_ENABLED
mboxd_SOURCES += pnor_partition_table.cpp \
mboxd_pnor_partition_table.cpp \
mboxd_flash_virtual.cpp \
- pnor_partition.cpp
+ pnor_partition.cpp \
+ mboxd_lpc_virtual.cpp
mboxd_LDFLAGS += -lstdc++fs \
$(SDBUSPLUS_LIBS) \
$(PHOSPHOR_LOGGING_LIBS) \
$(PHOSPHOR_DBUS_INTERFACES_LIBS)
else
-mboxd_SOURCES += mboxd_flash_physical.c
+mboxd_SOURCES += mboxd_flash_physical.c \
+ mboxd_lpc_physical.c
endif
mboxctl_SOURCES = mboxctl.c
@@ -61,6 +63,7 @@ TEST_MBOX_SRCS = \
mboxd_msg.c \
mboxd_windows.c \
mboxd_lpc.c \
+ mboxd_lpc_physical.c \
common.c \
mboxd_flash_physical.c
@@ -151,6 +154,7 @@ test_create_read_window_vpnor_SOURCES = \
mboxd_msg.c \
mboxd_windows.c \
mboxd_lpc.c \
+ mboxd_lpc_virtual.cpp \
mboxd_pnor_partition_table.cpp \
mboxd_flash_virtual.cpp \
pnor_partition.cpp \
diff --git a/mboxd.c b/mboxd.c
index ffd8c84..43d2aa1 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -104,7 +104,7 @@ static int poll_loop(struct mbox_context *context)
case SIGHUP:
/* Host didn't request reset -> Notify it */
reset_all_windows(context, SET_BMC_EVENT);
- rc = point_to_flash(context);
+ rc = reset_lpc(context);
if (rc < 0) {
MSG_ERR("WARNING: Failed to point the "
"LPC bus back to flash on "
@@ -139,10 +139,10 @@ static int poll_loop(struct mbox_context *context)
}
}
- /* Best to reset windows and point back to flash for safety */
+ /* Best to reset windows and the lpc mapping for safety */
/* Host didn't request reset -> Notify it */
reset_all_windows(context, SET_BMC_EVENT);
- rc = point_to_flash(context);
+ rc = reset_lpc(context);
/* Not much we can do if this fails */
if (rc < 0) {
MSG_ERR("WARNING: Failed to point the LPC bus back to flash\n"
@@ -343,8 +343,16 @@ int main(int argc, char **argv)
goto finish;
}
- /* Set the LPC bus mapping to point to the physical flash device */
- rc = point_to_flash(context);
+#ifdef VIRTUAL_PNOR_ENABLED
+ vpnor_create_partition_table(context);
+
+ strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
+ strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
+ strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
+#endif
+
+ /* Set the LPC bus mapping */
+ rc = reset_lpc(context);
if (rc) {
goto finish;
}
@@ -354,14 +362,6 @@ int main(int argc, char **argv)
goto finish;
}
-#ifdef VIRTUAL_PNOR_ENABLED
- vpnor_create_partition_table(context);
-
- strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
- strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
- strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
-#endif
-
MSG_INFO("Entering Polling Loop\n");
rc = poll_loop(context);
diff --git a/mboxd_dbus.c b/mboxd_dbus.c
index 6673ca6..3f869fe 100644
--- a/mboxd_dbus.c
+++ b/mboxd_dbus.c
@@ -133,12 +133,12 @@ static int dbus_handle_reset(struct mbox_context *context,
}
/*
- * This will close (and flush) the current window and point the lpc bus
- * mapping back to flash. Better set the bmc event to notify the host
- * of this.
+ * This will close (and flush) the current window and reset the lpc bus
+ * mapping back to flash, or memory in case we're using a virtual pnor.
+ * Better set the bmc event to notify the host of this.
*/
reset_all_windows(context, SET_BMC_EVENT);
- rc = point_to_flash(context);
+ rc = reset_lpc(context);
if (rc < 0) {
return -E_DBUS_HARDWARE;
}
diff --git a/mboxd_lpc.h b/mboxd_lpc.h
index bb288a9..2c38ab0 100644
--- a/mboxd_lpc.h
+++ b/mboxd_lpc.h
@@ -18,9 +18,18 @@
#ifndef MBOXD_LPC_H
#define MBOXD_LPC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int init_lpc_dev(struct mbox_context *context);
void free_lpc_dev(struct mbox_context *context);
int point_to_flash(struct mbox_context *context);
int point_to_memory(struct mbox_context *context);
+int reset_lpc(struct mbox_context *context);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* MBOXD_LPC_H */
diff --git a/mboxd_lpc_physical.c b/mboxd_lpc_physical.c
new file mode 100644
index 0000000..5f5dc01
--- /dev/null
+++ b/mboxd_lpc_physical.c
@@ -0,0 +1,34 @@
+/*
+ * Mailbox Daemon LPC Helpers
+ *
+ * Copyright 2017 IBM
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include "mbox.h"
+#include "mboxd_lpc.h"
+
+/*
+ * reset_lpc() - Reset the lpc bus mapping
+ * @context: The mbox context pointer
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+int reset_lpc(struct mbox_context *context)
+{
+ return point_to_flash(context);
+}
diff --git a/mboxd_lpc_virtual.cpp b/mboxd_lpc_virtual.cpp
new file mode 100644
index 0000000..802c761
--- /dev/null
+++ b/mboxd_lpc_virtual.cpp
@@ -0,0 +1,34 @@
+/*
+ * Mailbox Daemon LPC Helpers
+ *
+ * Copyright 2017 IBM
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "mbox.h"
+#include "mboxd_lpc.h"
+#include "mboxd_pnor_partition_table.h"
+
+/*
+ * reset_lpc() - Reset the lpc bus mapping
+ * @context: The mbox context pointer
+ *
+ * Return 0 on success otherwise negative error code
+ */
+int reset_lpc(struct mbox_context *context)
+{
+ vpnor_copy_bootloader_partition(context);
+ return point_to_memory(context);
+}
diff --git a/mboxd_msg.c b/mboxd_msg.c
index 65946e8..437c67d 100644
--- a/mboxd_msg.c
+++ b/mboxd_msg.c
@@ -138,14 +138,15 @@ int clr_bmc_events(struct mbox_context *context, uint8_t bmc_event,
/*
* Command: RESET_STATE
- * Reset the LPC mapping to point back at the flash
+ * Reset the LPC mapping to point back at the flash, or memory in case we're
+ * using a virtual pnor.
*/
static int mbox_handle_reset(struct mbox_context *context,
union mbox_regs *req, struct mbox_msg *resp)
{
/* Host requested it -> No BMC Event */
reset_all_windows(context, NO_BMC_EVENT);
- return point_to_flash(context);
+ return reset_lpc(context);
}
/*
diff --git a/mboxd_pnor_partition_table.cpp b/mboxd_pnor_partition_table.cpp
index 2464e6c..d2fdba3 100644
--- a/mboxd_pnor_partition_table.cpp
+++ b/mboxd_pnor_partition_table.cpp
@@ -1,5 +1,7 @@
#include "mboxd_pnor_partition_table.h"
+#include "common.h"
#include "mbox.h"
+#include "mboxd_flash.h"
#include "pnor_partition_table.hpp"
#include <experimental/filesystem>
@@ -57,6 +59,44 @@ const struct pnor_partition* vpnor_get_partition(
&(context->vpnor->table->partition(offset)) : nullptr;
}
+void vpnor_copy_bootloader_partition(const struct mbox_context *context)
+{
+ // 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";
+
+ openpower::virtual_pnor::partition::Table blTable(eraseSize, pnorSize);
+ vpnor_partition_table vtbl{};
+ vtbl.table = &blTable;
+ struct mbox_context local{};
+ local.vpnor = &vtbl;
+ local.block_size_shift = log_2(eraseSize);
+ memcpy(&local.paths, &context->paths, sizeof(local.paths));
+
+ size_t tocOffset = 0;
+ // Copy TOC
+ copy_flash(&local, tocOffset,
+ static_cast<uint8_t*>(context->mem) + tocStart,
+ blTable.size() * eraseSize);
+ const pnor_partition& partition = blTable.partition(blPartitionName);
+ size_t hbbOffset = partition.data.base * eraseSize;
+ size_t hbbSize = partition.data.actual;
+ // Copy HBB
+ copy_flash(&local, hbbOffset,
+ static_cast<uint8_t*>(context->mem) + hbbOffset, hbbSize);
+}
+
void vpnor_destroy_partition_table(struct mbox_context *context)
{
if(context && context->vpnor)
diff --git a/mboxd_pnor_partition_table.h b/mboxd_pnor_partition_table.h
index e6c899b..df15d24 100644
--- a/mboxd_pnor_partition_table.h
+++ b/mboxd_pnor_partition_table.h
@@ -78,11 +78,16 @@ const struct pnor_partition* vpnor_get_partition(
const size_t offset);
-/** @brief Destroy partition table, if it exists.
+/** @brief Copy bootloader partition (alongwith TOC) to LPC memory
*
* @param[in] context - mbox context pointer
*/
+void vpnor_copy_bootloader_partition(const struct mbox_context *context);
+/** @brief Destroy partition table, if it exists.
+ *
+ * @param[in] context - mbox context pointer
+ */
void vpnor_destroy_partition_table(struct mbox_context *context);
#ifdef __cplusplus
OpenPOWER on IntegriCloud