DeviceManifest and ChainedManifest

As described in Assemble vs Build, KOS is an assembly-based platform that simply runs a collection of KAB files defined by a manifest. While this offers many advantages, it can make per-device customization difficult. For example, if every device needs custom content, doesn’t this mean we need a custom manifest for each device? KOS solves this by defining two types of manifests that can be used to create a manifest chain:

  • Device manifest: Defines the base software release for a device. It defines the KOS version, system application, default content, etc. Building a release from KOS Studio results in a device manifest. There can only be one device manifest in a chain and it is the base of the chain.
  • Chained manifest: Defines additional KABs that can added to a device manifest. A chained manifest can contain anything from content to additional applications. There can be multiple chained manifests in a chain, allowing external systems to customize what is deployed to a particular device.

While the software team creates a device manifest as part of creating a release, external systems can create chained manifests that reference the device manifest to add additional customization and functionality to a device.

Manifest sections

A manifest in KOS is fundamentally just a collection of sections, where a section is just a named list of KABs. This is reflected in KOS Studio when building a disk image. The editor allows users to create named sections and add KABs to each. The convention in KOS is that the name of a section defines how the KABs in the section should be used. KOS only defines two special section names:

  • kos.system: This section is expected to contain a KAB of type kos.system, which contains the system application for the device. When KOS boots, it will look for this section and find and load the system application.
  • kos.autostart.* : Any section name that starts with kos.autostart is expected to contain a KAB of type kos.app. This application will automatically start after the system application is started. Any number of autostart sections can exist, allowing various applications to be started at boot time without the system application needing to be involved in starting them.

As KOS only uses these two section names internally, developers are free to define their own naming conventions for their own needs.

Section names form the base of dynamic systems in KOS. By establishing section naming conventions and writing applications that use the conventions, KOS provides an easy way to dynamically discover new features and content in a well-defined and controlled way. For example, consider an application that expects custom content but must ship with default content if no custom content is available. Developers can define a convention where custom content is expected to be in a section named content while default content is in a section named content.default. The application code can first search for the section named content, and if it exists, use the KABs from that section. If it doesn’t exist, the application can check content.default and use that content instead. In fact, the KOS DDK application uses this approach to allow entirely new UI applications and plugins to be installed by simply adding KABs in sections with names that follow DDK conventions.

Sections are not limited to just single KABs such as application or content. In fact, in many cases, sections are used to group related KABs together for easy discovery. For example, consider a KOS application that loads from one KAB and needs to access additional KABs containing the UI, content, data, etc. By placing these KABs together in a single section, the application can search the section from which it was loaded to find all the related KABs without needing to create sections for each individual KAB.

Manifest chains

As described above, a manifest chain consists of zero or more chained manifests followed by a single device manifest. Each chained manifest links to the next manifest in the chain until the device manifest is reached. The device manifest represents the release produced by the software team, and each chained manifest in the chain represents additions to the release.

In order to ensure that chained manifests cannot break the device manifest, chained manifests can only contribute new sections to the base release. This ensures that it is impossible for a chained manifest to accidentally or intentionally replace any part of the underlying release. In fact, chained manifests can only contribute sections that the device manifest explicitly requests from the chain. This allows the release developers to have fine-grained control over how chained manifests can be used. These rules are defined by chained section references.

Chained section references

Chained section references are rules created in KOS Studio by developers of a release that define how chained manifests can contribute additional sections. These rules are then encoded into the device manifest at the time the release is created and cannot be changed without creating another release. This requires that the release developers understand and test upstream integrations before releasing the software. This also ensures that nothing unexpected is deployed on top of a release on a live production device.

A single chained section reference contains the following attributes:

  • Chained manifest name: Every chained manifest in a manifest chain must have a unique name. This property identifies which chained manifest the rule applies to. This limits a rule to a single chained manifest.
  • Chained manifest authority: Every chained manifest is a KAB file and contains the authority of the organization that signed it. By matching the authority of a rule with the authority of the chained manifest, we establish a chain of trust to the chained manifest. It also ensures that no one can forge the chained manifest.
  • Source section name: The name (single or wildcard) of sections in the chained manifest that can be imported into the device manifest.
  • Destination section name: Optional transformation to convert the source section name to a different destination name to match how the device software works.
  • Optional flag: If false, it indicates that the device cannot run properly without this section, and the entire chain should be considered unusable if missing.

If a chained section reference matches a section that already exists in the device manifest, the section will be ignored, guaranteeing the integrity of the underlying release.

Building manifest chains

The process of customizing a release for a particular device may span multiple teams or organizations. For example, one team may be responsible for adding custom content, while another is responsible for adding custom apps. Rather than require every team to contribute to a single central authority that knows all customizations to apply to a device, chained manifests allow each team to contribute their changes by adding a manifest to the chain. While this appears quite complex, it’s straightforward because manifests are just KAB files, and every KAB file has a unique UUID.

When constructing a new chained manifest, the only external information that is required is the UUID of the previous manifest in the chain. This means that as one system hands off a chain to another system, all it needs to provide about the chain is the UUID of the current head of the chain, but there is no need to pass the chain itself. The next system simply creates a manifest in the chain that includes the previous manifest UUID and the process continues. If each party publishes the manifest KAB files in a public location that the device can reach, the OTA process in KOS will simply download each KAB in the chain and process the entire chain on the device.