420 lines
14 KiB
Markdown
420 lines
14 KiB
Markdown
|
|
# 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
|