[Concept,09/19] bootctl: Enhance the UI to support a TKey

Message ID 20251208023229.3929910-10-sjg@u-boot.org
State New
Headers
Series bootctl: Continue development with TKey functionality |

Commit Message

Simon Glass Dec. 8, 2025, 2:32 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

When unlocking an encrypted disk with a TKey we need a few more UI
operations:

- allow the password-entry textline to be shown/hidden
- allow showing instructions to the user, as well as unlock result
- obtain the password entered by the user

Add these to the API and implement them in the multi UI.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 boot/bootctl/multi_ui.c | 84 +++++++++++++++++++++++++++++++++++++++++
 boot/bootctl/util.c     | 60 +++++++++++++++++++++++++++++
 include/bootctl/ui.h    | 80 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 224 insertions(+)
  

Patch

diff --git a/boot/bootctl/multi_ui.c b/boot/bootctl/multi_ui.c
index f4f0bd281fe..5145e4357cb 100644
--- a/boot/bootctl/multi_ui.c
+++ b/boot/bootctl/multi_ui.c
@@ -577,6 +577,86 @@  static int multiboot_ui_of_to_plat(struct udevice *dev)
 	return 0;
 }
 
+static int multiboot_ui_show_pass(struct udevice *dev, int seq, bool show)
+{
+	struct bc_ui_priv *upriv = dev_get_uclass_priv(dev);
+	struct scene *scn = upriv->scn;
+	int ret;
+
+	scene_obj_set_hide(scn, ITEM_PASS + seq, !show);
+	scene_obj_set_hide(scn, ITEM_PASS_LABEL + seq, !show);
+	scene_obj_set_hide(scn, ITEM_PASS_EDIT + seq, !show);
+
+	if (show) {
+		struct scene_obj_textline *tline;
+		char *buf;
+
+		/* Clear the passphrase buffer for retry */
+		tline = scene_obj_find(scn, ITEM_PASS + seq,
+				       SCENEOBJT_TEXTLINE);
+		if (!tline)
+			return log_msg_ret("tln", -ENOENT);
+		buf = abuf_data(&tline->buf);
+		*buf = '\0';
+
+		/* Set highlight and open the textline for editing */
+		scene_set_highlight_id(scn, ITEM_PASS + seq);
+		ret = scene_set_open(scn, ITEM_PASS + seq, true);
+		if (ret)
+			return log_msg_ret("sop", ret);
+	} else {
+		/* Close the textline */
+		ret = scene_set_open(scn, ITEM_PASS + seq, false);
+		if (ret)
+			return log_msg_ret("sop", ret);
+	}
+
+	return 0;
+}
+
+static int multiboot_ui_get_pass(struct udevice *dev, int seq,
+				 const char **passp)
+{
+	struct bc_ui_priv *upriv = dev_get_uclass_priv(dev);
+	struct scene *scn = upriv->scn;
+	struct scene_obj_textline *tline;
+
+	tline = scene_obj_find(scn, ITEM_PASS + seq, SCENEOBJT_TEXTLINE);
+	if (!tline)
+		return log_msg_ret("tln", -ENOENT);
+
+	*passp = abuf_data(&tline->buf);
+
+	return 0;
+}
+
+static int multiboot_ui_show_pass_msg(struct udevice *dev, int seq, bool show)
+{
+	struct bc_ui_priv *upriv = dev_get_uclass_priv(dev);
+	struct scene *scn = upriv->scn;
+
+	scene_obj_set_hide(scn, ITEM_PASS_MSG + seq, !show);
+
+	return 0;
+}
+
+static int multiboot_ui_set_pass_msg(struct udevice *dev, int seq,
+				     const char *msg)
+{
+	struct bc_ui_priv *upriv = dev_get_uclass_priv(dev);
+	struct expo *exp = upriv->expo;
+	struct abuf *buf;
+	int ret;
+
+	ret = expo_edit_str(exp, STR_PASS_MSG + seq, NULL, &buf);
+	if (ret)
+		return log_msg_ret("spm", ret);
+
+	abuf_set(buf, (void *)msg, strlen(msg) + 1);
+
+	return 0;
+}
+
 static struct bc_ui_ops ops = {
 	.print	= multiboot_ui_print,
 	.show	= multiboot_ui_show,
@@ -584,6 +664,10 @@  static struct bc_ui_ops ops = {
 	.render	= multiboot_ui_render,
 	.poll	= multiboot_ui_poll,
 	.switch_layout = multiboot_ui_switch_layout,
+	.show_pass = multiboot_ui_show_pass,
+	.get_pass = multiboot_ui_get_pass,
+	.show_pass_msg = multiboot_ui_show_pass_msg,
+	.set_pass_msg = multiboot_ui_set_pass_msg,
 };
 
 static const struct udevice_id multiboot_ui_ids[] = {
diff --git a/boot/bootctl/util.c b/boot/bootctl/util.c
index 48912c67f21..790489ca937 100644
--- a/boot/bootctl/util.c
+++ b/boot/bootctl/util.c
@@ -110,6 +110,66 @@  int bc_ui_switch_layout(struct udevice *dev)
 	return 0;
 }
 
+int bc_ui_show_pass(struct udevice *dev, int seq, bool show)
+{
+	struct bc_ui_ops *ops = bc_ui_get_ops(dev);
+	int ret;
+
+	if (!ops->show_pass)
+		return -ENOSYS;
+
+	ret = ops->show_pass(dev, seq, show);
+	if (ret)
+		return log_msg_ret("bsp", ret);
+
+	return 0;
+}
+
+int bc_ui_get_pass(struct udevice *dev, int seq, const char **passp)
+{
+	struct bc_ui_ops *ops = bc_ui_get_ops(dev);
+	int ret;
+
+	if (!ops->get_pass)
+		return -ENOSYS;
+
+	ret = ops->get_pass(dev, seq, passp);
+	if (ret)
+		return log_msg_ret("bgp", ret);
+
+	return 0;
+}
+
+int bc_ui_show_pass_msg(struct udevice *dev, int seq, bool show)
+{
+	struct bc_ui_ops *ops = bc_ui_get_ops(dev);
+	int ret;
+
+	if (!ops->show_pass_msg)
+		return -ENOSYS;
+
+	ret = ops->show_pass_msg(dev, seq, show);
+	if (ret)
+		return log_msg_ret("bse", ret);
+
+	return 0;
+}
+
+int bc_ui_set_pass_msg(struct udevice *dev, int seq, const char *msg)
+{
+	struct bc_ui_ops *ops = bc_ui_get_ops(dev);
+	int ret;
+
+	if (!ops->set_pass_msg)
+		return -ENOSYS;
+
+	ret = ops->set_pass_msg(dev, seq, msg);
+	if (ret)
+		return log_msg_ret("bsm", ret);
+
+	return 0;
+}
+
 void bc_oslist_setup_iter(struct oslist_iter *iter)
 {
 	memset(iter, '\0', sizeof(struct oslist_iter));
diff --git a/include/bootctl/ui.h b/include/bootctl/ui.h
index 4f8e08a00c2..5e592e3dce2 100644
--- a/include/bootctl/ui.h
+++ b/include/bootctl/ui.h
@@ -99,6 +99,46 @@  struct bc_ui_ops {
 	 * Return 0 if OK, -ve on error
 	 */
 	int (*switch_layout)(struct udevice *dev);
+
+	/**
+	 * show_pass() - Show or hide the passphrase input field
+	 *
+	 * @dev: Display device
+	 * @seq: Sequence number of the bootflow item
+	 * @show: true to show the pass field, false to hide it
+	 * Return 0 if OK, -ve on error
+	 */
+	int (*show_pass)(struct udevice *dev, int seq, bool show);
+
+	/**
+	 * get_pass() - Get the passphrase entered by the user
+	 *
+	 * @dev: Display device
+	 * @seq: Sequence number of the bootflow item
+	 * @passp: Returns pointer to the passphrase string
+	 * Return 0 if OK, -ve on error
+	 */
+	int (*get_pass)(struct udevice *dev, int seq, const char **passp);
+
+	/**
+	 * show_pass_msg() - Show or hide the pass message
+	 *
+	 * @dev: Display device
+	 * @seq: Sequence number of the bootflow item
+	 * @show: true to show the message, false to hide it
+	 * Return 0 if OK, -ve on error
+	 */
+	int (*show_pass_msg)(struct udevice *dev, int seq, bool show);
+
+	/**
+	 * set_pass_msg() - Set the pass message text
+	 *
+	 * @dev: Display device
+	 * @seq: Sequence number of the bootflow item
+	 * @msg: Message text to display
+	 * Return 0 if OK, -ve on error
+	 */
+	int (*set_pass_msg)(struct udevice *dev, int seq, const char *msg);
 };
 
 #define bc_ui_get_ops(dev)  ((struct bc_ui_ops *)(dev)->driver->ops)
@@ -148,4 +188,44 @@  int bc_ui_poll(struct udevice *dev, int *seqp, bool *selectedp);
  */
 int bc_ui_switch_layout(struct udevice *dev);
 
+/**
+ * bc_ui_show_pass() - Show or hide the pass input field
+ *
+ * @dev: Display device
+ * @seq: Sequence number of the bootflow item
+ * @show: true to show the pass field, false to hide it
+ * Return 0 if OK, -ve on error
+ */
+int bc_ui_show_pass(struct udevice *dev, int seq, bool show);
+
+/**
+ * bc_ui_get_pass() - Get the pass entered by the user
+ *
+ * @dev: Display device
+ * @seq: Sequence number of the bootflow item
+ * @passp: Returns pointer to the pass string
+ * Return 0 if OK, -ve on error
+ */
+int bc_ui_get_pass(struct udevice *dev, int seq, const char **passp);
+
+/**
+ * bc_ui_show_pass_msg() - Show or hide the pass message
+ *
+ * @dev: Display device
+ * @seq: Sequence number of the bootflow item
+ * @show: true to show the message, false to hide it
+ * Return 0 if OK, -ve on error
+ */
+int bc_ui_show_pass_msg(struct udevice *dev, int seq, bool show);
+
+/**
+ * bc_ui_set_pass_msg() - Set the pass message text
+ *
+ * @dev: Display device
+ * @seq: Sequence number of the bootflow item
+ * @msg: Message text to display
+ * Return 0 if OK, -ve on error
+ */
+int bc_ui_set_pass_msg(struct udevice *dev, int seq, const char *msg);
+
 #endif