|
Firmware Management
|
-------------------
|
Copyright 2016 Google Inc.
|
Copyright 2016 Linaro Ltd.
|
|
Interface-Manifest
|
------------------
|
|
All firmware packages on the Modules or Interfaces are managed by a special
|
Firmware Management Protocol. To support Firmware Management by the AP, the
|
Interface Manifest shall at least contain the Firmware Management Bundle and a
|
Firmware Management Protocol CPort within it.
|
|
The bundle may contain additional CPorts based on the extra functionality
|
required to manage firmware packages.
|
|
For example, this is how the Firmware Management part of the Interface Manifest
|
may look like:
|
|
; Firmware Management Bundle (Bundle 1):
|
[bundle-descriptor 1]
|
class = 0x16
|
|
; (Mandatory) Firmware Management Protocol on CPort 1
|
[cport-descriptor 2]
|
bundle = 1
|
protocol = 0x18
|
|
; (Optional) Firmware Download Protocol on CPort 2
|
[cport-descriptor 1]
|
bundle = 1
|
protocol = 0x17
|
|
; (Optional) SPI protocol on CPort 3
|
[cport-descriptor 3]
|
bundle = 1
|
protocol = 0x0b
|
|
; (Optional) Component Authentication Protocol (CAP) on CPort 4
|
[cport-descriptor 4]
|
bundle = 1
|
protocol = 0x19
|
|
|
Sysfs Interfaces - Firmware Management
|
--------------------------------------
|
|
The Firmware Management Protocol interacts with Userspace using the character
|
device interface. The character device will be present in /dev/ directory
|
and will be named gb-fw-mgmt-<N>. The number <N> is assigned at runtime.
|
|
Identifying the Character Device
|
================================
|
|
There can be multiple devices present in /dev/ directory with name gb-fw-mgmt-N
|
and user first needs to identify the character device used for
|
firmware-management for a particular interface.
|
|
The Firmware Management core creates a device of class 'gb_fw_mgmt', which shall
|
be used by the user to identify the right character device for it. The class
|
device is created within the Bundle directory for a particular Interface.
|
|
For example this is how the class-device can be present:
|
|
/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_fw_mgmt/gb-fw-mgmt-0
|
|
The last name in this path: gb-fw-mgmt-0 is precisely the name of the char
|
device and so the device in this case will be:
|
|
/dev/gb-fw-mgmt-0.
|
|
Operations on the Char device
|
=============================
|
|
The Character device (gb-fw-mgmt-0 in example) can be opened by the userspace
|
application and it can perform various 'ioctl' operations on the device. The
|
device doesn't support any read/write operations.
|
|
Following are the IOCTLs and their data structures available to the user:
|
|
/* IOCTL support */
|
#define GB_FW_LOAD_METHOD_UNIPRO 0x01
|
#define GB_FW_LOAD_METHOD_INTERNAL 0x02
|
|
#define GB_FW_LOAD_STATUS_FAILED 0x00
|
#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01
|
#define GB_FW_LOAD_STATUS_VALIDATED 0x02
|
#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03
|
|
#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01
|
#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02
|
#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03
|
#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04
|
#define GB_FW_BACKEND_FW_STATUS_INT 0x05
|
#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06
|
#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07
|
|
#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01
|
#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02
|
#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03
|
#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04
|
#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05
|
|
|
struct fw_mgmt_ioc_get_intf_version {
|
__u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE];
|
__u16 major;
|
__u16 minor;
|
} __attribute__ ((__packed__));
|
|
struct fw_mgmt_ioc_get_backend_version {
|
__u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE];
|
__u16 major;
|
__u16 minor;
|
__u8 status;
|
} __attribute__ ((__packed__));
|
|
struct fw_mgmt_ioc_intf_load_and_validate {
|
__u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE];
|
__u8 load_method;
|
__u8 status;
|
__u16 major;
|
__u16 minor;
|
} __packed;
|
|
struct fw_mgmt_ioc_backend_fw_update {
|
__u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE];
|
__u8 status;
|
} __packed;
|
|
#define FW_MGMT_IOCTL_BASE 'S'
|
#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version)
|
#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version)
|
#define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate)
|
#define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update)
|
#define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int)
|
#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5)
|
|
1. FW_MGMT_IOC_GET_INTF_FW:
|
|
This ioctl shall be used by the user to get the version and firmware-tag of
|
the currently running Interface Firmware. All the fields of the 'struct
|
fw_mgmt_ioc_get_fw' are filled by the kernel.
|
|
2. FW_MGMT_IOC_GET_BACKEND_FW:
|
|
This ioctl shall be used by the user to get the version of a currently
|
running Backend Interface Firmware identified by a firmware-tag. The user is
|
required to fill the 'firmware_tag' field of the 'struct fw_mgmt_ioc_get_fw'
|
in this case. The 'major' and 'minor' fields are set by the kernel in
|
response.
|
|
3. FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE:
|
|
This ioctl shall be used by the user to load an Interface Firmware package on
|
an Interface. The user needs to fill the 'firmware_tag' and 'load_method'
|
fields of the 'struct fw_mgmt_ioc_intf_load_and_validate'. The 'status',
|
'major' and 'minor' fields are set by the kernel in response.
|
|
4. FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE:
|
|
This ioctl shall be used by the user to request an Interface to update a
|
Backend Interface Firmware. The user is required to fill the 'firmware_tag'
|
field of the 'struct fw_mgmt_ioc_get_fw' in this case. The 'status' field is
|
set by the kernel in response.
|
|
5. FW_MGMT_IOC_SET_TIMEOUT_MS:
|
|
This ioctl shall be used by the user to increase the timeout interval within
|
which the firmware must get loaded by the Module. The default timeout is 1
|
second. The user needs to pass the timeout in milliseconds.
|
|
6. FW_MGMT_IOC_MODE_SWITCH:
|
|
This ioctl shall be used by the user to mode-switch the module to the
|
previously loaded interface firmware. If the interface firmware isn't loaded
|
previously, or if another unsuccessful FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE
|
operation is started after loading interface firmware, then the firmware core
|
wouldn't allow mode-switch.
|
|
|
Sysfs Interfaces - Authentication
|
---------------------------------
|
|
The Component Authentication Protocol interacts with Userspace using the
|
character device interface. The character device will be present in /dev/
|
directory and will be named gb-authenticate-<N>. The number <N> is assigned at
|
runtime.
|
|
Identifying the Character Device
|
================================
|
|
There can be multiple devices present in /dev/ directory with name
|
gb-authenticate-N and user first needs to identify the character device used for
|
authentication a of particular interface.
|
|
The Authentication core creates a device of class 'gb_authenticate', which shall
|
be used by the user to identify the right character device for it. The class
|
device is created within the Bundle directory for a particular Interface.
|
|
For example this is how the class-device can be present:
|
|
/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_authenticate/gb-authenticate-0
|
|
The last name in this path: gb-authenticate-0 is precisely the name of the char
|
device and so the device in this case will be:
|
|
/dev/gb-authenticate-0.
|
|
Operations on the Char device
|
=============================
|
|
The Character device (/dev/gb-authenticate-0 in above example) can be opened by
|
the userspace application and it can perform various 'ioctl' operations on the
|
device. The device doesn't support any read/write operations.
|
|
Following are the IOCTLs and their data structures available to the user:
|
|
#define CAP_CERTIFICATE_MAX_SIZE 1600
|
#define CAP_SIGNATURE_MAX_SIZE 320
|
|
/* Certificate class types */
|
#define CAP_CERT_IMS_EAPC 0x00000001
|
#define CAP_CERT_IMS_EASC 0x00000002
|
#define CAP_CERT_IMS_EARC 0x00000003
|
#define CAP_CERT_IMS_IAPC 0x00000004
|
#define CAP_CERT_IMS_IASC 0x00000005
|
#define CAP_CERT_IMS_IARC 0x00000006
|
|
/* IMS Certificate response result codes */
|
#define CAP_IMS_RESULT_CERT_FOUND 0x00
|
#define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01
|
#define CAP_IMS_RESULT_CERT_CORRUPT 0x02
|
#define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03
|
|
/* Authentication types */
|
#define CAP_AUTH_IMS_PRI 0x00000001
|
#define CAP_AUTH_IMS_SEC 0x00000002
|
#define CAP_AUTH_IMS_RSA 0x00000003
|
|
/* Authenticate response result codes */
|
#define CAP_AUTH_RESULT_CR_SUCCESS 0x00
|
#define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01
|
#define CAP_AUTH_RESULT_CR_WRONG_EP 0x02
|
#define CAP_AUTH_RESULT_CR_NO_KEY 0x03
|
#define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04
|
|
|
/* IOCTL support */
|
struct cap_ioc_get_endpoint_uid {
|
__u8 uid[8];
|
} __attribute__ ((__packed__));
|
|
struct cap_ioc_get_ims_certificate {
|
__u32 certificate_class;
|
__u32 certificate_id;
|
|
__u8 result_code;
|
__u32 cert_size;
|
__u8 certificate[CAP_CERTIFICATE_MAX_SIZE];
|
} __attribute__ ((__packed__));
|
|
struct cap_ioc_authenticate {
|
__u32 auth_type;
|
__u8 uid[8];
|
__u8 challenge[32];
|
|
__u8 result_code;
|
__u8 response[64];
|
__u32 signature_size;
|
__u8 signature[CAP_SIGNATURE_MAX_SIZE];
|
} __attribute__ ((__packed__));
|
|
#define CAP_IOCTL_BASE 'C'
|
#define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid)
|
#define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate)
|
#define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate)
|
|
|
1. CAP_IOC_GET_ENDPOINT_UID:
|
|
This ioctl shall be used by the user to get the endpoint UID associated with
|
the Interface. All the fields of the 'struct cap_ioc_get_endpoint_uid' are
|
filled by the kernel.
|
|
2. CAP_IOC_GET_IMS_CERTIFICATE:
|
|
This ioctl shall be used by the user to retrieve one of the available
|
cryptographic certificates held by the Interface for use in Component
|
Authentication. The user is required to fill the 'certificate_class' and
|
'certificate_id' field of the 'struct cap_ioc_get_ims_certificate' in this
|
case. The other fields will be set by the kernel in response. The first
|
'cert_size' bytes of the 'certificate' shall be read by the user and others
|
must be discarded.
|
|
3. CAP_IOC_AUTHENTICATE:
|
|
This ioctl shall be used by the user to authenticate the Module attached to
|
an Interface. The user needs to fill the 'auth_type', 'uid', and 'challenge'
|
fields of the 'struct cap_ioc_authenticate'. The other fields will be set by
|
the kernel in response. The first 'signature_size' bytes of the 'signature'
|
shall be read by the user and others must be discarded.
|
|
|
Sysfs Interfaces - Firmware Download
|
------------------------------------
|
|
The Firmware Download Protocol uses the existing Linux Kernel's Firmware class
|
and the interface provided to userspace are described in:
|
Documentation/firmware_class/.
|
|
|
Sysfs Interfaces - SPI Flash
|
----------------------------
|
|
The SPI flash is exposed in userspace as a MTD device and is created
|
within the Bundle directory. For example, this is how the path may look like:
|
|
$ ls /sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/spi_master/spi32766/spi32766.0/mtd
|
mtd0 mtd0ro
|
|
|
Sample Applications
|
-------------------
|
|
The current directory also provides a firmware.c test application, which can be
|
referenced while developing userspace application to talk to firmware-management
|
protocol.
|
|
The current directory also provides a authenticate.c test application, which can
|
be referenced while developing userspace application to talk to
|
component authentication protocol.
|