On 12/18/23 12:32, Dikshita Agarwal wrote:
> Host firmware interface (HFI) is well defined set of interfaces
> for communication between host driver and firmware.
> The command and responses are exchanged in form of packets.
> One or multiple packets are grouped under packet header.
> Each packet has packet type which describes the specific HFI
> and payload which holds the corresponding value for that HFI.
>
> Sys_init is the first packets sent to firmware, which initializes
> the firmware. Sys_image_version packet is to get the firmware
> version string.
>
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
[...]
> struct iris_core {
> @@ -65,6 +70,11 @@ struct iris_core {
> struct mem_desc sfr;
> struct mutex lock; /* lock for core structure */
> unsigned int use_tz;
> + u8 *packet;
> + u32 packet_size;
I'm not sure it's necessary to always keep a reference to the last
packet in the core struct, especially since it needs to be allocated
first anyway
> + u32 sys_init_id;
This looks like a hyper-defensive measure against some firmware
overtaking attacks.. Or a way to spot random/unwanted resets of
the firmware core..
Is it actually necessary, or does this just serve as a debug
feature?
> + u32 header_id;
Similar to above..
> + u32 packet_id;
And here.
I performed some quick CTRL-F-agge around the series and this is
never reset.. Can the firmware cope with this? What if I watch a
veeeery long youtube video that ends up creating more than
(1<<32)-1 HFI packets while playing?
> +
> +enum hfi_packet_host_flags {
> + HFI_HOST_FLAGS_NONE = 0x00000000,
> + HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001,
> + HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002,
> + HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004,
> + HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008,
BIT(n)?
> +};
> +
> +enum hfi_packet_firmware_flags {
> + HFI_FW_FLAGS_NONE = 0x00000000,
> + HFI_FW_FLAGS_SUCCESS = 0x00000001,
> + HFI_FW_FLAGS_INFORMATION = 0x00000002,
> + HFI_FW_FLAGS_SESSION_ERROR = 0x00000004,
> + HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008,
BIT(n)?
Konrad
@@ -6,6 +6,7 @@ iris-objs += iris_probe.o \
iris_state.o \
iris_helpers.o \
iris_hfi.o \
+ iris_hfi_packet.o \
resources.o
obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o
new file mode 100644
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _HFI_DEFINES_H_
+#define _HFI_DEFINES_H_
+
+#define HFI_VIDEO_ARCH_LX 0x1
+
+#define HFI_CMD_INIT 0x01000001
+
+#define HFI_PROP_IMAGE_VERSION 0x03000001
+
+#endif
@@ -39,6 +39,11 @@
* @sfr: SFR register memory
* @lock: a lock for this strucure
* @use_tz: a flag that suggests presence of trustzone
+ * @packet: pointer to packet from driver to fw
+ * @packet_size: size of packet
+ * @sys_init_id: id of sys init packet
+ * @header_id: id of packet header
+ * @packet_id: id of packet
*/
struct iris_core {
@@ -65,6 +70,11 @@ struct iris_core {
struct mem_desc sfr;
struct mutex lock; /* lock for core structure */
unsigned int use_tz;
+ u8 *packet;
+ u32 packet_size;
+ u32 sys_init_id;
+ u32 header_id;
+ u32 packet_id;
};
int iris_core_init(struct iris_core *core);
@@ -4,8 +4,67 @@
*/
#include "../firmware.h"
+#include "../hfi_queue.h"
#include "iris_helpers.h"
#include "iris_hfi.h"
+#include "iris_hfi_packet.h"
+
+static int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt)
+{
+ struct iface_q_info *q_info;
+ struct hfi_header *header;
+ u32 packet_size, rx_req;
+ int ret;
+
+ ret = check_core_lock(core);
+ if (ret)
+ return ret;
+
+ if (!core_in_valid_state(core))
+ return -EINVAL;
+
+ q_info = &core->command_queue;
+ if (!q_info || !q_info->q_array.kernel_vaddr || !pkt) {
+ dev_err(core->dev, "cannot write to shared CMD Q's\n");
+ return -ENODATA;
+ }
+
+ header = pkt;
+ packet_size = header->size;
+
+ if (!write_queue(q_info, pkt, packet_size, &rx_req)) {
+ dev_err(core->dev, "queue full\n");
+ return -ENODATA;
+ }
+
+ return ret;
+}
+
+static int sys_init(struct iris_core *core)
+{
+ int ret;
+
+ ret = hfi_packet_sys_init(core, core->packet, core->packet_size);
+ if (ret)
+ return ret;
+
+ ret = iris_hfi_queue_cmd_write(core, core->packet);
+
+ return ret;
+}
+
+static int sys_image_version(struct iris_core *core)
+{
+ int ret;
+
+ ret = hfi_packet_image_version(core, core->packet, core->packet_size);
+ if (ret)
+ return ret;
+
+ ret = iris_hfi_queue_cmd_write(core, core->packet);
+
+ return ret;
+}
#define CP_START 0
#define CP_SIZE 0x25800000
@@ -46,6 +105,16 @@ int iris_hfi_core_init(struct iris_core *core)
ret = protect_secure_region(CP_START, CP_SIZE, CP_NONPIXEL_START,
CP_NONPIXEL_SIZE, IRIS_PAS_ID);
+ if (ret)
+ goto error;
+
+ ret = sys_init(core);
+ if (ret)
+ goto error;
+
+ ret = sys_image_version(core);
+ if (ret)
+ goto error;
return ret;
new file mode 100644
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_core.h"
+#include "iris_hfi_packet.h"
+#include "hfi_defines.h"
+
+static int hfi_create_header(u8 *packet, u32 packet_size, u32 session_id,
+ u32 header_id)
+{
+ struct hfi_header *hdr = (struct hfi_header *)packet;
+
+ if (!packet || packet_size < sizeof(*hdr))
+ return -EINVAL;
+
+ memset(hdr, 0, sizeof(*hdr));
+
+ hdr->size = sizeof(*hdr);
+ hdr->session_id = session_id;
+ hdr->header_id = header_id;
+ hdr->num_packets = 0;
+
+ return 0;
+}
+
+static int hfi_create_packet(u8 *packet, u32 packet_size, u32 pkt_type,
+ u32 pkt_flags, u32 payload_type, u32 port,
+ u32 packet_id, void *payload, u32 payload_size)
+{
+ struct hfi_header *hdr;
+ struct hfi_packet *pkt;
+ u32 pkt_size;
+
+ if (!packet)
+ return -EINVAL;
+
+ hdr = (struct hfi_header *)packet;
+ if (hdr->size < sizeof(*hdr))
+ return -EINVAL;
+
+ pkt = (struct hfi_packet *)(packet + hdr->size);
+ pkt_size = sizeof(*pkt) + payload_size;
+ if (packet_size < hdr->size + pkt_size)
+ return -EINVAL;
+
+ memset(pkt, 0, pkt_size);
+ pkt->size = pkt_size;
+ pkt->type = pkt_type;
+ pkt->flags = pkt_flags;
+ pkt->payload_info = payload_type;
+ pkt->port = port;
+ pkt->packet_id = packet_id;
+ if (payload_size)
+ memcpy((u8 *)pkt + sizeof(*pkt),
+ payload, payload_size);
+
+ hdr->num_packets++;
+ hdr->size += pkt->size;
+
+ return 0;
+}
+
+int hfi_packet_sys_init(struct iris_core *core,
+ u8 *pkt, u32 pkt_size)
+{
+ u32 payload = 0;
+ int ret;
+
+ ret = hfi_create_header(pkt, pkt_size,
+ 0,
+ core->header_id++);
+ if (ret)
+ goto error;
+
+ payload = HFI_VIDEO_ARCH_LX;
+ core->sys_init_id = core->packet_id++;
+ ret = hfi_create_packet(pkt, pkt_size,
+ HFI_CMD_INIT,
+ (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+ HFI_HOST_FLAGS_INTR_REQUIRED |
+ HFI_HOST_FLAGS_NON_DISCARDABLE),
+ HFI_PAYLOAD_U32,
+ HFI_PORT_NONE,
+ core->sys_init_id,
+ &payload,
+ sizeof(u32));
+ if (ret)
+ goto error;
+
+ return ret;
+
+error:
+ dev_err(core->dev, "%s: create sys init packet failed\n", __func__);
+
+ return ret;
+}
+
+int hfi_packet_image_version(struct iris_core *core,
+ u8 *pkt, u32 pkt_size)
+{
+ int ret;
+
+ ret = hfi_create_header(pkt, pkt_size,
+ 0,
+ core->header_id++);
+ if (ret)
+ goto error;
+
+ ret = hfi_create_packet(pkt, pkt_size,
+ HFI_PROP_IMAGE_VERSION,
+ (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+ HFI_HOST_FLAGS_INTR_REQUIRED |
+ HFI_HOST_FLAGS_GET_PROPERTY),
+ HFI_PAYLOAD_NONE,
+ HFI_PORT_NONE,
+ core->packet_id++,
+ NULL, 0);
+ if (ret)
+ goto error;
+
+ return ret;
+
+error:
+ dev_err(core->dev, "%s: create image version packet failed\n", __func__);
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_HFI_PACKET_H_
+#define _IRIS_HFI_PACKET_H_
+
+struct hfi_header {
+ u32 size;
+ u32 session_id;
+ u32 header_id;
+ u32 reserved[4];
+ u32 num_packets;
+};
+
+struct hfi_packet {
+ u32 size;
+ u32 type;
+ u32 flags;
+ u32 payload_info;
+ u32 port;
+ u32 packet_id;
+ u32 reserved[2];
+};
+
+enum hfi_packet_host_flags {
+ HFI_HOST_FLAGS_NONE = 0x00000000,
+ HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001,
+ HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002,
+ HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004,
+ HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008,
+};
+
+enum hfi_packet_firmware_flags {
+ HFI_FW_FLAGS_NONE = 0x00000000,
+ HFI_FW_FLAGS_SUCCESS = 0x00000001,
+ HFI_FW_FLAGS_INFORMATION = 0x00000002,
+ HFI_FW_FLAGS_SESSION_ERROR = 0x00000004,
+ HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008,
+};
+
+enum hfi_packet_payload_info {
+ HFI_PAYLOAD_NONE = 0x00000000,
+ HFI_PAYLOAD_U32 = 0x00000001,
+ HFI_PAYLOAD_S32 = 0x00000002,
+ HFI_PAYLOAD_U64 = 0x00000003,
+ HFI_PAYLOAD_S64 = 0x00000004,
+ HFI_PAYLOAD_STRUCTURE = 0x00000005,
+ HFI_PAYLOAD_BLOB = 0x00000006,
+ HFI_PAYLOAD_STRING = 0x00000007,
+ HFI_PAYLOAD_Q16 = 0x00000008,
+ HFI_PAYLOAD_U32_ENUM = 0x00000009,
+ HFI_PAYLOAD_32_PACKED = 0x0000000a,
+ HFI_PAYLOAD_U32_ARRAY = 0x0000000b,
+ HFI_PAYLOAD_S32_ARRAY = 0x0000000c,
+ HFI_PAYLOAD_64_PACKED = 0x0000000d,
+};
+
+enum hfi_packet_port_type {
+ HFI_PORT_NONE = 0x00000000,
+ HFI_PORT_BITSTREAM = 0x00000001,
+ HFI_PORT_RAW = 0x00000002,
+};
+
+int hfi_packet_sys_init(struct iris_core *core,
+ u8 *pkt, u32 pkt_size);
+int hfi_packet_image_version(struct iris_core *core,
+ u8 *pkt, u32 pkt_size);
+
+#endif
@@ -79,6 +79,11 @@ static int iris_probe(struct platform_device *pdev)
core->state = IRIS_CORE_DEINIT;
mutex_init(&core->lock);
+ core->packet_size = IFACEQ_CORE_PKT_SIZE;
+ core->packet = devm_kzalloc(core->dev, core->packet_size, GFP_KERNEL);
+ if (!core->packet)
+ return -ENOMEM;
+
core->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(core->reg_base))
return PTR_ERR(core->reg_base);