openbmc_docs/architecture/code-update/code-update.md

420 lines
14 KiB
Markdown
Raw Normal View History

2024-12-23 14:53:31 +08:00
# OpenBMC Code Update
Two BMC Code layouts are available:
- Static, non-UBI layout
- UBI layout - enabled via `obmc-ubi-fs` distro feature
This document describes the code update that supports both layouts.
### Steps to Update
The following are the steps to update the BMC.
1. Get a BMC image tar: After building OpenBMC, you will end up with a set of
image files in `tmp/deploy/images/<platform>/`.
- The UBI layout image is
`obmc-phosphor-image-<platform>-<timestamp>.ubi.mtd.tar`
- The static layout image is
`obmc-phosphor-image-<platform>-<timestamp>.static.mtd.tar`
The BMC tar image contains 5 files: u-boot, kernel, ro, and rw partitions and
the MANIFEST file, which contains information about the image such as the image
purpose, version, KeyType (Key type used for signature), HashType (SHA type used
for key generation) and MachineName (name of machine used while building image,
and this will be used for validation of image build). A MANIFEST file might look
like
```
purpose=xyz.openbmc_project.Software.Version.VersionPurpose.BMC
version=2.7.0-dev
KeyType=OpenBMC
HashType=RSA-SHA256
MachineName=tiogapass
```
2. Transfer the generated BMC image to the BMC via one of the following methods:
- Method 1: Via Redfish Upload:
https://github.com/openbmc/docs/blob/master/REDFISH-cheatsheet.md#firmware-update.
If using this method skip ahead to step 5!
- Method 2: Via scp: Copy the generated BMC image to the `/tmp/images/`
directory on the BMC.
- Method 3: Via REST Upload:
https://github.com/openbmc/docs/blob/master/rest-api.md#uploading-images
- Method 4: Via TFTP: Perform a POST request to call the `DownloadViaTFTP`
method of `/xyz/openbmc_project/software`.
Methods 3 and 4 require additional options in bmcweb to be enabled.
3. Note the version id generated for that image file. The version id is a hash
value of 8 hexadecimal numbers, generated by SHA-512 hashing the version
string contained in the image and taking the first 8 characters. Get the
version id via one of the following methods:
- Method 1: From the BMC command line, note the most recent directory name
created under `/tmp/images/`, in this example it'd be `2a1022fe`:
```
# ls -l /tmp/images/
total 0
drwx------ 2 root root 80 Aug 22 07:54 2a1022fe
drwx------ 2 root root 80 Aug 22 07:53 488449a2
```
- Method 2: This method _only_ works if there are no `Ready` images at the start
of transferring the image. Using the REST API, note the object that has its
Activation property set to Ready, in this example it'd be `2a1022fe`:
```
$ curl -b cjar -k https://${bmc}/xyz/openbmc_project/software/enumerate
{
"data": {
"/xyz/openbmc_project/software/2a1022fe": {
"Activation": "xyz.openbmc_project.Software.Activation.Activations.Ready",
```
- Method 3: Calculate the version id beforehand from the image with:
```
tar xfO <BMC tar image> MANIFEST | sed -ne '/version=/ {s/version=//;p}' | head -n1 | tr -d '\n' | sha512sum | cut -b 1-8
```
4. To initiate the update, set the `RequestedActivation` property of the desired
image to `Active`, substitute `<id>` with the hash value noted on the
previous step, this will write the contents of the image to the BMC chip via
one of the following methods:
- Method 1: From the BMC command line:
```
busctl set-property xyz.openbmc_project.Software.BMC.Updater \
/xyz/openbmc_project/software/<id> \
xyz.openbmc_project.Software.Activation RequestedActivation s \
xyz.openbmc_project.Software.Activation.RequestedActivations.Active
```
- Method 2: Using the REST API:
```
curl -b cjar -k -H "Content-Type: application/json" -X PUT \
-d '{"data":
"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}' \
https://${bmc}/xyz/openbmc_project/software/<id>/attr/RequestedActivation
```
5. (Optional) Check the flash progress. This interface is only available during
the activation progress and is not present once the activation is completed
via one of the following:
- Method 1: From Redfish: A task is returned from the Redfish upload. The task
can be used to monitor the progress.
```
curl -k https://${bmc}/redfish/v1/TaskService/Tasks/0
```
- Method 2: From the BMC command line:
```
busctl get-property xyz.openbmc_project.Software.BMC.Updater \
/xyz/openbmc_project/software/<id> \
xyz.openbmc_project.Software.ActivationProgress Progress
```
- Method 3: Using the REST API:
```
curl -b cjar -k https://${bmc}/xyz/openbmc_project/software/<id>/attr/Progress
```
6. Check that the activation is complete by verifying the "Activation" property
is set to "Active" via one of the following methods:
- Method 1: From Redfish: Check the task returned from the Redfish upload.
```
curl -k https://${bmc}/redfish/v1/TaskService/Tasks/0
```
- Method 2: From the BMC command line:
```
busctl get-property xyz.openbmc_project.Software.BMC.Updater \
/xyz/openbmc_project/software/<id> \
xyz.openbmc_project.Software.Activation Activation
```
- Method 3: Using the REST API:
```
curl -b cjar -k https://${bmc}/xyz/openbmc_project/software/<id>
```
7. Reboot the BMC for the image to take effect.
- Method 1: From Redfish: If ApplyTime was set to "Immediate", the BMC will
automatically reboot:
https://github.com/openbmc/docs/blob/master/REDFISH-cheatsheet.md#firmware-applytime.
To reboot the BMC manually see:
https://github.com/openbmc/docs/blob/master/REDFISH-cheatsheet.md#bmc-reboot.
- Method 2: From the BMC command line:
```
reboot
```
- Method 3: Using the REST API:
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X PUT \
-d '{"data": "xyz.openbmc_project.State.BMC.Transition.Reboot"}' \
https://${bmc}/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition
```
### Associations
In addition to all software images, several associations are listed at
`/xyz/openbmc_project/software/`:
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET \
https://${bmc}/xyz/openbmc_project/software/
{
"data": [
"/xyz/openbmc_project/software/46e65782",
"/xyz/openbmc_project/software/493a00ad",
"/xyz/openbmc_project/software/88c153b1",
"/xyz/openbmc_project/software/active",
"/xyz/openbmc_project/software/functional"
],
"message": "200 OK",
"status": "ok"
}
```
1. A "functional" association to the "running" BMC and host images
There is only one functional association per BMC and one functional association
per host. The functional/running BMC image is the BMC image with the lowest
priority when rebooting the BMC. The functional image does not update until the
BMC is rebooted. The functional host image behaves the same way except that it
updates on a power on or reboot of the host.
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET \
https://${bmc}/xyz/openbmc_project/software/functional
{
"data": {
"endpoints": [
"/xyz/openbmc_project/software/46e65782",
"/xyz/openbmc_project/software/493a00ad"
]
},
"message": "200 OK",
"status": "ok"
}
```
2. An "active" association to the active BMC and host images
Note: Several BMC images might be active, this is true for the host images as
well.
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET \
https://${bmc}/xyz/openbmc_project/software/active
{
"data": {
"endpoints": [
"/xyz/openbmc_project/software/46e65782",
"/xyz/openbmc_project/software/493a00ad",
"/xyz/openbmc_project/software/88c153b1"
]
},
"message": "200 OK",
"status": "ok"
}
```
3. An "updateable" association to the programmable components
This is used for identifying firmware components which are programmable via BMC
OOB interfaces like Redfish/IPMI. All updateable firmware components must expose
the updateable association so that upper applications like Redfish/IPMI will
know about updateable firmwares.
To know the updateable software components:
```
# busctl call xyz.openbmc_project.ObjectMapper \
/xyz/openbmc_project/software/updatable org.freedesktop.DBus.Properties \
Get ss xyz.openbmc_project.Association endpoints
v as 1 "/xyz/openbmc_project/software/1201fc36"
```
Redfish interface uses 'updateable' association in SoftwareInventory schema.
4. An additional association is located at
`/xyz/openbmc_project/software/<id>/inventory` for "associating" a software
image with an inventory item.
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET \
https://${bmc}/xyz/openbmc_project/software/493a00ad/inventory
{
"data": {
"endpoints": [
"/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc"
]
},
"message": "200 OK",
"status": "ok"
}
```
To get all software images associated with an inventory item:
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET \
https://${bmc}/xyz/openbmc_project/inventory/system/chassis/activation
{
"data": {
"endpoints": [
"/xyz/openbmc_project/software/46e65782"
]
},
"message": "200 OK",
"status": "ok"
}
```
### MANIFEST File
A file named "MANIFEST" must be included in any image tar uploaded, downloaded
via TFTP, or copied to the BMC.
The MANIFEST file format must be key=value (e.g. version=v1.99.10). It should
include the following fields:
- version - The version of the image
- purpose - The image's purpose (e.g.
xyz.openbmc_project.Software.Version.VersionPurpose.BMC or
xyz.openbmc_project.Software.Version.VersionPurpose.Host). Accepted purpose
values can be found at
[Version interface](https://github.com/openbmc/phosphor-dbus-interfaces/blob/6f69ae5b33ee224358cb4c2061f4ad44c6b36d70/xyz/openbmc_project/Software/Version.interface.yaml)
under "VersionPurpose" values.
- MachineName - The name of machine (platform) for which this image is built
for. This value will be compared against OPENBMC_TARGET_MACHINE value defined
in os-release file of running image. Image will not be upgraded if this check
fails. For backward compatibility this check skips failure if MachineName is
not defined for current released images but it will be made mandatory field
from 2.9 onward releases.
Other optional fields are:
- extended_version - A more detailed version, which could include versions of
different components in the image.
### Deleting an Image
To delete an image:
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" \
-X POST https://${bmc}/xyz/openbmc_project/software/<$id>/action/delete \
-d "{\"data\": [] }"
```
Note: The image must be non-functional ("non-running").
To delete all non-functional images, whether BMC or host images:
```
curl -c cjar -b cjar -k -H "Content-Type: application/json" \
-X POST https://${bmc}/xyz/openbmc_project/software/action/deleteAll \
-d "{\"data\": [] }"
```
### Software Field Mode
Field mode is meant for systems shipped from manufacturing to a customer. Field
mode offers a way to provide security and ensure incorrect patches don't get
loaded on the system by accident. The software implementation of the field mode
interface disables patching of the BMC by not mounting `/usr/local`, which in
turn disables host patching at `/usr/local/share/pnor/`. Enabling field mode is
intended to be a one-way operation which means that once enabled, there is no
REST API provided to disable it.
Field mode can be enabled by running the following command:
```
curl -b cjar -k -H 'Content-Type: application/json' -X PUT -d '{"data":1}' \
https://${bmc}/xyz/openbmc_project/software/attr/FieldModeEnabled
```
Although field mode is meant to be a one-way operation, it can be disabled by a
user with admin privileges by running the following commands on the BMC:
```
fw_setenv fieldmode
systemctl unmask usr-local.mount
reboot
```
More information on field mode can be found here:
https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Control/FieldMode.interface.yaml
### Software Factory Reset
Software factory reset resets the BMC and host firmware to its factory state by
clearing out any read/write data. To software factory reset run the following
command and then reboot the BMC:
```
curl -b cjar -k -H 'Content-Type: application/json' -X POST -d '{"data":[]}' \
https://${bmc}/xyz/openbmc_project/software/action/Reset
```
The factory reset on the BMC side will clear `/var`, `/home`, and `/etc`. On the
host side, the factory reset will clear the read/write volume for each host
image on the system, clear the shared preserve host volume, pnor-prsv, and clear
any host patches located in `/usr/local/share/pnor/`.
The factory reset interface can be found here:
https://github.com/openbmc/phosphor-dbus-interfaces/blob/02b39246d45ea029a1652a49cc20eab7723dd63b/xyz/openbmc_project/Common/FactoryReset.interface.yaml
### Image Storage Location
#### Static layout
When a BMC image is activated, each `image-<name>` is written to the BMC chip's
partitions indicated by the `<name>`:
- image-u-boot
- image-kernel
- image-rofs
- image-rwfs
#### UBI layout
When a BMC image is activated (i.e. when "RequestedActivation" is set to
"Active"), UBI volumes are created on the BMC chip for the image. The alternate
BMC chip can also be used to store images. This is determined by "BMC_RO_MTD".
Using both the alternate BMC chip and the BMC chip allows for multiple BMC
images to be stored. By default, only the BMC chip is used. To use both, set
"BMC_RO_MTD" to "alt-bmc+bmc".
### Implementation
More information about the implementation of the code update can be found at
https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Software
and https://github.com/openbmc/phosphor-bmc-code-mgmt