# Design proposal: UEFI Capsule support

**URL:** <https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278>\
**Category:** General Discussions\
**Tags:** yocto, uefi, capsule\
**Created:** [September 27, 2022, 9:01am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278 "2022-09-27T09:01:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [September 27, 2022, 9:01am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/1 "2022-09-27T09:01:20Z")

</div>

# **UEFI Capsule update proposal**

## **1. Why do we need this?**

Today Mender has no ability to update System Firmware. Whole firmware single image updates will be a step forwards from today’s firmware update capability, but the end goal should be to support partial firmware updates where only one part of the installed firmware is updated. Therefore, it would be ideal to use a UEFI capsule delivery mechanism to only update only specific firmware(s) on a device when needed by adding some intelligence on the device which has access to the information of ESRT table (GUID’s with their versions).

Benefits:

- Specific devices are sent the update if they are out of date.
- Rather than updating the whole image (bank), they only update specific GUID → firmware(s)

The capsule update process has the sequence of events as shown in this [figure page 3, 4 and 5](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf "UEFI specification 2.9 (Mar 2021)"). The detailed UEFI platform initialization (PI) firmware process can be found [here](https://uefi.org/sites/default/files/resources/PI_Spec_1_6.pdf "UEFI Platform initialization (PI) specification").

## **2. Mender Server – The deployment microservice**

The deployment microservice is the one that is responsible for deciding if an artifact must be pushed to a device or not. If an update is required, the microservice monitors the deployment for each device until it is completed. Please note when the device is provisioned, pre-existing **provides** needs to be present for it to deploy the update, because the board might have single or multiple firmware image(s) containing their own version information.

**There are no changes required for deployment service** , but we must specify the **provides** and **depends** field to give the top layer control over what version of firmware(s) are pushed on to the device when generating the mender artifact.

**For example:**

```json
provides: {
<custom update module>.<GUID1>-:1.0
<custom update module>.<GUID2>-:1.2
}

depends: {
<custom update module>.<GUID1>:0.9
<custom update module>.<GUID2>:1.1
}

```

### **2.1 Artifact format for UEFI capsule update**

UEFI capsule update works through custom update module scripts so we need to create an artifact of type module-image. The firmware versioning information is encoded in the **provides** and **depends** field of the artifact which is used by the deployment microservice to decide if the artifact needs to be pushed to the device or not.

**For example** :

```auto
./mender-artifact write module-image -t <platform> -o capsule.mender -T uefi-capsule -n <sha or md5> -f <platform>-capsule --no-default-clears-provides --depends KEY:VALUE --provides KEY:VALUE
-t The compatible device type of this Mender Artifact.
-o The path where to place the output Mender Artifact. This should always have a `.mender` suffix.
-T The payload type. It should be the same as the Update Module name and corresponds to the filename of the script which is present inside the /usr/share/mender/modules/v3 directory.
-n The name of the Mender Artifact. (This could sha or md5 of uefi image)
-f The path to the file(s) to send to the device(s) in the update.
--no-default-software-version Disable the software version field for compatibility with old clients
--provides KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact\_provides section. Can be given multiple times
--depends KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact\_depends section. Can be given multiple times

```

Depending on various **update scenarios** mentioned below we need to modify the above command.

### **2.2 Update scenarios**

| **Scenario** | **Mender artifact** | **Pre-existing provides on the device** | **Update scenario** |
| --- | --- | --- | --- |
| 1 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | uefi-firmware.uefi-capsule.tfa: **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **2.0** | uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.5** | uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **3.0** | uefi-firmware.uefi-capsule.tfm : **2.7** |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | This update can be used when all the firmware images must be updated on the device. As seen in the diagram, the mender artifact has the latest firmware versions in the **provides** compared to the artifact **depends**. This artifact will be installed on all devices which have provides matching the artifact’s **depends**. If any **depends** does not match a **provides** on the device, the server is not going to push the artifact to the device. |
| 2 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | |
| uefi-firmware.uefi-capsule.edk2 : **2.0** | |
| uefi-firmware.uefi-capsule.optee : **1.5** | |
| uefi-firmware.uefi-capsule.tfm : **3.0** | |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | In this case, the artifact will be pushed to all the available devices as there are no **depends** in the artifact. Since the pushed artifact is containing all the new artifact versions, the mender client will install all the firmware capsules and update the device **provides** field. If any firmware image installation fails, the device will reject all the firmware images in the capsule and report the update as unsuccessful to the server. |
| 3 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | uefi-firmware.uefi-capsule.tfa: **1.6** |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | In this case, the artifact contains only a single firmware image in the capsule and also has a **depends** field. Only those devices with provides containing **tfa** 1.6 will receive the artifact. Upon successful installation, only the **tfa**  **provides** information on the device will be updated. If the installation fails, then the mender client should report to the server. |
| 4 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | In this case, the mender artifact contains only a single firmware image with **provides**  **tfa** 1.7 which will be pushed to all the devices as there is no artifact **depends** - device provides matching. If the device already has a **tfa** version greater than 1.7 then the artifact should be rejected. Since the device in this case has **tfa** 1.6, the installation will be successful. |
| 5 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | uefi-firmware.uefi-capsule.tfa: **1.6** |
| | uefi-firmware.uefi-capsule.edk2 : **1.0** |
| | uefi-firmware.uefi-capsule.optee : **1.2** |
| | uefi-firmware.uefi-capsule.tfm : **2.7** |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | In this case, the mender artifact contains only a single firmware image capsule and has **depends** for multiple firmware images. This update can be used when a firmware image has dependencies on other firmware image versions. In the current scenario, the update will be successful as **provides** , **depends** match and **tfa** version is higher than the currently installed version. |
| 6 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | uefi-firmware.uefi-capsule.tfa: **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **2.0** | uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.5** | uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **3.0** | uefi-firmware.uefi-capsule.tfm : **2.7** |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.3** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | This is a negative case, where the update fails. Since one of the **depends** on the artifact does not match any **provides** on the device, the installation aborts. |
| 7 | depends

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | uefi-firmware.uefi-capsule.tfa: **1.6** |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.2** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | This is again a negative update scenario, where the single **depends** field does not match any **provides** on the device on the artifact. The artifact in this case can only be pushed to device with **tfa** 1.6 version. |
| 8 | !

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.7** | |
| uefi-firmware.uefi-capsule.edk2 : **2.0** | |
| uefi-firmware.uefi-capsule.optee : **1.5** | |
| uefi-firmware.uefi-capsule.tfm : **1.7** | |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | This is a negative update case. The artifacts firstly do not contain any **depends** field. So all device receive the artifact. But in the current scenario, the **tfm** version in the artifact is older than the one in the artifact. So all the firmware images in the artifact should be rejected and the client reports the failure status to the server. |
| 9 | 

| provides | depends |
| --- | --- |
| uefi-firmware.uefi-capsule.tfa : **1.1** | |

 | 

| provides |
| --- |
| uefi-firmware.uefi-capsule.tfa : **1.6** |
| uefi-firmware.uefi-capsule.edk2 : **1.0** |
| uefi-firmware.uefi-capsule.optee : **1.2** |
| uefi-firmware.uefi-capsule.tfm : **2.7** |

 | This is again a similar negative update scenario. In this case, the **tfa** version is older than the one installed on the device. So even though the artifact gets pushed the client should not install the firmware image. |

### **2.3 Pre-existing provides on the device**

For the update scenarios explained above to work as expected, we need to have the device provisioned with **provides**. This feature is currently missing on the meta-mender yocto [repository](https://github.com/mendersoftware/meta-mender). There is a MENDER\_ARTIFACT\_PROVIDES yocto variable available but this only adds the provides information to the mender artifact but not the compiled image. This query was posted in the mender community and the discussion can be found [here](https://hub.mender.io/t/apply-preexisting-provides-to-compiled-mender-uefiimg-image/4870).

This [feature](https://tracker.mender.io/browse/MEN-2582) has been planned for implementation within the mender community. The approach is to have an bootstrap.mender artifact with the initial **provides** information included in the compiled image. This artifact will be installed by the mender client upon first boot to populate the **provides** information.

**Therefore, we need to implement a yocto class or script to use the tool to populate necessary details after the UEFI image has been created for a target device which would be wrapped as a mender artifact.**

## **Mender Client**

To support a UEFI capsule update, we need to develop a custom script which would be part of mender client to collect all the information related to firmware from the ESRT table and export as a json file before the update process begins. This is to maintain the information of previous firmware version(s) of the mender-client which would be used for performing a check after the update process. This script can also publish the details to the mender server if needed.

Example of [**custom inventory script**](https://docs.mender.io/client-installation/inventory)

**Example code snippet to read ESRT table and write a json file** :

```bash
#!/bin/bash

WORK\_DIR="/sys/firmware/efi/esrt"
OUTPUT\_FILE="esrt\_table.json"

write\_info() {
NUM\_ENTRIES=$(cat $WORK\_DIR/fw\_resource\_count)
if [-z "$NUM\_ENTRIES"]; then
    echo "Error: No entries found in ESRT table. Can not continue..."
    exit 1
fi

echo "$(cat <<EOF
{
    "fw\_resource\_count": $NUM\_ENTRIES,
    "fw\_resource\_count\_max": $(cat $WORK\_DIR/fw\_resource\_count\_max),
    "fw\_resource\_version": $(cat $WORK\_DIR/fw\_resource\_version),
    "entries": {
EOF
)" > $OUTPUT\_FILE

index=0
while [$index -lt $NUM\_ENTRIES]
do
    ENTRY\_PATH="$WORK\_DIR/entries/entry$index"
    echo "$(cat <<EOF
    "entry$index": {
        "capsule\_flags": "$(cat $ENTRY\_PATH/capsule\_flags)",
        "fw\_class": "$(cat $ENTRY\_PATH/fw\_class)",
        "fw\_type": $(cat $ENTRY\_PATH/fw\_type),
        "fw\_version": $(cat $ENTRY\_PATH/fw\_version),
        "last\_attempt\_status": $(cat $ENTRY\_PATH/last\_attempt\_status),
        "last\_attempt\_version": $(cat $ENTRY\_PATH/last\_attempt\_version),
        "lowest\_supported\_fw\_version": $(cat $ENTRY\_PATH/lowest\_supported\_fw\_version)
}
EOF
)" >> $OUTPUT\_FILE

if [$index -lt `expr $NUM\_ENTRIES - 1`]; then
truncate -s-1 $OUTPUT\_FILE
echo "," >> $OUTPUT\_FILE
else
echo "$(cat <<EOF
    }
}
EOF
)" >> $OUTPUT\_FILE
fi

index=`expr $index + 1`
done

}

if [-d "$WORK\_DIR"]; then
    echo "Reading the ESRT table from ${WORK\_DIR}..."
    if [-f "$OUTPUT\_FILE"]; then
        chmod a+rw $OUTPUT\_FILE
        rm -rf $OUTPUT\_FILE
    fi
    write\_info
    chmod a+rw $OUTPUT\_FILE
    echo "Output file - $(cd "$(dirname "$OUTPUT\_FILE")"; pwd -P)/$(basename "$OUTPUT\_FILE")"
else
    echo "Error: ${WORK\_DIR} not found. Can not continue."
    exit 1
fi

```

### **4. Creating a UEFI Update module**

The Update module follows Mender state machine workflow as described in the [state-machine-workflow](https://docs.mender.io/artifact-creation/create-a-custom-update-module#the-state-machine-workflow) . The current custom update modules are under this [repository](https://github.com/mendersoftware/mender-update-modules), which also hosts an artifact generation script for the custom update module. We are relying on mender-artifact tool to populate the necessary **provides** and **depends** fields.

An example of [Custom Update module](https://docs.mender.io/3.2/artifact-creation/create-a-custom-update-module#basic-example-file-copy-update-module) is already provided by mender with rollback feature. With rollback scenario, the initial investigation suggests that **LastAttemptVersion** and **LastAttemptStatus** from the [EFI\_SYSTEM\_RESOURCE\_ENTRY (section 23.4)](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf "UEFI specification 2.9 (Mar 2021)") should ensure that we are not running on trial state firmware after the firmware update.

**Since we would have a json file with ESRT information, the update module needs to verify ESRT Table with various GUID’s of the firmware versions to check if the update was successful and then only perform `Artifact commit`.**

### **Implementation stages**

**Stage I – All required firmware(s) or complete software image in UEFI Capsule**

- **Develop a script to read ESRT table.**
- **Develop yocto class or script which will package UEFI image into mender artifact.**
- **Develop UEFI update module which includes mender artifact generation script.**
- **Test the update module.**
- **Refactor - UEFI Update module with rollback scenario**
- **Test the update module with rollback scenario**

**Stage II – Single or multiple firmware(s) in UEFI Capsule (Phased firmware update)**

- **Refactor - UEFI Update module**
- **Test the update module.**
- **Refactor - UEFI Update module with rollback scenario**
- **Test the update module with rollback scenario**

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [September 27, 2022, 12:06pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/2 "2022-09-27T12:06:43Z")

</div>

@kacf Please could you share your thoughts on this and tag the necessary members to have a look at this? Thanks.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 5, 2022, 8:03am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/3 "2022-10-05T08:03:40Z")

</div>

Sorry for the delay, this was quite a lot to take in.

I think the proposal is very good, very similar to what I would have suggested myself. You are using provides and depends exactly as intended, I believe!

Probably I’m the main guy to look at this, but I’ll tag @eystein as well, just so he’s aware. I’m not sure if he will have any comments, but I know he’s looking a bit at UEFI support, though at a bit higher and more architectural level.

#### One comment about naming

You describe the `--no-default-software-version` flag, but in your command you have `--no-default-clears-provides`. I would recommend that you remove both, and instead use `--software-filesystem uefi-firmware --software-name edk2`. This aligns it better with your later examples, and sets up both the “provides” and the “clears provides” to support this use case.

Your naming would then change slightly: Instead of `uefi-firmware.uefi-capsule.edk2: 1.0`, you would have `uefi-firmware.edk2.name : 1.0`. Although strictly speaking your naming is not wrong, my suggestion has the advantage that it is more in line with what Mender expects, it will look better in the UI, and most likely you can stick to only the `--software-*` options, and avoid the `--provides` options altogether.

With this approach it is also possible to put other pieces of information under edk2, such as for example: `--provides uefi-firmware.edk2.checksum: abcdef`.

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [October 5, 2022, 11:28am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/4 "2022-10-05T11:28:24Z")

</div>

Tagging: @GowthamSK

Thanks for reviewing and tagging the necessary members.

> [@kacf](#):
>
> #### One comment about naming
> 
> You describe the `--no-default-software-version` flag, but in your command you have `--no-default-clears-provides`. I would recommend that you remove both, and instead use `--software-filesystem uefi-firmware --software-name edk2`. This aligns it better with your later examples, and sets up both the “provides” and the “clears provides” to support this use case.
> 
> Your naming would then change slightly: Instead of `uefi-firmware.uefi-capsule.edk2: 1.0`, you would have `uefi-firmware.edk2.name : 1.0`. Although strictly speaking your naming is not wrong, my suggestion has the advantage that it is more in line with what Mender expects, it will look better in the UI, and most likely you can stick to only the `--software-*` options, and avoid the `--provides` options altogether.
> 
> With this approach it is also possible to put other pieces of information under edk2, such as for example: `--provides uefi-firmware.edk2.checksum: abcdef`.

Considering your suggestion: I think the idea to use this kind of format `uefi-firmware.<firmware name>.<GUID of the firmware>:<version>` would be beneficial?. As firmware’s have a unique identification mentioned below:  
`FwClass - The firmware class field contains a GUID that identifies a firmware component that can be updated via UpdateCapsule(). This GUID must be unique within all entries of the ESRT.`  
It would be easy to identify GUID to their name in the provides?

```auto
./mender-artifact write module-image -t <platform> -o capsule.mender -T uefi-capsule -n <sha or md5> -f <platform-capsule> software-filesystem uefi-firmware --no-default-clears-provides --clears-provides uefi-firmware.<*> --depends KEY:VALUE --provides KEY:VALUE
-t The compatible device type of this Mender Artifact.
-o The path where to place the output Mender Artifact. This should always have a `.mender` suffix.
-T The payload type. It should be the same as the Update Module name and corresponds to the filename of the script which is present inside the /usr/share/mender/modules/v3 directory.
-n The name of the Mender Artifact. (This could sha or md5 of uefi image)
-f The path to the file(s) to send to the device(s) in the update.
--no-default-clear-provides Do not add any default clears_artifact_provides fields to Artifact payload
--clears-provides VALUE Add a clears_artifact_provides field to Artifact payload. Can be given multiple times
--provides KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact_provides section. Can be given multiple times
--depends KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact_depends section. Can be given multiple times
--software-filesystem VALUE If specified is used instead of rootfs-image

```

Please note: `--clears-provides uefi-firmware.<*>` should be similar to provides, so that it clears any existing provides.

Example:

```auto
./mender-artifact write module-image -t <platform> -o capsule.mender -T uefi-capsule -n <sha or md5> -f <platform-capsule> --software-filesystem uefi-firmware --no-default-clears-provides
--clears-provides uefi-firmware.tfa.<GUID> --depends uefi-firmware.tfa.<GUID>:15 --provides uefi-firmware.tfa.<GUID>:16
--clears-provides uefi-firmware.edk2.<GUID> --depends uefi-firmware.edk2.<GUID>:10 --provides uefi-firmware.edk2.<GUID>:12
--clears-provides uefi-firmware.optee.<GUID> --depends uefi-firmware.optee.<GUID>:11 --provides uefi-firmware.optee.<GUID>:12

```

We are not sure whether we need to append `uefi-firmware` to the `provides` and `depends` fields in the above command, as we have specified it in `--software-filesystem`?

Unfortunately, I can’t update the proposal above as it has been disabled to take in more changes. So when we have finalised this design, I’ll post the complete this again.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 12, 2022, 7:43am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/5 "2022-10-12T07:43:37Z")

</div>

Just a clarification first, I made a mistake above: When I said `uefi-firmware.edk2.name`, I meant `uefi-firmware.edk2.version`. Sorry about that.

> [@jainvikas8](#):
>
> Considering your suggestion: I think the idea to use this kind of format `uefi-firmware.<firmware name>.<GUID of the firmware>:<version>` would be beneficial?

Aha, so you want both a name and a GUID. Is there a 1-to-1 relationship between the GUID and the name? Or can there be multiple GUIDs within the same name? If it’s the former, I might recommend something like this instead:

```auto
uefi-firmware.<firmware name>.version: <version>
uefi-firmware.<firmware name>.guid: <GUID of the firmware>

```

But if you want it the way you described, then I would recommend you use this:

```auto
uefi-firmware.<firmware name>.<GUID of the firmware>.version: <version>

```

Note the verbatim `version` in there. This is important for clear-provides to work correctly. But I think it will not render correctly in the UI, because it does not yet support multi-level software versions (this is coming though).

Your existing proposal will work just fine for dependency resolution though. I’m mainly concerned with how it will look in the UI.

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [October 12, 2022, 9:42am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/6 "2022-10-12T09:42:35Z")

</div>

Thanks for the reply.  
`< firmware name >` is just an alias and can be the same (very low probability), as people can decide what they want to call it.  
On the other hand `<GUID>` is unique, in that way 1:1 relationship can be established.

> [@kacf](#):
>
> ```auto
> uefi-firmware.<firmware name>.<GUID of the firmware>.version: <version>
> 
> ```

This should be good, but `.version` anyways is implied? so we could ignore that, therefore avoiding the complexity of having multiple fields.

So could go with the below?  
`uefi-firmware.<firmware name>.<GUID of the firmware>: <version>`

or

```auto
uefi-firmware.<GUID of the firmware>.version: <version>
uefi-firmware.<GUID of the firmware>.name: <firmware name>

```

I understand about the UI, considering GUID could be for example: `a2cb66ff-df5c-4a5c-aded-bf3dda35eb1a`, so it will not look good.

The way to differentiate the firmware GUID is required.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 12, 2022, 12:48pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/7 "2022-10-12T12:48:38Z")

</div>

> [@jainvikas8](#):
>
> This should be good, but `.version` anyways is implied? so we could ignore that, therefore avoiding the complexity of having multiple fields.

`.version` has a special meaning in the UI. That’s why I keep suggesting it. 🙂

> [@jainvikas8](#):
>
> ```auto
> uefi-firmware.<GUID of the firmware>.version: <version>
> uefi-firmware.<GUID of the firmware>.name: <firmware name>
> 
> ```

This one is perfect. It both captures the necessary information, and will look good in the UI.

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [October 12, 2022, 4:05pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/8 "2022-10-12T16:05:24Z")

</div>

> [@kacf](#):
>
> Note the verbatim `version` in there. This is important for clear-provides to work correctly. But I think it will not render correctly in the UI, because it does not yet support multi-level software versions (this is coming though).

Could you please link the issue? Will update the design proposal and resend it as a reply.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 13, 2022, 6:34am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/9 "2022-10-13T06:34:52Z")

</div>

It’s this one: [[MEN-5875] UI: Implement support for more than three levels of software provides - Northern.tech AS](https://tracker.mender.io/browse/MEN-5875).

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 13, 2022, 6:36am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/10 "2022-10-13T06:36:14Z")

</div>

It will work in your proposed variant though, because it has three levels, which is already supported.

---

<div class="post-metadata">

**Author:** ![GowthamSK](https://avatars.discourse-cdn.com/v4/letter/g/50afbb/32.png) [@GowthamSK](https://hub.mender.io/u/GowthamSK)\
**Post date:** [October 18, 2022, 9:23am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/11 "2022-10-18T09:23:34Z")

</div>

Hi @kacf.

Thanks for your input. I tried both the naming conventions discussed above and found the following,  
(Please note we are using Mender Server Version: 3.1.0)

1. Separate name and version

> uefi-firmware.GUID.version: v1  
> uefi-firmware.GUID.name: edk2

Sample Mender server view:  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/e/e6ea56d0648e22c5a0494831fe86bf205107787f.png)

Sample Client view:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/b/b83849a7ccce72ef5cce52a14a95a5b1bd56ec9c.jpeg)

The .name parameter does not appear in the UI.

1. Single field with name and version

> uefi-firmware.GUID.edk2.version: v1

Sample Mender server view:  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/1/136ae167c8d40b85875d5bb1b9c2319c9ec8d069.png)

Sample Client view:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/0/0b5f22c83b79723897b9fe837fdb9708d9627c5e.png)  
Only the GUID appears not the name in this case.

Is this expected? 🙂

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 19, 2022, 7:49am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/12 "2022-10-19T07:49:58Z")

</div>

Oh my apologies, I thought this would render correctly, but it appears that there is special handling in the UI for `rootfs-image`, but not for other software components.

However, I spoke to our UI developer and he confirmed that this will be fixed in [https://tracker.mender.io/browse/MEN-5875](https://tracker.mender.io/browse/MEN-5875), which he is working on as we speak, so it should not be long before this is live on Hosted Mender.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [October 21, 2022, 8:33am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/13 "2022-10-21T08:33:54Z")

</div>

@GowthamSK take a look at [this pull request](https://github.com/mendersoftware/gui/pull/3219) which has screenshots. We used your use case as inspiration! It’s being worked on right now, so maybe you can comment directly in there if you see something which doesn’t align with what you expect.

---

<div class="post-metadata">

**Author:** ![GowthamSK](https://avatars.discourse-cdn.com/v4/letter/g/50afbb/32.png) [@GowthamSK](https://hub.mender.io/u/GowthamSK)\
**Post date:** [October 21, 2022, 12:33pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/14 "2022-10-21T12:33:22Z")

</div>

Thanks for the update @kacf.  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/0/05fb7cf6a30fe4381c838f3b3513bbbcfd1d146b.png)

This representation of the provides and depends fields works for us.

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [October 26, 2022, 4:36pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/15 "2022-10-26T16:36:32Z")

</div>

# **UEFI Capsule update proposal**

## **1. Why do we need this?**

Today Mender has no ability to update System Firmware. Whole firmware single image updates will be a step forwards from today’s firmware update capability, but the end goal should be to support partial firmware updates where only one part of the installed firmware is updated. Therefore, it would be ideal to use a UEFI capsule delivery mechanism to only update only specific firmware(s) on a device when needed by adding some intelligence on the device which has access to the information of ESRT table (GUID’s with their versions).

Benefits:

- Specific devices are sent the update if they are out of date.
- Rather than updating the whole image (bank), they only update specific GUID → firmware(s)

The capsule update sequence is described here on pages [3](https://www.uefi.org/sites/default/files/resources/UEFI%20Fall%202018%20Intel%20UEFI%20Capsules.pdf#page=3 "System Firmware and Device Firmware Updates Using Unified Extensible Firmware Interface (UEFI) Capsules, Page 3"), [4](https://www.uefi.org/sites/default/files/resources/UEFI%20Fall%202018%20Intel%20UEFI%20Capsules.pdf#page=4 "System Firmware and Device Firmware Updates Using Unified Extensible Firmware Interface (UEFI) Capsules, Page 4"), and [5](https://www.uefi.org/sites/default/files/resources/UEFI%20Fall%202018%20Intel%20UEFI%20Capsules.pdf#page=5 "System Firmware and Device Firmware Updates Using Unified Extensible Firmware Interface (UEFI) Capsules, Page 5").  
The information on various other topics related to UEFI can be found here:

1. [UEFI platform initialization (PI)](https://uefi.org/sites/default/files/resources/PI_Spec_1_6.pdf "UEFI Platform initialization (PI) specification") firmware process.
2. [UEFI 2.9 specification](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf "UEFI specification 2.9 (Mar 2021)").
3. Additional [presentations and videos](https://uefi.org/learning_center/presentationsandvideos/ "UEFI presentation and videos").

## **2. Mender Server – The deployment microservice**

The deployment microservice is the one that is responsible for deciding if an artifact must be pushed to a device or not. If an update is required, the microservice monitors the deployment for each device until it is completed. Please note when the device is provisioned, pre-existing **provides** needs to be present for it to deploy the update, because the board might have single or multiple firmware image(s) containing their own version information.

**There are no changes required for deployment service** , but we must specify the **provides** and **depends** field to give the top layer control over what version of firmware(s) are pushed on to the device when generating the mender artifact.

**For example:**

```js
provides: {
<custom update module>.<GUID_1>.version:10
<custom update module>.<GUID_2>.version:12
}

depends: {
<custom update module>.<GUID_1>.version:9
<custom update module>.<GUID_2>.version:9
}

```

**Note** : The firmware versions are read from [ESRT table](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf#page=1084 "UEFI specification 2.9 (Mar 2021), Section 23.4") which is of integer format.

### **2.1 Artifact format for UEFI capsule update**

UEFI capsule update works through custom update module scripts so we need to create an artifact of type module-image. The firmware versioning information is encoded in the **provides** and **depends** field of the artifact which is used by the deployment microservice to decide if the artifact needs to be pushed to the device or not.

**For example** :

```shell
./mender-artifact write module-image -t <platform> -o capsule.mender -T uefi-capsule -n <sha or md5> -f <platform-capsule> --software-filesystem uefi-firmware --no-default-clears-provides
--clears-provides uefi-firmware.<GUID_1>.* --depends uefi-firmware.<GUID_1>.version:15 --provides uefi-firmware.<GUID_1>.version:16 --provides uefi-firmware.<GUID_1>.name:<firmware_name>
--clears-provides uefi-firmware.<GUID_2>.* --depends uefi-firmware.<GUID_2>.version:10 --provides uefi-firmware.<GUID_2>.version:12 --provides uefi-firmware.<GUID_2>.name:<firmware_name>
--clears-provides uefi-firmware.<GUID_3>.* --depends uefi-firmware.<GUID_3>.version:10 --provides uefi-firmware.<GUID_3>.version:13 --provides uefi-firmware.<GUID_3>.name:<firmware_name>
-t The compatible device type of this Mender Artifact.
-o The path where to place the output Mender Artifact. This should always have a `.mender` suffix.
-T The payload type. It should be the same as the Update Module name and corresponds to the filename of the script which is present inside the /usr/share/mender/modules/v3 directory.
-n The name of the Mender Artifact. (This could sha or md5 of uefi image)
-f The path to the file(s) to send to the device(s) in the update.
--no-default-clear-provides Do not add any default clears_artifact_provides fields to Artifact payload
--clears-provides VALUE Add a clears_artifact_provides field to Artifact payload. Can be given multiple times
--provides KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact_provides section. Can be given multiple times
--depends KEY:VALUE Generic KEY:VALUE which is added to the type-info -> artifact_depends section. Can be given multiple times
--software-filesystem VALUE If specified, it is used instead of rootfs-image

```

Depending on various **update scenarios** mentioned below we need to modify the above command.

### **2.2 Update scenarios**

**Note** : In the mentioned scenarios below, these are the following assumptions:

1. The GUID is a unique ID/name, which would be translated to `--provides <custom_update_module>.tfa.version:16` or `--provides <custom_update_module>.78dg-349765nf-45nf-vioj4.version:16`.
2. `.version` has a special meaning in the mender server UI.
3. We can have multiple KEY:VALUE pairs for `uefi-firmware.<GUID_1>.*`, where `GUID_1` is unique.  
For example:

```js
<custom_update_module>.<GUID_1>.version:<version>
<custom_update_module>.<GUID_1>.name:<firmware_name>

```

| **Scenario** | **Mender artifact** | **Pre-existing provides on the device** | **Update scenario** |
| --- | --- | --- | --- |
| 1 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | uefi-firmware.tfa.version: **16** |
| uefi-firmware.edk2.version : **20** | uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **15** | uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **30** | uefi-firmware.tfm.version : **27** |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | This update can be used when all the firmware images must be updated on the device. As seen in the diagram, the mender artifact has the latest firmware versions in the **provides** compared to the artifact **depends**. This artifact will be installed on all devices which have provides matching the artifact’s **depends**. If any **depends** does not match a **provides** on the device, the server is not going to push the artifact to the device. |
| 2 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | |
| uefi-firmware.edk2.version : **20** | |
| uefi-firmware.optee.version : **15** | |
| uefi-firmware.tfm.version : **30** | |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | In this case, the artifact will be pushed to all the available devices as there are no **depends** in the artifact. Since the pushed artifact is containing all the new artifact versions, the mender client will install all the firmware capsules and update the device **provides** field. If any firmware image installation fails, the device will reject all the firmware images in the capsule and report the update as unsuccessful to the server. |
| 3 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | uefi-firmware.tfa.version: **16** |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | In this case, the artifact contains only a single firmware image in the capsule and also has a **depends** field. Only those devices with provides containing **tfa** 16 will receive the artifact. Upon successful installation, only the **tfa**  **provides** information on the device will be updated. If the installation fails, then the mender client should report to the server. |
| 4 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | In this case, the mender artifact contains only a single firmware image with **provides**  **tfa** 17 which will be pushed to all the devices as there is no artifact **depends** - device provides matching. If the device already has a **tfa** version greater than 17 then the artifact should be rejected. Since the device in this case has **tfa** 16, the installation will be successful. |
| 5 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | uefi-firmware.tfa.version: **16** |
| | uefi-firmware.edk2.version : **10** |
| | uefi-firmware.optee.version : **12** |
| | uefi-firmware.tfm.version : **27** |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | In this case, the mender artifact contains only a single firmware image capsule and has **depends** for multiple firmware images. This update can be used when a firmware image has dependencies on other firmware image versions. In the current scenario, the update will be successful as **provides** , **depends** match and **tfa** version is higher than the currently installed version. |
| 6 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | uefi-firmware.tfa.version: **16** |
| uefi-firmware.edk2.version : **20** | uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **15** | uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **30** | uefi-firmware.tfm.version : **27** |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **13** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | This is a negative case, where the update fails. Since one of the **depends** on the artifact does not match any **provides** on the device, the installation aborts. |
| 7 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | uefi-firmware.tfa.version: **16** |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **12** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | This is again a negative update scenario, where the single **depends** field does not match any **provides** on the device on the artifact. The artifact in this case can only be pushed to device with **tfa** 16 version. |
| 8 | !

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **17** | |
| uefi-firmware.edk2.version : **20** | |
| uefi-firmware.optee.version : **15** | |
| uefi-firmware.tfm.version : **17** | |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | This is a negative update case. The artifacts firstly do not contain any **depends** field. So all device receive the artifact. But in the current scenario, the **tfm** version in the artifact is older than the one in the artifact. So all the firmware images in the artifact should be rejected and the client reports the failure status to the server. |
| 9 | 

| provides | depends |
| --- | --- |
| uefi-firmware.tfa.version : **11** | |

 | 

| provides |
| --- |
| uefi-firmware.tfa.version : **16** |
| uefi-firmware.edk2.version : **10** |
| uefi-firmware.optee.version : **12** |
| uefi-firmware.tfm.version : **27** |

 | This is again a similar negative update scenario. In this case, the **tfa** version is older than the one installed on the device. So even though the artifact gets pushed the client should not install the firmware image. |

### **2.3 Pre-existing provides on the device**

For the update scenarios explained above to work as expected, we need to have the device provisioned with **provides**. This feature is currently missing on the meta-mender yocto [repository](https://github.com/mendersoftware/meta-mender "Meta-mender repository"). There is a MENDER\_ARTIFACT\_PROVIDES yocto variable available but this only adds the provides information to the mender artifact but not the compiled image. This query was posted in the mender community and the discussion can be found [here](https://hub.mender.io/t/apply-preexisting-provides-to-compiled-mender-uefiimg-image/4870 "Query 4890").

This [feature](https://tracker.mender.io/browse/MEN-2582 "MEN-2582") has been planned for implementation within the mender community. The approach is to have an bootstrap.mender artifact with the initial **provides** information included in the compiled image. This artifact will be installed by the mender client upon first boot to populate the **provides** information.

**Therefore, we need to implement a yocto class or script to use the tool to populate necessary details after the UEFI image has been created for a target device which would be wrapped as a mender artifact.**

## **3. Mender Client**

To support a UEFI capsule update, we need to develop a custom script which would be part of mender client to collect all the information related to firmware from the ESRT table and export as a json file before the update process begins. This is to maintain the information of previous firmware version(s) of the mender-client which would be used for performing a check after the update process. This script can also publish the details to the mender server if needed.

Example of [**custom inventory script**](https://docs.mender.io/client-installation/inventory "Documentation - inventory")

**Example code snippet to read ESRT table and write a json file** :

```bash
#!/bin/bash

WORK_DIR="/sys/firmware/efi/esrt"
OUTPUT_FILE="esrt_table.json"

write_info() {
NUM_ENTRIES=$(cat $WORK_DIR/fw_resource_count)
if [-z "$NUM_ENTRIES"]; then
    echo "Error: No entries found in ESRT table. Can not continue..."
    exit 1
fi

echo "$(cat <<EOF
{
    "fw_resource_count": $NUM_ENTRIES,
    "fw_resource_count_max": $(cat $WORK_DIR/fw_resource_count_max),
    "fw_resource_version": $(cat $WORK_DIR/fw_resource_version),
    "entries": {
EOF
)" > $OUTPUT_FILE

index=0
while [$index -lt $NUM_ENTRIES]
do
    ENTRY_PATH="$WORK_DIR/entries/entry$index"
    echo "$(cat <<EOF
    "entry$index": {
        "capsule_flags": "$(cat $ENTRY_PATH/capsule_flags)",
        "fw_class": "$(cat $ENTRY_PATH/fw_class)",
        "fw_type": $(cat $ENTRY_PATH/fw_type),
        "fw_version": $(cat $ENTRY_PATH/fw_version),
        "last_attempt_status": $(cat $ENTRY_PATH/last_attempt_status),
        "last_attempt_version": $(cat $ENTRY_PATH/last_attempt_version),
        "lowest_supported_fw_version": $(cat $ENTRY_PATH/lowest_supported_fw_version)
}
EOF
)" >> $OUTPUT_FILE

if [$index -lt `expr $NUM_ENTRIES - 1`]; then
truncate -s-1 $OUTPUT_FILE
echo "," >> $OUTPUT_FILE
else
echo "$(cat <<EOF
    }
}
EOF
)" >> $OUTPUT_FILE
fi

index=`expr $index + 1`
done

}

if [-d "$WORK_DIR"]; then
    echo "Reading the ESRT table from ${WORK_DIR}..."
    if [-f "$OUTPUT_FILE"]; then
        chmod a+rw $OUTPUT_FILE
        rm -rf $OUTPUT_FILE
    fi
    write_info
    chmod a+rw $OUTPUT_FILE
    echo "Output file - $(cd "$(dirname "$OUTPUT_FILE")"; pwd -P)/$(basename "$OUTPUT_FILE")"
else
    echo "Error: ${WORK_DIR} not found. Can not continue."
    exit 1
fi

```

### **4. Creating a UEFI Update module**

The Update module follows Mender state machine workflow as described in the [state-machine-workflow](https://docs.mender.io/artifact-creation/create-a-custom-update-module#the-state-machine-workflow "state-machine-workflow") . The current custom update modules are under this [repository](https://github.com/mendersoftware/mender-update-modules "mender-ipdate-module repository"), which also hosts an artifact generation script for the custom update module. We are relying on mender-artifact tool to populate the necessary **provides** and **depends** fields.

An example of [Custom Update module](https://docs.mender.io/3.2/artifact-creation/create-a-custom-update-module#basic-example-file-copy-update-module "Custom Update module") is already provided by mender with rollback feature. With rollback scenario, the initial investigation suggests that **LastAttemptVersion** and **LastAttemptStatus** from the [EFI\_SYSTEM\_RESOURCE\_ENTRY (section 23.4)](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf#page=1084 "UEFI specification 2.9 (Mar 2021), Section 23.4") should ensure that we are not running on trial state firmware after the firmware update.

**Since we would have a json file with ESRT information, the update module needs to verify ESRT Table with various GUID’s of the firmware versions to check if the update was successful and then only perform `Artifact commit`.**

### **Implementation stages**

**Stage I – All required firmware(s) or complete software image in UEFI Capsule**

- **Develop a script to read ESRT table.**
- **Develop yocto class or script which will package UEFI image into mender artifact.**
- **Develop UEFI update module which includes mender artifact generation script.**
- **Test the update module.**
- **Refactor - UEFI Update module with rollback scenario**
- **Test the update module with rollback scenario**

**Stage II – Single or multiple firmware(s) in UEFI Capsule (Phased firmware update)**

- **Refactor - UEFI Update module**
- **Test the update module.**
- **Refactor - UEFI Update module with rollback scenario**
- **Test the update module with rollback scenario**

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [October 26, 2022, 4:39pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/16 "2022-10-26T16:39:06Z")

</div>

@kacf Updated the design proposal as per our discussion. Thanks.

---

<div class="post-metadata">

**Author:** ![oleorhagen](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/oleorhagen/32/297_2.png) [@oleorhagen](https://hub.mender.io/u/oleorhagen)\
**Post date:** [November 2, 2022, 2:54pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/17 "2022-11-02T14:54:51Z")

</div>

I am sorry for the long delay here @jainvikas8 - to me the proposal looks really nice.

@kacf is really busy for a few days more, but the will get back to you soon 🙂

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [November 7, 2022, 7:29am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/18 "2022-11-07T07:29:18Z")

</div>

Looks good to me! I have updated [Apply preexisting provides to compiled mender uefiimg image - #11 by kacf](https://hub.mender.io/t/apply-preexisting-provides-to-compiled-mender-uefiimg-image/4870/11).

---

<div class="post-metadata">

**Author:** ![jainvikas8](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/jainvikas8/32/1558_2.png) [@jainvikas8](https://hub.mender.io/u/jainvikas8)\
**Post date:** [January 13, 2023, 11:56am UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/19 "2023-01-13T11:56:53Z")

</div>

Hi @kacf ,

We are working on the UEFI capsule support feature for meta-mender, should we use `master-next` as our development branch here?

Thanks.

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [January 13, 2023, 12:12pm UTC](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278/20 "2023-01-13T12:12:01Z")

</div>

No, you don’t need that. Master-next has been merged now, and is compatible with kirkstone, so you should be able to use master directly.

[Next page](https://hub.mender.io/t/design-proposal-uefi-capsule-support/5278.md?page=2)
