tools: p2a: enable bridge on host side
Enable the PCI-to-AHB bridge from the host-side.
Note: On my test system, this didn't seem to be required, it's possible
the bit was stuck on when enabled.
Tested: Not tested.
Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: Idbea0e9d378ee108f24240d64b43b6a3c0eea799
diff --git a/tools/p2a.cpp b/tools/p2a.cpp
index b5fa8a4..b1f8672 100644
--- a/tools/p2a.cpp
+++ b/tools/p2a.cpp
@@ -29,6 +29,23 @@
namespace host_tool
{
+namespace
+{
+void disablePciBridge(HostIoInterface* io, std::size_t address)
+{
+ /* Read current value, and just blindly unset the bit. */
+ std::uint32_t value;
+ if (!io->read(address + aspeedP2aConfig, sizeof(value), &value))
+ {
+ return;
+ }
+
+ value &= ~p2ABridgeEnabled;
+ io->write(address + aspeedP2aConfig, sizeof(value), &value);
+}
+
+} // namespace
+
bool P2aDataHandler::sendContents(const std::string& input,
std::uint16_t session)
{
@@ -36,6 +53,12 @@
PciFilter filter;
bool found = false;
pciaddr_t bar1;
+ bool returnValue = false;
+ int inputFd = -1;
+ ipmi_flash::PciConfigResponse pciResp;
+ std::int64_t fileSize;
+ const std::uint32_t p2aLength = aspeedP2aOffset;
+ std::unique_ptr<std::uint8_t[]> readBuffer;
filter.vid = aspeedVendorId;
filter.did = aspeedDeviceId;
@@ -68,10 +91,10 @@
std::fprintf(stderr, "\n");
/* We sent the open command before this, so the window should be open and
- * the bridge enabled.
+ * the bridge enabled on the BMC.
*/
std::uint32_t value;
- if (!io->read(bar1 | aspeedP2aConfig, sizeof(value), &value))
+ if (!io->read(bar1 + aspeedP2aConfig, sizeof(value), &value))
{
std::fprintf(stderr, "PCI config read failed\n");
return false;
@@ -79,10 +102,17 @@
if (0 == (value & p2ABridgeEnabled))
{
- std::fprintf(stderr, "Bridge not enabled.\n");
- return false;
+ std::fprintf(stderr, "Bridge not enabled - Enabling from host\n");
+
+ value |= p2ABridgeEnabled;
+ if (!io->write(bar1 + aspeedP2aConfig, sizeof(value), &value))
+ {
+ std::fprintf(stderr, "PCI config write failed\n");
+ return false;
+ }
}
+ /* From this point down we need to disable the bridge. */
std::fprintf(stderr, "The bridge is enabled!\n");
/* Read the configuration via blobs metadata (stat). */
@@ -91,45 +121,43 @@
{
std::fprintf(stderr, "Didn't receive expected size of metadata for "
"PCI Configuration response\n");
- return false;
+ goto exit;
}
- ipmi_flash::PciConfigResponse pciResp;
std::memcpy(&pciResp, stat.metadata.data(), sizeof(pciResp));
std::fprintf(stderr, "Received address: 0x%x\n", pciResp.address);
/* Configure the mmio to point there. */
- if (!io->write(bar1 | aspeedP2aBridge, sizeof(pciResp.address),
+ if (!io->write(bar1 + aspeedP2aBridge, sizeof(pciResp.address),
&pciResp.address))
{
// Failed to set it up, so fall back.
std::fprintf(stderr, "Failed to update the bridge address\n");
- return false;
+ goto exit;
}
/* For data blocks in 64kb, stage data, and send blob write command. */
- int inputFd = sys->open(input.c_str(), 0);
+ inputFd = sys->open(input.c_str(), 0);
if (inputFd < 0)
{
- return false;
+ std::fprintf(stderr, "Unable to open file: '%s'\n", input.c_str());
+ goto exit;
}
- std::int64_t fileSize = sys->getSize(input.c_str());
+ fileSize = sys->getSize(input.c_str());
if (fileSize == 0)
{
std::fprintf(stderr, "Zero-length file, or other file access error\n");
- return false;
+ goto exit;
}
progress->start(fileSize);
- const std::uint32_t p2aLength = aspeedP2aOffset;
-
- auto readBuffer = std::make_unique<std::uint8_t[]>(p2aLength);
+ readBuffer = std::make_unique<std::uint8_t[]>(p2aLength);
if (nullptr == readBuffer)
{
std::fprintf(stderr, "Unable to allocate memory for read buffer.\n");
- return false;
+ goto exit;
}
try
@@ -142,19 +170,19 @@
bytesRead = sys->read(inputFd, readBuffer.get(), p2aLength);
if (bytesRead > 0)
{
- /* TODO: Will likely need to store an rv somewhere to know when
- * we're exiting from failure.
+ /* TODO: Will likely need to store an rv somewhere to know
+ * when we're exiting from failure.
*/
- if (!io->write(bar1 | aspeedP2aOffset, bytesRead,
+ if (!io->write(bar1 + aspeedP2aOffset, bytesRead,
readBuffer.get()))
{
std::fprintf(stderr,
"Failed to write to region in memory!\n");
- break;
+ goto exit;
}
- /* Ok, so the data is staged, now send the blob write with the
- * details.
+ /* Ok, so the data is staged, now send the blob write with
+ * the details.
*/
struct ipmi_flash::ExtChunkHdr chunk;
chunk.length = bytesRead;
@@ -170,12 +198,22 @@
}
catch (const ipmiblob::BlobException& b)
{
- sys->close(inputFd);
- return false;
+ goto exit;
}
- sys->close(inputFd);
- return true;
+ /* defaults to failure. */
+ returnValue = true;
+
+exit:
+ /* disable PCI bridge. */
+ disablePciBridge(io, bar1);
+
+ /* close input file. */
+ if (inputFd != -1)
+ {
+ sys->close(inputFd);
+ }
+ return returnValue;
}
} // namespace host_tool