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.