From b07cc48ca16f54f51c28f9fa352a68da58ee5881 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Fri, 12 Apr 2019 12:37:03 +0200 Subject: main: add new bootstage ID for entering cli loop adding a new bootstage ID: BOOTSTAGE_ID_ENTER_CLI_LOOP Signed-off-by: Heiko Schocher --- include/bootstage.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/bootstage.h b/include/bootstage.h index c9408e7b126..5e7e242b834 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -181,6 +181,7 @@ enum bootstage_id { BOOTSTAGE_ID_BOOTM_START, BOOTSTAGE_ID_BOOTM_HANDOFF, BOOTSTAGE_ID_MAIN_LOOP, + BOOTSTAGE_ID_ENTER_CLI_LOOP, BOOTSTAGE_KERNELREAD_START, BOOTSTAGE_KERNELREAD_STOP, BOOTSTAGE_ID_BOARD_INIT, -- cgit v1.3.1 From 32ca8ffd5b282da8f4767680ac8b440f73ad41b5 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 12 Apr 2019 12:54:43 -0400 Subject: firmware: ti_sci: Add support for firewall management TI-SCI message protocol provides support for controlling the firewall configurations available in SoC. Introduce support for the set of TI-SCI message protocol APIs that provide us with this capability of controlling firewalls. Signed-off-by: Andrew F. Davis Reviewed-by: Tom Rini Reviewed-by: Andreas Dannenberg --- drivers/firmware/ti_sci.c | 177 +++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 121 ++++++++++++++++++++++ include/linux/soc/ti/ti_sci_protocol.h | 64 ++++++++++++ 3 files changed, 362 insertions(+) (limited to 'include') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index d47d22fff3e..44bbeb66c2d 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -2428,6 +2428,178 @@ fail: return ret; } +/** + * ti_sci_cmd_set_fwl_region() - Request for configuring a firewall region + * @handle: pointer to TI SCI handle + * @region: region configuration parameters + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_fwl_region(const struct ti_sci_handle *handle, + const struct ti_sci_msg_fwl_region *region) +{ + struct ti_sci_msg_fwl_set_firewall_region_req req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_SET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + req.fwl_id = region->fwl_id; + req.region = region->region; + req.n_permission_regs = region->n_permission_regs; + req.control = region->control; + req.permissions[0] = region->permissions[0]; + req.permissions[1] = region->permissions[1]; + req.permissions[2] = region->permissions[2]; + req.start_address = region->start_address; + req.end_address = region->end_address; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region + * @handle: pointer to TI SCI handle + * @region: region configuration parameters + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_fwl_region(const struct ti_sci_handle *handle, + struct ti_sci_msg_fwl_region *region) +{ + struct ti_sci_msg_fwl_get_firewall_region_req req; + struct ti_sci_msg_fwl_get_firewall_region_resp *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_GET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + req.fwl_id = region->fwl_id; + req.region = region->region; + req.n_permission_regs = region->n_permission_regs; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_fwl_get_firewall_region_resp *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + region->fwl_id = resp->fwl_id; + region->region = resp->region; + region->n_permission_regs = resp->n_permission_regs; + region->control = resp->control; + region->permissions[0] = resp->permissions[0]; + region->permissions[1] = resp->permissions[1]; + region->permissions[2] = resp->permissions[2]; + region->start_address = resp->start_address; + region->end_address = resp->end_address; + + return 0; +} + +/** + * ti_sci_cmd_change_fwl_owner() - Request for changing a firewall owner + * @handle: pointer to TI SCI handle + * @region: region configuration parameters + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle, + struct ti_sci_msg_fwl_owner *owner) +{ + struct ti_sci_msg_fwl_change_owner_info_req req; + struct ti_sci_msg_fwl_change_owner_info_resp *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_GET, + TISCI_MSG_FWL_CHANGE_OWNER, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + req.fwl_id = owner->fwl_id; + req.region = owner->region; + req.owner_index = owner->owner_index; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_fwl_change_owner_info_resp *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + owner->fwl_id = resp->fwl_id; + owner->region = resp->region; + owner->owner_index = resp->owner_index; + owner->owner_privid = resp->owner_privid; + owner->owner_permission_bits = resp->owner_permission_bits; + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -2444,6 +2616,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops; struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops; + struct ti_sci_fwl_ops *fwl_ops = &ops->fwl_ops; bops->board_config = ti_sci_cmd_set_board_config; bops->board_config_rm = ti_sci_cmd_set_board_config_rm; @@ -2501,6 +2674,10 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg; udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg; udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg; + + fwl_ops->set_fwl_region = ti_sci_cmd_set_fwl_region; + fwl_ops->get_fwl_region = ti_sci_cmd_get_fwl_region; + fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner; } /** diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 2d87cdd2cf9..1b601ff01bb 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -79,6 +79,10 @@ #define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232 #define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233 +#define TISCI_MSG_FWL_SET 0x9000 +#define TISCI_MSG_FWL_GET 0x9001 +#define TISCI_MSG_FWL_CHANGE_OWNER 0x9002 + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -1338,4 +1342,121 @@ struct ti_sci_msg_rm_udmap_flow_cfg_resp { struct ti_sci_msg_hdr hdr; } __packed; +#define FWL_MAX_PRIVID_SLOTS 3U + +/** + * struct ti_sci_msg_fwl_set_firewall_region_req - Request for configuring the firewall permissions. + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @n_permission_regs: Number of permission registers to set + * @control: Contents of the firewall CONTROL register to set + * @permissions: Contents of the firewall PERMISSION register to set + * @start_address: Contents of the firewall START_ADDRESS register to set + * @end_address: Contents of the firewall END_ADDRESS register to set + */ + +struct ti_sci_msg_fwl_set_firewall_region_req { + struct ti_sci_msg_hdr hdr; + u16 fwl_id; + u16 region; + u32 n_permission_regs; + u32 control; + u32 permissions[FWL_MAX_PRIVID_SLOTS]; + u64 start_address; + u64 end_address; +} __packed; + +/** + * struct ti_sci_msg_fwl_get_firewall_region_req - Request for retrieving the firewall permissions + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to get config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question (index starting from 0). In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0). + * @n_permission_regs: Number of permission registers to retrieve + */ +struct ti_sci_msg_fwl_get_firewall_region_req { + struct ti_sci_msg_hdr hdr; + u16 fwl_id; + u16 region; + u32 n_permission_regs; +} __packed; + +/** + * struct ti_sci_msg_fwl_get_firewall_region_resp - Response for retrieving the firewall permissions + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info This field is + * unused in case of a simple firewall and must be initialized to zero. In + * case of a region based firewall, this field indicates the region in + * question. (index starting from 0) In case of a channel based firewall, this + * field indicates the channel in question (index starting from 0) + * @n_permission_regs: Number of permission registers retrieved + * @control: Contents of the firewall CONTROL register + * @permissions: Contents of the firewall PERMISSION registers + * @start_address: Contents of the firewall START_ADDRESS register This is not applicable for channelized firewalls. + * @end_address: Contents of the firewall END_ADDRESS register This is not applicable for channelized firewalls. + */ +struct ti_sci_msg_fwl_get_firewall_region_resp { + struct ti_sci_msg_hdr hdr; + u16 fwl_id; + u16 region; + u32 n_permission_regs; + u32 control; + u32 permissions[FWL_MAX_PRIVID_SLOTS]; + u64 start_address; + u64 end_address; +} __packed; + +/** + * struct ti_sci_msg_fwl_change_owner_info_req - Request for a firewall owner change + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number if applicable + * @owner_index: New owner index to transfer ownership to + */ +struct ti_sci_msg_fwl_change_owner_info_req { + struct ti_sci_msg_hdr hdr; + u16 fwl_id; + u16 region; + u8 owner_index; +} __packed; + +/** + * struct ti_sci_msg_fwl_change_owner_info_resp - Response for a firewall owner change + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID specified in request + * @region: Region or channel number specified in request + * @owner_index: Owner index specified in request + * @owner_privid: New owner priv-ID returned by DMSC. + * @owner_permission_bits: New owner permission bits returned by DMSC. + */ +struct ti_sci_msg_fwl_change_owner_info_resp { + struct ti_sci_msg_hdr hdr; + u16 fwl_id; + u16 region; + u8 owner_index; + u8 owner_privid; + u16 owner_permission_bits; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 222cf665460..895cb1b911c 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -510,6 +510,68 @@ struct ti_sci_rm_udmap_ops { const struct ti_sci_msg_rm_udmap_flow_cfg *params); }; +/** + * struct ti_sci_msg_fwl_region_cfg - Request and Response for firewalls settings + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @n_permission_regs: Number of permission registers to set + * @control: Contents of the firewall CONTROL register to set + * @permissions: Contents of the firewall PERMISSION register to set + * @start_address: Contents of the firewall START_ADDRESS register to set + * @end_address: Contents of the firewall END_ADDRESS register to set + */ +struct ti_sci_msg_fwl_region { + u16 fwl_id; + u16 region; + u32 n_permission_regs; + u32 control; + u32 permissions[3]; + u64 start_address; + u64 end_address; +} __packed; + +/** + * \brief Request and Response for firewall owner change + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @n_permission_regs: Number of permission registers <= 3 + * @control: Control register value for this region + * @owner_index: New owner index to change to. Owner indexes are setup in DMSC firmware boot configuration data + * @owner_privid: New owner priv-id, used to lookup owner_index is not known, must be set to zero otherwise + * @owner_permission_bits: New owner permission bits + */ +struct ti_sci_msg_fwl_owner { + u16 fwl_id; + u16 region; + u8 owner_index; + u8 owner_privid; + u16 owner_permission_bits; +} __packed; + +/** + * struct ti_sci_fwl_ops - Firewall specific operations + * @set_fwl_region: Request for configuring the firewall permissions. + * @get_fwl_region: Request for retrieving the firewall permissions. + * @change_fwl_owner: Request for a change of firewall owner. + */ +struct ti_sci_fwl_ops { + int (*set_fwl_region)(const struct ti_sci_handle *handle, const struct ti_sci_msg_fwl_region *region); + int (*get_fwl_region)(const struct ti_sci_handle *handle, struct ti_sci_msg_fwl_region *region); + int (*change_fwl_owner)(const struct ti_sci_handle *handle, struct ti_sci_msg_fwl_owner *owner); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @board_ops: Miscellaneous operations @@ -518,6 +580,7 @@ struct ti_sci_rm_udmap_ops { * @core_ops: Core specific operations * @proc_ops: Processor specific operations * @ring_ops: Ring Accelerator Management operations + * @fw_ops: Firewall specific operations */ struct ti_sci_ops { struct ti_sci_board_ops board_ops; @@ -529,6 +592,7 @@ struct ti_sci_ops { struct ti_sci_rm_ringacc_ops rm_ring_ops; struct ti_sci_rm_psil_ops rm_psil_ops; struct ti_sci_rm_udmap_ops rm_udmap_ops; + struct ti_sci_fwl_ops fwl_ops; }; /** -- cgit v1.3.1 From ff6043a5fd9ada40d5890eb6cf4f624e22c14c80 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 12 Apr 2019 12:54:44 -0400 Subject: firmware: ti_sci: Modify auth_boot TI-SCI API to match new version SYSFW version 2019.01 introduces a slightly modified version of this API, add support for it here. Signed-off-by: Andrew F. Davis Reviewed-by: Tom Rini Reviewed-by: Andreas Dannenberg --- drivers/firmware/ti_sci.c | 25 ++++++++++++++++--------- drivers/firmware/ti_sci.h | 9 +++++++-- include/linux/soc/ti/ti_sci_protocol.h | 4 ++-- 3 files changed, 25 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 44bbeb66c2d..1196ce07123 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1915,16 +1915,19 @@ static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle, * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the * image and then set the processor configuration flags. * @handle: Pointer to TI SCI handle - * @proc_id: Processor ID this request is for - * @cert_addr: Memory address at which payload image certificate is located. + * @image_addr: Memory address at which payload image and certificate is + * located in memory, this is updated if the image data is + * moved during authentication. + * @image_size: This is updated with the final size of the image after + * authentication. * * Return: 0 if all went well, else returns appropriate error value. */ static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle, - u8 proc_id, u64 cert_addr) + u64 *image_addr, u32 *image_size) { struct ti_sci_msg_req_proc_auth_boot_image req; - struct ti_sci_msg_hdr *resp; + struct ti_sci_msg_resp_proc_auth_boot_image *resp; struct ti_sci_info *info; struct ti_sci_xfer *xfer; int ret = 0; @@ -1944,9 +1947,8 @@ static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle, dev_err(info->dev, "Message alloc failed(%d)\n", ret); return ret; } - req.processor_id = proc_id; - req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; - req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> + req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >> TISCI_ADDR_HIGH_SHIFT; ret = ti_sci_do_xfer(info, xfer); @@ -1955,10 +1957,15 @@ static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle, return ret; } - resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf; if (!ti_sci_is_response_ack(resp)) - ret = -ENODEV; + return -ENODEV; + + *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) | + (((u64)resp->image_addr_high << + TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK); + *image_size = resp->image_size; return ret; } diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 1b601ff01bb..a484b1fa408 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -708,7 +708,6 @@ struct ti_sci_msg_req_set_proc_boot_ctrl { /** * struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image * @hdr: Generic Header - * @processor_id: ID of processor * @cert_addr_low: Lower 32bit (Little Endian) of certificate * @cert_addr_high: Higher 32bit (Little Endian) of certificate * @@ -717,11 +716,17 @@ struct ti_sci_msg_req_set_proc_boot_ctrl { */ struct ti_sci_msg_req_proc_auth_boot_image { struct ti_sci_msg_hdr hdr; - u8 processor_id; u32 cert_addr_low; u32 cert_addr_high; } __packed; +struct ti_sci_msg_resp_proc_auth_boot_image { + struct ti_sci_msg_hdr hdr; + u32 image_addr_low; + u32 image_addr_high; + u32 image_size; +} __packed; + /** * struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status * @hdr: Generic Header diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 895cb1b911c..c57802f2934 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -279,8 +279,8 @@ struct ti_sci_proc_ops { u64 bv, u32 cfg_set, u32 cfg_clr); int (*set_proc_boot_ctrl)(const struct ti_sci_handle *handle, u8 pid, u32 ctrl_set, u32 ctrl_clr); - int (*proc_auth_boot_image)(const struct ti_sci_handle *handle, u8 pid, - u64 caddr); + int (*proc_auth_boot_image)(const struct ti_sci_handle *handle, + u64 *image_addr, u32 *image_size); int (*get_proc_boot_status)(const struct ti_sci_handle *handle, u8 pid, u64 *bv, u32 *cfg_flags, u32 *ctrl_flags, u32 *sts_flags); -- cgit v1.3.1 From fc1fe01b08cedd77a194bb82fa81af4fe1e39031 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Tue, 9 Apr 2019 15:38:14 +0200 Subject: avb: add support for named persistent values AVB 2.0 spec. revision 1.1 introduces support for named persistent values that must be tamper evident and allows AVB to store arbitrary key-value pairs [1]. Introduce implementation of two additional AVB operations read_persistent_value()/write_persistent_value() for retrieving/storing named persistent values. Correspondent pull request in the OP-TEE OS project repo [2]. [1]: https://android.googlesource.com/platform/external/avb/+/android-9.0.0_r22 [2]: https://github.com/OP-TEE/optee_os/pull/2699 Reviewed-by: Simon Glass Reviewed-by: Sam Protsenko Signed-off-by: Igor Opaniuk --- cmd/avb.c | 78 ++++++++++++++++++++++++++++ common/avb_verify.c | 125 +++++++++++++++++++++++++++++++++++++++++++++ drivers/tee/sandbox.c | 121 ++++++++++++++++++++++++++++++++++++------- include/sandboxtee.h | 15 ++++-- include/tee.h | 2 + include/tee/optee_ta_avb.h | 16 ++++++ test/py/tests/test_avb.py | 16 ++++++ 7 files changed, 351 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/cmd/avb.c b/cmd/avb.c index ff00be4cee3..c5af4a2e461 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -340,6 +340,76 @@ int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; } +int do_avb_read_pvalue(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const char *name; + size_t bytes; + size_t bytes_read; + void *buffer; + char *endp; + + if (!avb_ops) { + printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + return CMD_RET_FAILURE; + } + + if (argc != 3) + return CMD_RET_USAGE; + + name = argv[1]; + bytes = simple_strtoul(argv[2], &endp, 10); + if (*endp && *endp != '\n') + return CMD_RET_USAGE; + + buffer = malloc(bytes); + if (!buffer) + return CMD_RET_FAILURE; + + if (avb_ops->read_persistent_value(avb_ops, name, bytes, buffer, + &bytes_read) == AVB_IO_RESULT_OK) { + printf("Read %ld bytes, value = %s\n", bytes_read, + (char *)buffer); + free(buffer); + return CMD_RET_SUCCESS; + } + + printf("Failed to read persistent value\n"); + + free(buffer); + + return CMD_RET_FAILURE; +} + +int do_avb_write_pvalue(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const char *name; + const char *value; + + if (!avb_ops) { + printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + return CMD_RET_FAILURE; + } + + if (argc != 3) + return CMD_RET_USAGE; + + name = argv[1]; + value = argv[2]; + + if (avb_ops->write_persistent_value(avb_ops, name, strlen(value) + 1, + (const uint8_t *)value) == + AVB_IO_RESULT_OK) { + printf("Wrote %ld bytes\n", strlen(value) + 1); + return CMD_RET_SUCCESS; + } + + printf("Failed to write persistent value\n"); + + return CMD_RET_FAILURE; +} + static cmd_tbl_t cmd_avb[] = { U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""), U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""), @@ -350,6 +420,10 @@ static cmd_tbl_t cmd_avb[] = { U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""), U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""), U_BOOT_CMD_MKENT(verify, 1, 0, do_avb_verify_part, "", ""), +#ifdef CONFIG_OPTEE_TA_AVB + U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_avb_read_pvalue, "", ""), + U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""), +#endif }; static int do_avb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -384,6 +458,10 @@ U_BOOT_CMD( " partition and print to stdout\n" "avb write_part - write bytes to\n" " by using data from \n" +#ifdef CONFIG_OPTEE_TA_AVB + "avb read_pvalue - read a persistent value \n" + "avb write_pvalue - write a persistent value \n" +#endif "avb verify - run verification process using hash data\n" " from vbmeta structure\n" ); diff --git a/common/avb_verify.c b/common/avb_verify.c index a8c5a3e7db3..32034d927cf 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -647,6 +647,10 @@ static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func, return AVB_IO_RESULT_OK; case TEE_ERROR_OUT_OF_MEMORY: return AVB_IO_RESULT_ERROR_OOM; + case TEE_ERROR_STORAGE_NO_SPACE: + return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE; + case TEE_ERROR_ITEM_NOT_FOUND: + return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; case TEE_ERROR_TARGET_DEAD: /* * The TA has paniced, close the session to reload the TA @@ -847,6 +851,123 @@ static AvbIOResult get_size_of_partition(AvbOps *ops, return AVB_IO_RESULT_OK; } +static AvbIOResult read_persistent_value(AvbOps *ops, + const char *name, + size_t buffer_size, + u8 *out_buffer, + size_t *out_num_bytes_read) +{ + AvbIOResult rc; + struct tee_shm *shm_name; + struct tee_shm *shm_buf; + struct tee_param param[2]; + struct udevice *tee; + size_t name_size = strlen(name) + 1; + + if (get_open_session(ops->user_data)) + return AVB_IO_RESULT_ERROR_IO; + + tee = ((struct AvbOpsData *)ops->user_data)->tee; + + rc = tee_shm_alloc(tee, name_size, + TEE_SHM_ALLOC, &shm_name); + if (rc) + return AVB_IO_RESULT_ERROR_OOM; + + rc = tee_shm_alloc(tee, buffer_size, + TEE_SHM_ALLOC, &shm_buf); + if (rc) { + rc = AVB_IO_RESULT_ERROR_OOM; + goto free_name; + } + + memcpy(shm_name->addr, name, name_size); + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[0].u.memref.shm = shm_name; + param[0].u.memref.size = name_size; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param[1].u.memref.shm = shm_buf; + param[1].u.memref.size = buffer_size; + + rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE, + 2, param); + if (rc) + goto out; + + if (param[1].u.memref.size > buffer_size) { + rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; + goto out; + } + + *out_num_bytes_read = param[1].u.memref.size; + + memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read); + +out: + tee_shm_free(shm_buf); +free_name: + tee_shm_free(shm_name); + + return rc; +} + +static AvbIOResult write_persistent_value(AvbOps *ops, + const char *name, + size_t value_size, + const u8 *value) +{ + AvbIOResult rc; + struct tee_shm *shm_name; + struct tee_shm *shm_buf; + struct tee_param param[2]; + struct udevice *tee; + size_t name_size = strlen(name) + 1; + + if (get_open_session(ops->user_data)) + return AVB_IO_RESULT_ERROR_IO; + + tee = ((struct AvbOpsData *)ops->user_data)->tee; + + if (!value_size) + return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; + + rc = tee_shm_alloc(tee, name_size, + TEE_SHM_ALLOC, &shm_name); + if (rc) + return AVB_IO_RESULT_ERROR_OOM; + + rc = tee_shm_alloc(tee, value_size, + TEE_SHM_ALLOC, &shm_buf); + if (rc) { + rc = AVB_IO_RESULT_ERROR_OOM; + goto free_name; + } + + memcpy(shm_name->addr, name, name_size); + memcpy(shm_buf->addr, value, value_size); + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[0].u.memref.shm = shm_name; + param[0].u.memref.size = name_size; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[1].u.memref.shm = shm_buf; + param[1].u.memref.size = value_size; + + rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE, + 2, param); + if (rc) + goto out; + +out: + tee_shm_free(shm_buf); +free_name: + tee_shm_free(shm_name); + + return rc; +} /** * ============================================================================ * AVB2.0 AvbOps alloc/initialisation/free @@ -870,6 +991,10 @@ AvbOps *avb_ops_alloc(int boot_device) ops_data->ops.read_is_device_unlocked = read_is_device_unlocked; ops_data->ops.get_unique_guid_for_partition = get_unique_guid_for_partition; +#ifdef CONFIG_OPTEE_TA_AVB + ops_data->ops.write_persistent_value = write_persistent_value; + ops_data->ops.read_persistent_value = read_persistent_value; +#endif ops_data->ops.get_size_of_partition = get_size_of_partition; ops_data->mmc_dev = boot_device; diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c index ccddb03e730..a136bc96098 100644 --- a/drivers/tee/sandbox.c +++ b/drivers/tee/sandbox.c @@ -14,6 +14,7 @@ * available. */ +static const u32 pstorage_max = 16; /** * struct ta_entry - TA entries * @uuid: UUID of an emulated TA @@ -24,8 +25,11 @@ */ struct ta_entry { struct tee_optee_ta_uuid uuid; - u32 (*open_session)(uint num_params, struct tee_param *params); - u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params); + u32 (*open_session)(struct udevice *dev, uint num_params, + struct tee_param *params); + u32 (*invoke_func)(struct udevice *dev, + u32 func, uint num_params, + struct tee_param *params); }; #ifdef CONFIG_OPTEE_TA_AVB @@ -59,10 +63,8 @@ bad_params: return TEE_ERROR_BAD_PARAMETERS; } -static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS]; -static u32 ta_avb_lock_state; - -static u32 ta_avb_open_session(uint num_params, struct tee_param *params) +static u32 ta_avb_open_session(struct udevice *dev, uint num_params, + struct tee_param *params) { /* * We don't expect additional parameters when opening a session to @@ -73,12 +75,17 @@ static u32 ta_avb_open_session(uint num_params, struct tee_param *params) num_params, params); } -static u32 ta_avb_invoke_func(u32 func, uint num_params, +static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params, struct tee_param *params) { + struct sandbox_tee_state *state = dev_get_priv(dev); + ENTRY e, *ep; + char *name; u32 res; uint slot; u64 val; + char *value; + u32 value_sz; switch (func) { case TA_AVB_CMD_READ_ROLLBACK_INDEX: @@ -91,12 +98,12 @@ static u32 ta_avb_invoke_func(u32 func, uint num_params, return res; slot = params[0].u.value.a; - if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) { + if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) { printf("Rollback index slot out of bounds %u\n", slot); return TEE_ERROR_BAD_PARAMETERS; } - val = ta_avb_rollback_indexes[slot]; + val = state->ta_avb_rollback_indexes[slot]; params[1].u.value.a = val >> 32; params[1].u.value.b = val; return TEE_SUCCESS; @@ -111,16 +118,16 @@ static u32 ta_avb_invoke_func(u32 func, uint num_params, return res; slot = params[0].u.value.a; - if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) { + if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) { printf("Rollback index slot out of bounds %u\n", slot); return TEE_ERROR_BAD_PARAMETERS; } val = (u64)params[1].u.value.a << 32 | params[1].u.value.b; - if (val < ta_avb_rollback_indexes[slot]) + if (val < state->ta_avb_rollback_indexes[slot]) return TEE_ERROR_SECURITY; - ta_avb_rollback_indexes[slot] = val; + state->ta_avb_rollback_indexes[slot] = val; return TEE_SUCCESS; case TA_AVB_CMD_READ_LOCK_STATE: @@ -132,7 +139,7 @@ static u32 ta_avb_invoke_func(u32 func, uint num_params, if (res) return res; - params[0].u.value.a = ta_avb_lock_state; + params[0].u.value.a = state->ta_avb_lock_state; return TEE_SUCCESS; case TA_AVB_CMD_WRITE_LOCK_STATE: @@ -144,13 +151,64 @@ static u32 ta_avb_invoke_func(u32 func, uint num_params, if (res) return res; - if (ta_avb_lock_state != params[0].u.value.a) { - ta_avb_lock_state = params[0].u.value.a; - memset(ta_avb_rollback_indexes, 0, - sizeof(ta_avb_rollback_indexes)); + if (state->ta_avb_lock_state != params[0].u.value.a) { + state->ta_avb_lock_state = params[0].u.value.a; + memset(state->ta_avb_rollback_indexes, 0, + sizeof(state->ta_avb_rollback_indexes)); } return TEE_SUCCESS; + case TA_AVB_CMD_READ_PERSIST_VALUE: + res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT, + TEE_PARAM_ATTR_TYPE_MEMREF_INOUT, + TEE_PARAM_ATTR_TYPE_NONE, + TEE_PARAM_ATTR_TYPE_NONE, + num_params, params); + if (res) + return res; + + name = params[0].u.memref.shm->addr; + + value = params[1].u.memref.shm->addr; + value_sz = params[1].u.memref.size; + + e.key = name; + e.data = NULL; + hsearch_r(e, FIND, &ep, &state->pstorage_htab, 0); + if (!ep) + return TEE_ERROR_ITEM_NOT_FOUND; + + value_sz = strlen(ep->data); + memcpy(value, ep->data, value_sz); + + return TEE_SUCCESS; + case TA_AVB_CMD_WRITE_PERSIST_VALUE: + res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT, + TEE_PARAM_ATTR_TYPE_MEMREF_INPUT, + TEE_PARAM_ATTR_TYPE_NONE, + TEE_PARAM_ATTR_TYPE_NONE, + num_params, params); + if (res) + return res; + + name = params[0].u.memref.shm->addr; + + value = params[1].u.memref.shm->addr; + value_sz = params[1].u.memref.size; + + e.key = name; + e.data = NULL; + hsearch_r(e, FIND, &ep, &state->pstorage_htab, 0); + if (ep) + hdelete_r(e.key, &state->pstorage_htab, 0); + + e.key = name; + e.data = value; + hsearch_r(e, ENTER, &ep, &state->pstorage_htab, 0); + if (!ep) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; default: return TEE_ERROR_NOT_SUPPORTED; @@ -225,7 +283,7 @@ static int sandbox_tee_open_session(struct udevice *dev, return 0; } - arg->ret = ta->open_session(num_params, params); + arg->ret = ta->open_session(dev, num_params, params); arg->ret_origin = TEE_ORIGIN_TRUSTED_APP; if (!arg->ret) { @@ -261,7 +319,7 @@ static int sandbox_tee_invoke_func(struct udevice *dev, return -EINVAL; } - arg->ret = ta->invoke_func(arg->func, num_params, params); + arg->ret = ta->invoke_func(dev, arg->func, num_params, params); arg->ret_origin = TEE_ORIGIN_TRUSTED_APP; return 0; @@ -285,6 +343,29 @@ static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm) return 0; } +static int sandbox_tee_remove(struct udevice *dev) +{ + struct sandbox_tee_state *state = dev_get_priv(dev); + + hdestroy_r(&state->pstorage_htab); + + return 0; +} + +static int sandbox_tee_probe(struct udevice *dev) +{ + struct sandbox_tee_state *state = dev_get_priv(dev); + /* + * With this hastable we emulate persistent storage, + * which should contain persistent values + * between different sessions/command invocations. + */ + if (!hcreate_r(pstorage_max, &state->pstorage_htab)) + return TEE_ERROR_OUT_OF_MEMORY; + + return 0; +} + static const struct tee_driver_ops sandbox_tee_ops = { .get_version = sandbox_tee_get_version, .open_session = sandbox_tee_open_session, @@ -305,4 +386,6 @@ U_BOOT_DRIVER(sandbox_tee) = { .of_match = sandbox_tee_match, .ops = &sandbox_tee_ops, .priv_auto_alloc_size = sizeof(struct sandbox_tee_state), + .probe = sandbox_tee_probe, + .remove = sandbox_tee_remove, }; diff --git a/include/sandboxtee.h b/include/sandboxtee.h index 44f653d9cf3..419643a0246 100644 --- a/include/sandboxtee.h +++ b/include/sandboxtee.h @@ -6,16 +6,25 @@ #ifndef __SANDBOXTEE_H #define __SANDBOXTEE_H +#include +#include + /** * struct sandbox_tee_state - internal state of the sandbox TEE - * @session: current open session - * @num_shms: number of registered shared memory objects - * @ta: Trusted Application of current session + * @session: current open session + * @num_shms: number of registered shared memory objects + * @ta: Trusted Application of current session + * @ta_avb_rollback_indexes TA avb rollback indexes storage + * @ta_avb_lock_state TA avb lock state storage + * @pstorage_htab named persistent values storage */ struct sandbox_tee_state { u32 session; int num_shms; void *ta; + u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS]; + u32 ta_avb_lock_state; + struct hsearch_data pstorage_htab; }; #endif /*__SANDBOXTEE_H*/ diff --git a/include/tee.h b/include/tee.h index edd9f9b0c96..02bcd9e7038 100644 --- a/include/tee.h +++ b/include/tee.h @@ -43,7 +43,9 @@ #define TEE_ERROR_COMMUNICATION 0xffff000e #define TEE_ERROR_SECURITY 0xffff000f #define TEE_ERROR_OUT_OF_MEMORY 0xffff000c +#define TEE_ERROR_OVERFLOW 0xffff300f #define TEE_ERROR_TARGET_DEAD 0xffff3024 +#define TEE_ERROR_STORAGE_NO_SPACE 0xffff3041 #define TEE_ORIGIN_COMMS 0x00000002 #define TEE_ORIGIN_TEE 0x00000003 diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h index 074386af19a..949875a64cb 100644 --- a/include/tee/optee_ta_avb.h +++ b/include/tee/optee_ta_avb.h @@ -45,4 +45,20 @@ */ #define TA_AVB_CMD_WRITE_LOCK_STATE 3 +/* + * Reads a persistent value corresponding to the given name. + * + * in params[0].u.memref: persistent value name + * out params[1].u.memref: read persistent value buffer + */ +#define TA_AVB_CMD_READ_PERSIST_VALUE 4 + +/* + * Writes a persistent value corresponding to the given name. + * + * in params[0].u.memref: persistent value name + * in params[1].u.memref: persistent value buffer to write + */ +#define TA_AVB_CMD_WRITE_PERSIST_VALUE 5 + #endif /* __TA_AVB_H */ diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py index e70a010c9ac..2bb75ed6e2a 100644 --- a/test/py/tests/test_avb.py +++ b/test/py/tests/test_avb.py @@ -116,3 +116,19 @@ def test_avb_mmc_read(u_boot_console): response = u_boot_console.run_command('cmp 0x%x 0x%x 40' % (temp_addr, temp_addr2)) assert response.find('64 word') + + +@pytest.mark.buildconfigspec('cmd_avb') +@pytest.mark.buildconfigspec('optee_ta_avb') +def test_avb_persistent_values(u_boot_console): + """Test reading/writing persistent storage to avb + """ + + response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + assert response == '' + + response = u_boot_console.run_command('avb write_pvalue test value_value') + assert response == 'Wrote 12 bytes' + + response = u_boot_console.run_command('avb read_pvalue test 12') + assert response == 'Read 12 bytes, value = value_value' -- cgit v1.3.1