bios: support for tool: flashcp
flashcp as an alternative to flashrom which is already present in some
images.
Tested: On Tyan S8030
Set
```
"Tool": "flashcp"
```
in the EM json config.
Using the images from [1], update to v4.01 and v4.03, dump the
flash contents and compare md5sum output for both the image and flash
dumps after each update.
```
[alex@odroid host-fw]$ md5sum v4.01/8030V401.ROM
fbbe6ff9b05b6a21f43d58fb0e5108cd v4.01/8030V401.ROM
[alex@odroid host-fw]$ md5sum v4.03/8030V403.ROM
8a0f85d559913ea63b40cd467cc65cd3 v4.03/8030V403.ROM
```
on the bmc:
```
root@s8030-bmc-30303035c0c1:~# md5sum /tmp/mtd6_dump_v4.01.bin
fbbe6ff9b05b6a21f43d58fb0e5108cd /tmp/mtd6_dump_v4.01.bin
root@s8030-bmc-30303035c0c1:~# md5sum /tmp/mtd6_dump_v4.03.bin
8a0f85d559913ea63b40cd467cc65cd3 /tmp/mtd6_dump_v4.03.bin
```
References:
[1] https://www.tyan.com/Motherboards=S8030=S8030GM2NE=downloads=EN/_Motherboards_S8030_S8030GM2NE
Change-Id: I95b473a5e90da38da866f982946855bb9452aafd
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/bios/bios_software_manager.cpp b/bios/bios_software_manager.cpp
index 3f4099a..1183ea1 100644
--- a/bios/bios_software_manager.cpp
+++ b/bios/bios_software_manager.cpp
@@ -53,6 +53,10 @@
{
tool = flashToolFlashrom;
}
+ else if (config.configType == "SPIFlash")
+ {
+ tool = flashToolFlashcp;
+ }
const std::string configIfaceMux = configIface + ".MuxOutputs";
diff --git a/bios/spi_device.cpp b/bios/spi_device.cpp
index fbf6fe9..af9ef89 100644
--- a/bios/spi_device.cpp
+++ b/bios/spi_device.cpp
@@ -297,6 +297,11 @@
}
success = (status == 0);
}
+ else if (tool == flashToolFlashcp)
+ {
+ success = co_await SPIDevice::writeSPIFlashWithFlashcp(
+ image, image_size);
+ }
else
{
success =
@@ -443,6 +448,54 @@
}
// NOLINTBEGIN(readability-static-accessed-through-instance)
+sdbusplus::async::task<bool> SPIDevice::writeSPIFlashWithFlashcp(
+ const uint8_t* image, size_t image_size) const
+// NOLINTEND(readability-static-accessed-through-instance)
+{
+ // randomize the name to enable parallel updates
+ const std::string path = "/tmp/spi-device-image-" +
+ std::to_string(Software::getRandomId()) + ".bin";
+
+ int fd = open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ error("Failed to open file: {PATH}", "PATH", path);
+ co_return 1;
+ }
+
+ const ssize_t bytesWritten = write(fd, image, image_size);
+
+ close(fd);
+
+ setUpdateProgress(30);
+
+ if (bytesWritten < 0 || static_cast<size_t>(bytesWritten) != image_size)
+ {
+ error("Failed to write image to file");
+ co_return 1;
+ }
+
+ debug("wrote {SIZE} bytes to {PATH}", "SIZE", bytesWritten, "PATH", path);
+
+ auto devPath = getMTDDevicePath();
+
+ if (!devPath.has_value())
+ {
+ co_return 1;
+ }
+
+ std::string cmd = std::format("flashcp -v {} {}", path, devPath.value());
+
+ debug("running {CMD}", "CMD", cmd);
+
+ const int exitCode = co_await asyncSystem(ctx, cmd);
+
+ std::filesystem::remove(path);
+
+ co_return exitCode == 0;
+}
+
+// NOLINTBEGIN(readability-static-accessed-through-instance)
sdbusplus::async::task<bool> SPIDevice::writeSPIFlashDefault(
const uint8_t* image, size_t image_size)
// NOLINTEND(readability-static-accessed-through-instance)
diff --git a/bios/spi_device.hpp b/bios/spi_device.hpp
index 4a9e6fc..25a53d1 100644
--- a/bios/spi_device.hpp
+++ b/bios/spi_device.hpp
@@ -35,6 +35,7 @@
{
flashToolNone, // write directly to the mtd device
flashToolFlashrom, // use flashrom, to handle e.g. IFD
+ flashToolFlashcp,
};
class SPIDevice : public Device, public NotifyWatchIntf
@@ -113,6 +114,16 @@
sdbusplus::async::task<int> writeSPIFlashWithFlashrom(
const uint8_t* image, size_t image_size) const;
+ // @description preconditions:
+ // - host is powered off
+ // - gpio / mux is set
+ // - spi device is bound to the driver
+ // @param image the component image
+ // @param image_size size of 'image'
+ // @returns true on success
+ sdbusplus::async::task<bool> writeSPIFlashWithFlashcp(
+ const uint8_t* image, size_t image_size) const;
+
// @returns nullopt on error
std::optional<std::string> getMTDDevicePath() const;
};