usb: Add service and rules files

Trigger the USB code update via udev rules. Once a USB flash drive is
plugged into the BMC, an sda1 device is created, starting the USB
service file. Use SYSTEMD_WANTS since this service is long running.

Use BindsTo and After dev-sdX in the service file so that it
automatically stops when then USB drive is unplugged. Also add a
dependency to start after the Version service, which creates the
/tmp/images directory to copy the image to, and after the Updater
service, which handles the update.

Every time a USB drive is plugged, Linux creates a device sda1, sdb1,
sdc1, etc. Add rules for only the first 2 plug attempts, in case the
user made a mistake with the first USB drive as that seems sufficient.
If the second attempt does not work, the user would need to reboot the
BMC to retry.

Tested:
- Inserted USB key and verified the code update started and finished
  successfully:
Dec 03 19:29:44 p10bmc kernel:  sda: sda1
Dec 03 19:29:44 p10bmc kernel: sd 0:0:0:0: [sda] Attached SCSI removable disk
Dec 03 19:29:44 p10bmc systemd[1]: Created slice Slice /system/usb-code-update.
Dec 03 19:29:44 p10bmc systemd[1]: Started FW Code Update via USB sda1.
Dec 03 19:29:50 p10bmc phosphor-version-software-manager[544]:
Untaring /tmp/images/obmc-phosphor-image-rainier.ext4.mmc.tar to
/tmp/images/imageM6FtSg
...
Dec 03 19:30:42 p10bmc phosphor-image-updater[470]: BMC activation
has ended - BMC reboots are re-enabled.

- Removed USB key and verified usb sda1 service stopped:
Dec 03 20:30:52 p10bmc systemd[1]: usb-code-update@sda1.service:
Deactivated successfully.
Dec 03 20:30:52 p10bmc systemd[1]: Stopped FW Code Update via USB sda1.

- Reinserted USB key and verified code update started with device sdb1:
Dec 03 20:31:05 p10bmc kernel:  sdb: sdb1
Dec 03 20:31:05 p10bmc kernel: sd 1:0:0:0: [sdb] Attached SCSI removable disk
Dec 03 20:31:05 p10bmc systemd[1]: Started FW Code Update via USB sdb1.
Dec 03 20:31:11 p10bmc phosphor-version-software-manager[541]:
Untaring /tmp/images/obmc-phosphor-image-rainier.ext4.mmc.tar to
/tmp/images/imagey2OFWQ

- Removed USB key and verified usb sdb1 service stopped:
Dec 03 20:32:38 p10bmc systemd[1]: usb-code-update@sdb1.service:
Deactivated successfully.
Dec 03 20:32:38 p10bmc systemd[1]: Stopped FW Code Update via USB sdb1.

- Rebooted BMC with the USB drive inserted and verified the code update
  started when the BMC booted after the software services started, and
  the usb code update finished by the time the BMC reached Ready state:
[  OK  ] Started OpenBMC Software Update Manager.
[  OK  ] Started Phosphor Version Software Manager.
[  OK  ] Started FW Code Update via USB sda1.

- Verified the usb service exited on error and a code update can be
  restarted:
root@p10bmc:~# systemctl status usb-code-update@sda1
● usb-code-update@sda1.service - FW Code Update via USB sda1
     Loaded: loaded (/lib/systemd/system/usb-code-update@.service; static)
     Active: active (exited) since Fri 2021-12-03 21:26:19 UTC; 2min 31s ago
    Process: 523 ExecStart=/usr/bin/phosphor-usb-code-update --device
sda1 (code=exited, status=0/SUCCESS)
   Main PID: 523 (code=exited, status=0/SUCCESS)
Dec 03 21:26:19 p10bmc systemd[1]: Started FW Code Update via USB sda1.
Dec 03 21:26:19 p10bmc phosphor-usb-code-update[523]: Error when
copying /run/media/usb/sda1/obmc-phosphor-image-rainier.ext4.mmc.tar to
/tmp/images: filesystem error: cannot copy file: No …r.ext4.mmc.tar]
Dec 03 21:26:19 p10bmc phosphor-usb-code-update[523]: Failed to FW
Update via USB, usbPath:/run/media/usb/sda1

Signed-off-by: George Liu <liuxiwei@inspur.com>
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
Change-Id: I733f1b0f217f4fdd2f99cc6e8bbd602085da407d
diff --git a/usb/usb_manager.cpp b/usb/usb_manager.cpp
index ed831dd..5e225ac 100644
--- a/usb/usb_manager.cpp
+++ b/usb/usb_manager.cpp
@@ -2,6 +2,8 @@
 
 #include "usb_manager.hpp"
 
+#include <sys/mount.h>
+
 namespace phosphor
 {
 namespace usb
@@ -10,8 +12,13 @@
 bool USBManager::run()
 {
     fs::path dir(usbPath);
-    if (!fs::exists(dir))
+    fs::create_directories(dir);
+
+    auto rc = mount(devicePath.c_str(), usbPath.c_str(), "vfat", 0, NULL);
+    if (rc)
     {
+        lg2::error("Error ({ERRNO}) occurred during the mount call", "ERRNO",
+                   errno);
         return false;
     }