i2c: Implement write function

Implement I2CDevice::write() by invoking i2c_smbus_write_xxx() APIs.
The code is referenced from i2c-tools' i2cset.c:

 https://github.com/ev3dev/i2c-tools/blob/ev3dev-stretch/tools/i2cset.c

Tested: Verify on Witherspoon that it writes the PSU unlock upgrade
        command and boot flag successfully.

Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I9fb014c787ef3ebb2f7793a0d012b1d652ef069f
diff --git a/tools/power-utils/test/test_updater.cpp b/tools/power-utils/test/test_updater.cpp
index d2dfd11..e1b6a2e 100644
--- a/tools/power-utils/test/test_updater.cpp
+++ b/tools/power-utils/test/test_updater.cpp
@@ -24,6 +24,7 @@
 
 using ::testing::_;
 using ::testing::An;
+using ::testing::Pointee;
 
 namespace updater
 {
@@ -95,10 +96,10 @@
     updater = std::make_unique<Updater>(psuInventoryPath, devPath, imageDir);
     updater->createI2CDevice();
     auto& i2c = getMockedI2c();
-    EXPECT_CALL(i2c, read(An<uint8_t&>()));
-    EXPECT_CALL(i2c, read(_, An<uint8_t&>()));
-    EXPECT_CALL(i2c, read(_, An<uint16_t&>()));
-    EXPECT_CALL(i2c, read(_, An<uint8_t&>(), _));
+
+    EXPECT_CALL(i2c, write(0xf0, 12, _));
+    EXPECT_CALL(i2c, write(0xf1, An<uint8_t>()));
+    EXPECT_CALL(i2c, read(0xf1, An<uint8_t&>()));
     updater->doUpdate();
 }
 
diff --git a/tools/power-utils/updater.cpp b/tools/power-utils/updater.cpp
index 2668030..4c6ed72 100644
--- a/tools/power-utils/updater.cpp
+++ b/tools/power-utils/updater.cpp
@@ -21,8 +21,10 @@
 #include "types.hpp"
 #include "utility.hpp"
 
+#include <chrono>
 #include <fstream>
 #include <phosphor-logging/log.hpp>
+#include <thread>
 
 using namespace phosphor::logging;
 namespace util = phosphor::power::util;
@@ -242,23 +244,26 @@
 
 int Updater::doUpdate()
 {
-    // TODO
-    uint8_t data;
-    uint8_t size;
-    uint16_t word;
-    std::vector<uint8_t> blockData(32);
+    using namespace std::chrono;
 
-    i2c->read(data);
-    printf("Read byte 0x%02x\n", data);
+    uint8_t data;
+    uint8_t unlockData[12] = {0x45, 0x43, 0x44, 0x31, 0x36, 0x30,
+                              0x33, 0x30, 0x30, 0x30, 0x34, 0x01};
+    uint8_t bootFlag = 0x01;
+    static_assert(sizeof(unlockData) == 12);
+
+    i2c->write(0xf0, sizeof(unlockData), unlockData);
+    printf("Unlock PSU\n");
+
+    std::this_thread::sleep_for(milliseconds(5));
+
+    i2c->write(0xf1, bootFlag);
+    printf("Set boot flag ret\n");
+
+    std::this_thread::sleep_for(seconds(3));
 
     i2c->read(0xf1, data);
-    printf("First read of 0x%02x, 0x%02x\n", 0xf1, data);
-
-    i2c->read(0xbd, word);
-    printf("Read word of 0x%02x, 0x%04x\n", 0xbd, word);
-
-    i2c->read(0x00, size, blockData.data()); // This throws on the device
-    printf("Read block data, size: %d\n", size);
+    printf("Read of 0x%02x, 0x%02x\n", 0xf1, data);
     return 0;
 }