
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.
