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>
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 @@
         &(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)