Software: add initial software-version mgmt

Change-Id: I3b50488b8383c595b4b41375ea0d62d62bdc0eed
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/xyz/openbmc_project/FilePath.interface.yaml b/xyz/openbmc_project/FilePath.interface.yaml
new file mode 100644
index 0000000..355298a
--- /dev/null
+++ b/xyz/openbmc_project/FilePath.interface.yaml
@@ -0,0 +1,11 @@
+description: >
+    An interface which encapsulates a file-system path on the BMC.
+
+    Typically, this is added onto an existing object path to show a
+    relationship between the object, in the dbus namespace, and a file, in
+    the filesystem namespace.
+properties:
+    - name: Path
+      type: string
+      description: >
+        The filesystem path for the dbus object.
diff --git a/xyz/openbmc_project/Software/Activation.interface.yaml b/xyz/openbmc_project/Software/Activation.interface.yaml
new file mode 100644
index 0000000..37c9cb9
--- /dev/null
+++ b/xyz/openbmc_project/Software/Activation.interface.yaml
@@ -0,0 +1,49 @@
+description: >
+    Activation state for an associated xyz.openbmc_project.Software.Version.
+properties:
+    - name: Activation
+      type: enum[self.Activations]
+      description: >
+        The current Activation state of the Software.Version.
+    - name: RequestedActivation
+      type: enum[self.RequestedActivations]
+      description: >
+        The desired Activation state of the Software.Version.
+enumerations:
+    - name: Activations
+      description: >
+        The possible Activation states of the Software.Version.
+      values:
+        - name: NotReady
+          description: >
+            The system is still analyzing the Software.Version and is
+            currently unable to activate.
+        - name: Invalid
+          description: >
+            The Software.Version is invalid and unable to be activated.
+        - name: Ready
+          description: >
+            The Software.Version has been processed and is ready for
+            Activation.
+        - name: Activating
+          description: >
+            The Software.Version is in the process of being Activated.
+        - name: Active
+          description: >
+            The Software.Version is currently Active.
+        - name: Failed
+          description: >
+            The Software.Version failed during or after Activation.
+    - name: RequestedActivations
+      description: >
+        The possible RequestedActivation states of a Software.Version.
+      values:
+        - name: None
+          description: >
+            No action has been directed for this Software.Version.
+        - name: Active
+          description: >
+            The Software.Version has been requested for Activation.
+# TODO: Specify "EAGAIN" type error when requested is unable to be acted on
+#       due to current system state.  Currently, sdbusplus does not support
+#       errors on properties.
diff --git a/xyz/openbmc_project/Software/ActivationBlocksTransition.interface.yaml b/xyz/openbmc_project/Software/ActivationBlocksTransition.interface.yaml
new file mode 100644
index 0000000..51fbc8e
--- /dev/null
+++ b/xyz/openbmc_project/Software/ActivationBlocksTransition.interface.yaml
@@ -0,0 +1,13 @@
+description: >
+    Empty interface to indicate that the associated `Software.Version` should
+    prevent a state transition of the associated managed element while the
+    `Software.Version` is in `Activating` state.
+
+    The specific state transition(s) to prevent are left to the implementation.
+    A typical use of this would be to prevent (delay) the power-on of a
+    managed host while the BIOS is being updated.  The managed host, via
+    systemd transitions, might start the power-on sequence and then wait for
+    any object with this `ActivationBlocksTransition` interface to no longer be
+    in `Activating` state.  Causal ordering of dbus operations can prove that
+    no update is currently being performed and the power-on sequence may safely
+    continue.
diff --git a/xyz/openbmc_project/Software/ActivationProgress.interface.yaml b/xyz/openbmc_project/Software/ActivationProgress.interface.yaml
new file mode 100644
index 0000000..9f96246
--- /dev/null
+++ b/xyz/openbmc_project/Software/ActivationProgress.interface.yaml
@@ -0,0 +1,8 @@
+description: >
+    Activation progress for an associated xyz.openbmc_project.Software.Version.
+properties:
+    - name: Progress
+      type: uint8
+      description: >
+        An integer between 0 and 100 representing the percentage complete of
+        the current activation progress.
diff --git a/xyz/openbmc_project/Software/ExtendedVersion.interface.yaml b/xyz/openbmc_project/Software/ExtendedVersion.interface.yaml
new file mode 100644
index 0000000..0bcc419
--- /dev/null
+++ b/xyz/openbmc_project/Software/ExtendedVersion.interface.yaml
@@ -0,0 +1,7 @@
+description: >
+    An extended version string for a xyz.openbmc_project.Software.Version.
+properties:
+    - name: ExtendedVersion
+      type: string
+      description: >
+        Extended version of the level.
diff --git a/xyz/openbmc_project/Software/README.md b/xyz/openbmc_project/Software/README.md
new file mode 100644
index 0000000..f732e56
--- /dev/null
+++ b/xyz/openbmc_project/Software/README.md
@@ -0,0 +1,159 @@
+# Software Version Management and Image Update
+
+## Overview
+
+There are two types of processes involved in software version management and
+code update:
+
+1. *ImageManager* - This is a process which manages a collection of, likely
+                    temporary, images located somewhere in a file system.
+                    These are images which are available on the BMC for update.
+2. *ItemUpdater* - This is a process which manages specific storage elements,
+                   likely for an inventory item, to determine which software
+                   versions are installed onto that item.  A specific example of
+                   this would be a process that controls and updates the BIOS
+                   flash module for a managed host.
+
+A simple system design would be to include a single *ImageManager* and two
+*ItemUpdater*s: one for the BMC itself and one for the Host.
+
+### ImageManager
+
+The *ImageManager* would provide interfaces at `/xyz/openbmc_project/software`
+to allow additional images to be added to the BMC, such as Object.Add() for
+REST and DownloadViaTFTP() for TFTP.  The standard Object.Delete() interface
+would also be provided to facilitate removing images which are no longer
+needed.  Images maintained in the file system would be presented as a
+corresponding `/xyz/openbmc_project/software/<id>` object.
+
+It is assumed that the *ImageManager* has [at least] a bare minimum amount of
+parsing knowledge, perhaps due to a common image format, to allow it to
+populate all of the properties of `xyz.openbmc_project.Software.Version`.
+*ItemUpdater*s will likely listen for standard dbus signals to identify new
+images being created.
+
+### *ItemUpdater*
+
+The *ItemUpdater* is responsible for monitoring for new `Software.Version` elements
+being created to identify versions that are applicable to the inventory
+element(s) it is managing.  The *ItemUpdater* should dynamically create
+an `xyz.openbmc_project.Software.Activation` interface under
+`/xyz/openbmc_project/software/active/`, an association of type
+`{activation,software_version}` between the `Software.Version` and
+`Software.Activation`, and an association of type `{active_image,item}` between
+the `Inventory.Item` and `Software.Activation`.  Application of the software
+image is then handled through the `RequestedActivation` property of the
+`Software.Activation` interface.
+
+The *ItemUpdater* should, if possible, also create its own
+`xyz.openbmc_project.Software.Version` objects, and appropriate associations
+for software versions that are currently present on the managed inventory
+element(s).  This provides a mechanism for interrogation of the
+software versions when the *ImageManager* no longer contains a copy.
+
+## Details
+
+### Image Identifier
+
+The *ImageManager* and *ItemUpdater* should use a common, though perhaps
+implementation specific, algorithm for the `<id>` portion of a dbus path for
+each `Software.Version`.  This allows the same software version to be contained
+in multiple locations but represented by the same object path.
+
+A reasonable algorithm might be:
+`echo <Version.Version> <Version.Purpose> | sha512sum | cut -b 1-8`
+
+> TODO: May need an issue against the REST server to 'merge' two copies of
+>       a single dbus object into a single REST object.
+
+### Activation States
+
+`xyz.openbmc_project.Software.Activation` has a property Activation that can
+be in the following states:
+
+1. *NotReady* - Indicating that the *ItemUpdater* is still processing the
+                version and it is therefore not ready for activation.  This
+                might be used on an image that has a security header while
+                verification is being performed.
+2. *Invalid* - Indicating that, while the `Software.Version.Purpose` suggested
+               the image was valid for a managed element, a detailed analysis
+               by the *ItemUpdater* showed that it was not.  Reasons may
+               include image corruption detected via CRC or security
+               verification failure.  An event may be recorded with additional
+               details.
+3. *Ready* - Indicating that the `Software.Version` can be activated.
+4. *Activating* - Indicating that the `Software.Version` is in the process of
+                  being activated.
+5. *Active* - The `Software.Version` is active on the managed element.  Note
+              that on systems with redundant storage devices a version might
+              be *Active* but not the primary version.
+6. *Failed* - The `Software.Version` or the storage medium on which it is stored
+              has failed.  An event may be recorded with additional details.
+
+### Blocking State Transitions
+
+It is sometimes useful to block a system state transition while activations
+are being performed.  For example, we do not want to boot a managed host while
+its BIOS is being updated.  In order to facilitate this, the interface
+`xyz.openbmc_project.Software.ActivationBlocksTransition` may be added to any
+object with `Software.Activation` to indicate this behavior.  See that
+interface for more details.
+
+It is strongly suggested that any activations are completed prior to a managed
+BMC reboot.  This could be facilitated with systemd service specifiers.
+
+### Software Versions
+
+All version identifiers are implementation specific strings.  No format
+should be assumed.
+
+Some software versions are a collection of images, each with their own version
+identifiers.  The `xyz.openbmc_project.Software.ExtendedVersion` interface
+can be added to any `Software.Version` to express the versioning of the
+aggregation.
+
+### Activation Progress
+
+The `xyz.openbmc_project.Software.ActivationProgress` interface is provided
+to show current progress while a software version is *Activating*.  It is
+expected that an *ItemUpdater* will dynamically create this interface while
+the version is *Activating* and dynamically remove it when the activation is
+complete (or failed).
+
+### Handling Redundancy
+
+The `xyz.openbmc_project.Software.RedundancyPriority` interface is provided to
+express the relationship between two (or more) software versions activated for
+a single managed element.  It is expected that all installed versions are listed
+as *Active* and the `Priority` shows which version is the primary and which are
+available for redundancy.
+
+## REST use-cases
+
+### Find all software versions on the system, either active or available.
+
+List `/xyz/openbmc_project/software/`.  This list can be filtered to just
+active listing `.../software/active/` and following the `software_version`
+association to retrieve version information.
+
+### Find all software versions on a managed element.
+
+List `/xyz/openbmc_project/inventory/.../<item>/active_image` association.
+
+### Upload new version via REST
+
+HTTP PUT to `/xyz/openbmc_project/software/`.  *ImageManager* will assign the
+`<id>` when called for Object.Add().
+
+### Upload new version via ???
+
+Need additional interfaces defined for alternative upload methods.
+
+### Activate a version.
+
+Modify `RequestedActivation` to *Active* on the desired `Activation`.
+
+### Switch primary image.
+
+Set `Priority` to 0 on the desired `RedundancyPriority` interface.
+
diff --git a/xyz/openbmc_project/Software/RedundancyPriority.interface.yaml b/xyz/openbmc_project/Software/RedundancyPriority.interface.yaml
new file mode 100644
index 0000000..4f7ba27
--- /dev/null
+++ b/xyz/openbmc_project/Software/RedundancyPriority.interface.yaml
@@ -0,0 +1,23 @@
+description: >
+    The priority, for redundancy purposes, of the associated
+    xyz.openbmc_project.Software.Version.
+properties:
+    - name: Priority
+      type: uint8
+      description: >
+        The priority order specified for the associated Software.Version,
+        represented as a value between 0 (High) and 127 (Low).  Any value
+        above 127 has implementation-specific purpose.
+
+        Only one Software.Version, per associated device, may be at any
+        particular priority.  A requested priority change may cause other
+        Software.Versions to change priority.
+
+        A dual-sided redundancy model could be represented by two
+        Software.Version associations, one of which is at priority 0 and the
+        other at priority 1.  When a new image is Activated, the old
+        priority-1 association is deleted, the old priority-0 association
+        becomes priority-1, and the new image is assigned priority-0.
+# TODO: Specify "EAGAIN" type error when priority is unable to be modified
+#       due to current system state.  Currently, sdbusplus does not support
+#       errors on properties.
diff --git a/xyz/openbmc_project/Software/Version.interface.yaml b/xyz/openbmc_project/Software/Version.interface.yaml
new file mode 100644
index 0000000..f655af0
--- /dev/null
+++ b/xyz/openbmc_project/Software/Version.interface.yaml
@@ -0,0 +1,32 @@
+description: >
+    Simple definition of a Software or Firmware version.
+properties:
+    - name: Version
+      type: string
+      description: >
+        The version identifier.
+    - name: Purpose
+      type: enum[self.VersionPurpose]
+      description: >
+        The purpose of the version.  As in, what can it be used for or
+        applied to?
+enumerations:
+    - name: VersionPurpose
+      description: >
+        An enumeration of possible purposes of the version.
+      values:
+        - name: Unknown
+          description: >
+            The version is of unknown purpose.
+        - name: Other
+          description: >
+            The version is of some other purpose.
+        - name: System
+          description: >
+            The version is an aggregate for the system as a whole.
+        - name: BMC
+          description: >
+            The version is a version for the BMC.
+        - name: Host
+          description: >
+            The version is a version for a managed host.