@@ -502,27 +502,80 @@ static int tkey_load_app_header(struct udevice *dev, int app_size,
return 0;
}
-static int tkey_load_app_data(struct udevice *dev, const void *data, int size)
+int tkey_load_app_with_uss(struct udevice *dev, const void *app_data,
+ int app_size, const void *uss, int uss_size)
{
- struct tkey_frame cmd_frame, rsp_frame;
- int offset = 0;
+ struct tkey_load_ctx ctx;
int ret;
- log_debug("Loading app data, %u bytes\n", size);
+ /* Start loading */
+ ret = tkey_load_start(&ctx, dev, app_data, app_size, uss,
+ uss_size);
+ if (ret)
+ return ret;
+
+ /* Send all remaining blocks */
+ do {
+ ret = tkey_load_next(&ctx, 0);
+ } while (ret == -EAGAIN);
+
+ return ret;
+}
+
+int tkey_load_app(struct udevice *dev, const void *app_data, int app_size)
+{
+ return tkey_load_app_with_uss(dev, app_data, app_size, NULL, 0);
+}
+
+int tkey_load_start(struct tkey_load_ctx *ctx, struct udevice *dev,
+ const void *app_data, int app_size,
+ const void *uss, int uss_size)
+{
+ int ret;
+
+ /* Initialize context */
+ ctx->dev = dev;
+ ctx->app_data = app_data;
+ ctx->app_size = app_size;
+ ctx->offset = 0;
+
+ /* Check if we're in firmware mode first */
+ ret = tkey_in_app_mode(dev);
+ if (ret < 0) {
+ log_debug("Failed to check device mode (error %d)\n", ret);
+ return ret;
+ }
+
+ if (ret) {
+ log_debug("Device must be in firmware mode to load app\n");
+ return -ENOTSUPP;
+ }
+
+ log_debug("Starting iterative app load (%u bytes)...\n", app_size);
+
+ /* Send app header with size and USS (if provided) */
+ ret = tkey_load_app_header(dev, app_size, uss, uss_size);
+ if (ret) {
+ log_debug("Failed to send app header (error %d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int tkey_load_next(struct tkey_load_ctx *ctx, int max_blocks)
+{
+ struct tkey_frame cmd_frame, rsp_frame;
+ int blocks_sent = 0;
+ int ret;
- while (offset < size) {
- int todo = min(size - offset, TKEY_MAX_DATA_SIZE - 1);
- u8 len_code;
+ /* If max_blocks is 0, send all remaining blocks */
+ if (max_blocks == 0)
+ max_blocks = INT_MAX;
- /* Determine length code for chunk */
- if (todo <= 1)
- len_code = TKEY_LEN_1_BYTE;
- else if (todo <= 4)
- len_code = TKEY_LEN_4_BYTES;
- else if (todo <= 32)
- len_code = TKEY_LEN_32_BYTES;
- else
- len_code = TKEY_LEN_128_BYTES;
+ while (ctx->offset < ctx->app_size && blocks_sent < max_blocks) {
+ int todo = min(ctx->app_size - ctx->offset,
+ TKEY_MAX_DATA_SIZE - 1);
/*
* Build LOAD_APP_DATA command (always use 128-byte frames
@@ -533,7 +586,7 @@ static int tkey_load_app_data(struct udevice *dev, const void *data, int size)
TKEY_STATUS_OK,
TKEY_LEN_128_BYTES);
cmd_frame.data[0] = TKEY_FW_CMD_LOAD_APP_DATA;
- memcpy(&cmd_frame.data[1], data + offset, todo);
+ memcpy(&cmd_frame.data[1], ctx->app_data + ctx->offset, todo);
/* Pad remaining bytes with zeros */
if (todo + 1 < 128)
@@ -541,73 +594,37 @@ static int tkey_load_app_data(struct udevice *dev, const void *data, int size)
128 - (todo + 1));
/* Send chunk (always 128 bytes like Go app) */
- ret = tkey_send_frame(dev, &cmd_frame, 128);
+ ret = tkey_send_frame(ctx->dev, &cmd_frame, 128);
if (ret < 0)
return ret;
/* Receive response */
- ret = tkey_recv_frame(dev, &rsp_frame, TKEY_LOAD_TIMEOUT_MS);
+ ret = tkey_recv_frame(ctx->dev, &rsp_frame,
+ TKEY_LOAD_TIMEOUT_MS);
if (ret < 0)
return ret;
/* Check response status */
if (rsp_frame.header & TKEY_STATUS_ERROR) {
log_debug("Load app data failed at offset %u\n",
- offset);
+ ctx->offset);
return -EIO;
}
- offset += todo;
- log_debug("Loaded chunk: %u/%u bytes\n", offset, size);
+ ctx->offset += todo;
+ blocks_sent++;
+ log_debug("Loaded chunk: %u/%u bytes (%d blocks sent)\n",
+ ctx->offset, ctx->app_size, blocks_sent);
schedule();
}
- log_debug("App data loaded successfully\n");
-
- return 0;
-}
-
-int tkey_load_app_with_uss(struct udevice *dev, const void *app_data,
- int app_size, const void *uss, int uss_size)
-{
- int ret;
-
- /* Check if we're in firmware mode first */
- ret = tkey_in_app_mode(dev);
- if (ret < 0) {
- log_debug("Failed to check device mode (error %d)\n", ret);
- return ret;
+ /* Check if we're done */
+ if (ctx->offset >= ctx->app_size) {
+ log_debug("App data loaded successfully\n");
+ return 0; /* Done */
}
- if (ret) {
- log_debug("Device must be in firmware mode to load app\n");
- return -ENOTSUPP;
- }
-
- log_debug("Loading app (%u bytes)...\n", app_size);
-
- /* Send app header with size and USS (if provided) */
- ret = tkey_load_app_header(dev, app_size, uss, uss_size);
- if (ret) {
- log_debug("Failed to send app header (error %d)\n", ret);
- return ret;
- }
-
- /* Send app data */
- ret = tkey_load_app_data(dev, app_data, app_size);
- if (ret) {
- log_debug("Failed to send app data (error %d)\n", ret);
- return ret;
- }
-
- log_debug("App loaded successfully\n");
-
- return 0;
-}
-
-int tkey_load_app(struct udevice *dev, const void *app_data, int app_size)
-{
- return tkey_load_app_with_uss(dev, app_data, app_size, NULL, 0);
+ return -EAGAIN; /* More blocks remain */
}
int tkey_get_pubkey(struct udevice *dev, void *pubkey)
@@ -13,6 +13,21 @@
struct tkey_frame;
struct udevice;
+/**
+ * struct tkey_load_ctx - Context for iterative app loading
+ *
+ * @dev: TKey device
+ * @app_data: Complete app binary data
+ * @app_size: Size of app data
+ * @offset: Current offset in app data
+ */
+struct tkey_load_ctx {
+ struct udevice *dev;
+ const void *app_data;
+ int app_size;
+ int offset;
+};
+
/* TKey constants */
#define TKEY_NAME_SIZE 5
#define TKEY_CDI_SIZE 32
@@ -182,6 +197,40 @@ int tkey_load_app(struct udevice *dev, const void *app_data, int app_size);
int tkey_load_app_with_uss(struct udevice *dev, const void *app_data,
int app_size, const void *uss, int uss_size);
+/**
+ * tkey_load_start() - Start iterative app loading
+ *
+ * @ctx: Context structure to initialize
+ * @dev: TKey device
+ * @app_data: Complete app binary data
+ * @app_size: Size of app data
+ * @uss: User-Supplied Secret (password/passphrase) - can be NULL
+ * @uss_size: Size of USS data (max 32 bytes)
+ *
+ * This function initializes the context and sends the app header.
+ * Call tkey_load_next() repeatedly to send the data blocks.
+ *
+ * Return: 0 on success, -ve error on failure (-ENOTSUPP if not in
+ * firmware mode)
+ */
+int tkey_load_start(struct tkey_load_ctx *ctx, struct udevice *dev,
+ const void *app_data, int app_size,
+ const void *uss, int uss_size);
+
+/**
+ * tkey_load_next() - Send next block(s) of app data
+ *
+ * @ctx: Context structure from tkey_load_start()
+ * @max_blocks: Maximum number of blocks to send (0 = send all remaining)
+ *
+ * This function sends the next n blocks of app data. Call repeatedly
+ * until it returns 0 (done) instead of -EAGAIN (more blocks remain).
+ *
+ * Return: 0 if loading is complete, -EAGAIN if more blocks remain,
+ * -ve error on failure
+ */
+int tkey_load_next(struct tkey_load_ctx *ctx, int max_blocks);
+
/**
* tkey_get_pubkey() - Get public key from signer app
*