[PATCH 06/10] ratp: implement generic command support
Aleksander Morgado
aleksander at aleksander.es
Fri Feb 2 03:14:38 PST 2018
The RATP implementation now allows executing generic commands with a
binary interface: binary requests are received and binary responses
are returned.
Each command can define its own RATP request contents (e.g. to specify
command-specific options) as well as its own RATP response contents
(if any data is to be returned).
Each command is associated with a numeric unique command ID, and for
easy reference these IDs are maintained in the common ratp_bb header.
Modules may override generic implemented commands or include their own
new ones (as long as the numeric IDs introduced are unique).
Signed-off-by: Aleksander Morgado <aleksander at aleksander.es>
---
arch/arm/lib32/barebox.lds.S | 4 +
arch/arm/lib64/barebox.lds.S | 4 +
arch/blackfin/boards/ipe337/barebox.lds.S | 5 +-
arch/mips/lib/barebox.lds.S | 4 +
arch/nios2/cpu/barebox.lds.S | 5 +-
arch/openrisc/cpu/barebox.lds.S | 4 +
arch/ppc/boards/pcm030/barebox.lds.S | 4 +
arch/ppc/mach-mpc85xx/barebox.lds.S | 4 +
arch/sandbox/board/barebox.lds.S | 5 +
arch/x86/lib/barebox.lds.S | 7 +
arch/x86/mach-efi/elf_ia32_efi.lds.S | 5 +
arch/x86/mach-efi/elf_x86_64_efi.lds.S | 5 +
common/module.lds.S | 2 +
common/ratp.c | 255 ++++++++++++++++++------------
include/asm-generic/barebox.lds.h | 2 +
include/ratp_bb.h | 47 ++++++
16 files changed, 258 insertions(+), 104 deletions(-)
diff --git a/arch/arm/lib32/barebox.lds.S b/arch/arm/lib32/barebox.lds.S
index e7b87b7cd..6fadc2a35 100644
--- a/arch/arm/lib32/barebox.lds.S
+++ b/arch/arm/lib32/barebox.lds.S
@@ -85,6 +85,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
diff --git a/arch/arm/lib64/barebox.lds.S b/arch/arm/lib64/barebox.lds.S
index 240699f1a..a53b933bb 100644
--- a/arch/arm/lib64/barebox.lds.S
+++ b/arch/arm/lib64/barebox.lds.S
@@ -82,6 +82,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
diff --git a/arch/blackfin/boards/ipe337/barebox.lds.S b/arch/blackfin/boards/ipe337/barebox.lds.S
index 51a586af2..7e82a1bd7 100644
--- a/arch/blackfin/boards/ipe337/barebox.lds.S
+++ b/arch/blackfin/boards/ipe337/barebox.lds.S
@@ -68,6 +68,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
___barebox_cmd_end = .;
+ ___barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ ___barebox_ratp_cmd_end = .;
+
___barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
___barebox_magicvar_end = .;
@@ -91,4 +95,3 @@ SECTIONS
___bss_stop = .;
_end = .;
}
-
diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S
index 899f62b96..660d4be85 100644
--- a/arch/mips/lib/barebox.lds.S
+++ b/arch/mips/lib/barebox.lds.S
@@ -55,6 +55,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
diff --git a/arch/nios2/cpu/barebox.lds.S b/arch/nios2/cpu/barebox.lds.S
index a2d7fa8cd..fbcd1cd3f 100644
--- a/arch/nios2/cpu/barebox.lds.S
+++ b/arch/nios2/cpu/barebox.lds.S
@@ -55,6 +55,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
@@ -129,4 +133,3 @@ SECTIONS
_end = .;
PROVIDE (end = .);
}
-
diff --git a/arch/openrisc/cpu/barebox.lds.S b/arch/openrisc/cpu/barebox.lds.S
index b819ca099..c6807aec3 100644
--- a/arch/openrisc/cpu/barebox.lds.S
+++ b/arch/openrisc/cpu/barebox.lds.S
@@ -57,6 +57,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS } > ram
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS } > ram
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS } > ram
__barebox_magicvar_end = .;
diff --git a/arch/ppc/boards/pcm030/barebox.lds.S b/arch/ppc/boards/pcm030/barebox.lds.S
index 0e34f0a41..3b8bf3c0d 100644
--- a/arch/ppc/boards/pcm030/barebox.lds.S
+++ b/arch/ppc/boards/pcm030/barebox.lds.S
@@ -104,6 +104,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
diff --git a/arch/ppc/mach-mpc85xx/barebox.lds.S b/arch/ppc/mach-mpc85xx/barebox.lds.S
index beebab39d..000197283 100644
--- a/arch/ppc/mach-mpc85xx/barebox.lds.S
+++ b/arch/ppc/mach-mpc85xx/barebox.lds.S
@@ -105,6 +105,10 @@ SECTIONS
.barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ __barebox_ratp_cmd_start = .;
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
__barebox_initcalls_start = .;
.barebox_initcalls : { INITCALLS }
__barebox_initcalls_end = .;
diff --git a/arch/sandbox/board/barebox.lds.S b/arch/sandbox/board/barebox.lds.S
index 0d67ab660..80e27fe87 100644
--- a/arch/sandbox/board/barebox.lds.S
+++ b/arch/sandbox/board/barebox.lds.S
@@ -21,6 +21,11 @@ SECTIONS
__barebox_cmd_start = .;
__barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+
+ . = ALIGN(64);
+ __barebox_ratp_cmd_start = .;
+ __barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
}
INSERT BEFORE .rodata;
diff --git a/arch/x86/lib/barebox.lds.S b/arch/x86/lib/barebox.lds.S
index 23d754653..6ee9342f4 100644
--- a/arch/x86/lib/barebox.lds.S
+++ b/arch/x86/lib/barebox.lds.S
@@ -171,6 +171,13 @@ SECTIONS
. = ALIGN(4);
} > barebox
+ .barebox_ratp_cmd : AT ( LOADADDR(.got) + SIZEOF (.got) ) {
+ __barebox_ratp_cmd_start = .;
+ BAREBOX_RATP_CMDS
+ __barebox_ratp_cmd_end = .;
+ . = ALIGN(4);
+ } > barebox
+
.barebox_magicvars : AT ( LOADADDR(.barebox_cmd) + SIZEOF (.barebox_cmd) ) {
__barebox_magicvar_start = .;
BAREBOX_MAGICVARS
diff --git a/arch/x86/mach-efi/elf_ia32_efi.lds.S b/arch/x86/mach-efi/elf_ia32_efi.lds.S
index 69f43f554..9477aa7d7 100644
--- a/arch/x86/mach-efi/elf_ia32_efi.lds.S
+++ b/arch/x86/mach-efi/elf_ia32_efi.lds.S
@@ -70,6 +70,11 @@ SECTIONS
__barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ . = ALIGN(64);
+ __barebox_ratp_cmd_start = .;
+ __barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
diff --git a/arch/x86/mach-efi/elf_x86_64_efi.lds.S b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
index 93d34d17a..90b6b9f3f 100644
--- a/arch/x86/mach-efi/elf_x86_64_efi.lds.S
+++ b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
@@ -72,6 +72,11 @@ SECTIONS
__barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
+ . = ALIGN(64);
+ __barebox_ratp_cmd_start = .;
+ __barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+ __barebox_ratp_cmd_end = .;
+
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
diff --git a/common/module.lds.S b/common/module.lds.S
index a03d04f40..f3dbb12f4 100644
--- a/common/module.lds.S
+++ b/common/module.lds.S
@@ -35,6 +35,8 @@ SECTIONS
.got : { *(.got) }
.barebox_cmd : { BAREBOX_CMDS }
+ .barebox_ratp_cmd : { BAREBOX_RATP_CMDS }
+
. = ALIGN(4);
.bss : { *(.bss) }
}
diff --git a/common/ratp.c b/common/ratp.c
index 79b0a9906..2cdb1cd89 100644
--- a/common/ratp.c
+++ b/common/ratp.c
@@ -31,20 +31,10 @@
#include <ratp_bb.h>
#include <fs.h>
-#define BB_RATP_TYPE_CONSOLE 1
-#define BB_RATP_TYPE_PING 2
-#define BB_RATP_TYPE_GETENV 3
-#define BB_RATP_TYPE_FS 4
+LIST_HEAD(ratp_command_list);
+EXPORT_SYMBOL(ratp_command_list);
-#define BB_RATP_FLAG_NONE 0
-#define BB_RATP_FLAG_RESPONSE (1 << 0) /* Packet is a response */
-#define BB_RATP_FLAG_INDICATION (1 << 1) /* Packet is an indication */
-
-struct ratp_bb {
- uint16_t type;
- uint16_t flags;
- uint8_t data[];
-};
+#define for_each_ratp_command(cmd) list_for_each_entry(cmd, &ratp_command_list, list)
struct ratp_bb_command_return {
uint32_t errno;
@@ -203,66 +193,6 @@ static int ratp_bb_send_getenv_return(struct ratp_ctx *ctx, const char *val)
static char *ratp_command;
static struct ratp_ctx *ratp_ctx;
-static int ratp_bb_dispatch(struct ratp_ctx *ctx, const void *buf, int len)
-{
- const struct ratp_bb *rbb = buf;
- struct ratp_bb_pkt *pkt;
- int dlen = len - sizeof(struct ratp_bb);
- char *varname;
- int ret = 0;
- uint16_t flags = be16_to_cpu(rbb->flags);
-
- switch (be16_to_cpu(rbb->type)) {
- case BB_RATP_TYPE_CONSOLE:
- if (flags & BB_RATP_FLAG_RESPONSE)
- break;
-
- if (flags & BB_RATP_FLAG_INDICATION) {
- kfifo_put(ctx->console_recv_fifo, rbb->data, dlen);
- break;
- }
-
- if (ratp_command)
- return 0;
-
- ratp_command = xmemdup_add_zero(&rbb->data, dlen);
- ratp_ctx = ctx;
- pr_debug("got command: %s\n", ratp_command);
- break;
-
- case BB_RATP_TYPE_PING:
- if (flags & BB_RATP_FLAG_RESPONSE)
- break;
-
- ret = ratp_bb_send_pong(ctx);
- break;
-
- case BB_RATP_TYPE_GETENV:
- if (flags & BB_RATP_FLAG_RESPONSE)
- break;
-
- varname = xmemdup_add_zero(&rbb->data, dlen);
- ret = ratp_bb_send_getenv_return(ctx, getenv(varname));
- break;
-
- case BB_RATP_TYPE_FS:
- /* Only responses expected */
- if (!(flags & BB_RATP_FLAG_RESPONSE))
- break;
-
- pkt = xzalloc(sizeof(*pkt) + dlen);
- pkt->len = dlen;
- memcpy(pkt->data, &rbb->data, dlen);
- ctx->fs_rx = pkt;
- break;
- default:
- printf("%s: unhandled packet type 0x%04x\n", __func__, be16_to_cpu(rbb->type));
- break;
- }
-
- return ret;
-}
-
static int ratp_console_getc(struct console_device *cdev)
{
struct ratp_ctx *ctx = container_of(cdev, struct ratp_ctx, ratp_console);
@@ -374,35 +304,6 @@ static void ratp_console_unregister(struct ratp_ctx *ctx)
}
}
-static void ratp_poller(struct poller_struct *poller)
-{
- struct ratp_ctx *ctx = container_of(poller, struct ratp_ctx, poller);
- int ret;
- size_t len;
- void *buf;
-
- ratp_queue_console_tx(ctx);
-
- ret = ratp_poll(&ctx->ratp);
- if (ret == -EINTR)
- goto out;
- if (ratp_closed(&ctx->ratp))
- goto out;
-
- ret = ratp_recv(&ctx->ratp, &buf, &len);
- if (ret < 0)
- return;
-
- ratp_bb_dispatch(ctx, buf, len);
-
- free(buf);
-
- return;
-
-out:
- ratp_console_unregister(ctx);
-}
-
int barebox_ratp_fs_call(struct ratp_bb_pkt *tx, struct ratp_bb_pkt **rx)
{
struct ratp_ctx *ctx = ratp_ctx;
@@ -442,6 +343,156 @@ int barebox_ratp_fs_call(struct ratp_bb_pkt *tx, struct ratp_bb_pkt **rx)
return 0;
}
+static int compare_ratp_command(struct list_head *a, struct list_head *b)
+{
+ int id_a = list_entry(a, struct ratp_command, list)->id;
+ int id_b = list_entry(b, struct ratp_command, list)->id;
+
+ return (id_a - id_b);
+}
+
+int register_ratp_command(struct ratp_command *cmd)
+{
+ debug("register ratp command %hu\n", cmd->id);
+ list_add_sort(&cmd->list, &ratp_command_list, compare_ratp_command);
+ return 0;
+}
+EXPORT_SYMBOL(register_ratp_command);
+
+struct ratp_command *find_ratp_cmd(uint16_t cmd_id)
+{
+ struct ratp_command *cmdtp;
+
+ for_each_ratp_command(cmdtp)
+ if (cmd_id == cmdtp->id)
+ return cmdtp;
+
+ return NULL; /* not found or ambiguous command */
+}
+
+static int dispatch_ratp_message(struct ratp_ctx *ctx, const void *buf, int len)
+{
+ const struct ratp_bb *rbb = buf;
+ struct ratp_bb_pkt *pkt;
+ int dlen = len - sizeof(struct ratp_bb);
+ char *varname;
+ int ret = 0;
+ uint16_t flags;
+ uint16_t type = be16_to_cpu(rbb->type);
+ struct ratp_command *cmd;
+
+ /* See if there's a command registered to this type */
+ cmd = find_ratp_cmd(type);
+ if (cmd) {
+ struct ratp_bb *rsp = NULL;
+ int rsp_len = 0;
+
+ ret = cmd->cmd(rbb, len, &rsp, &rsp_len);
+ if (!ret)
+ ret = ratp_send(&ctx->ratp, rsp, rsp_len);
+
+ free(rsp);
+ return ret;
+ }
+
+ flags = be16_to_cpu(rbb->flags);
+ switch (type) {
+ case BB_RATP_TYPE_CONSOLE:
+ if (flags & BB_RATP_FLAG_RESPONSE)
+ break;
+
+ if (flags & BB_RATP_FLAG_INDICATION) {
+ kfifo_put(ctx->console_recv_fifo, rbb->data, dlen);
+ break;
+ }
+
+ if (ratp_command)
+ return 0;
+
+ ratp_command = xmemdup_add_zero(&rbb->data, dlen);
+ ratp_ctx = ctx;
+ pr_debug("got command: %s\n", ratp_command);
+ break;
+
+ case BB_RATP_TYPE_PING:
+ if (flags & BB_RATP_FLAG_RESPONSE)
+ break;
+
+ ret = ratp_bb_send_pong(ctx);
+ break;
+
+ case BB_RATP_TYPE_GETENV:
+ if (flags & BB_RATP_FLAG_RESPONSE)
+ break;
+
+ varname = xmemdup_add_zero(&rbb->data, dlen);
+ ret = ratp_bb_send_getenv_return(ctx, getenv(varname));
+ break;
+
+ case BB_RATP_TYPE_FS:
+ /* Only responses expected */
+ if (!(flags & BB_RATP_FLAG_RESPONSE))
+ break;
+
+ pkt = xzalloc(sizeof(*pkt) + dlen);
+ pkt->len = dlen;
+ memcpy(pkt->data, &rbb->data, dlen);
+ ctx->fs_rx = pkt;
+ break;
+ default:
+ printf("%s: unhandled packet type 0x%04x\n", __func__, be16_to_cpu(rbb->type));
+ break;
+ }
+
+ return ret;
+}
+
+extern struct ratp_command __barebox_ratp_cmd_start;
+extern struct ratp_command __barebox_ratp_cmd_end;
+
+static int init_ratp_command_list(void)
+{
+ struct ratp_command *cmdtp;
+
+ for (cmdtp = &__barebox_ratp_cmd_start;
+ cmdtp != &__barebox_ratp_cmd_end;
+ cmdtp++)
+ register_ratp_command(cmdtp);
+
+ return 0;
+}
+
+late_initcall(init_ratp_command_list);
+
+static void ratp_poller(struct poller_struct *poller)
+{
+ struct ratp_ctx *ctx = container_of(poller, struct ratp_ctx, poller);
+ int ret;
+ size_t len;
+ void *buf;
+
+ ratp_queue_console_tx(ctx);
+
+ ret = ratp_poll(&ctx->ratp);
+ if (ret == -EINTR)
+ goto out;
+ if (ratp_closed(&ctx->ratp))
+ goto out;
+
+ ret = ratp_recv(&ctx->ratp, &buf, &len);
+ if (ret < 0)
+ return;
+
+ dispatch_ratp_message(ctx, buf, len);
+
+ free(buf);
+
+ return;
+
+out:
+ ratp_console_unregister(ctx);
+}
+
int barebox_ratp(struct console_device *cdev)
{
int ret;
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index c8a919b92..74d3ca4a9 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -44,6 +44,8 @@
#define BAREBOX_CMDS KEEP(*(SORT_BY_NAME(.barebox_cmd*)))
+#define BAREBOX_RATP_CMDS KEEP(*(SORT_BY_NAME(.barebox_ratp_cmd*)))
+
#define BAREBOX_SYMS KEEP(*(__usymtab))
#define BAREBOX_MAGICVARS KEEP(*(SORT_BY_NAME(.barebox_magicvar*)))
diff --git a/include/ratp_bb.h b/include/ratp_bb.h
index f485f7d8a..1c2aa1fb7 100644
--- a/include/ratp_bb.h
+++ b/include/ratp_bb.h
@@ -1,6 +1,24 @@
#ifndef __RATP_BB_H
#define __RATP_BB_H
+#include <linux/stringify.h>
+
+#define BB_RATP_TYPE_CONSOLE 1
+#define BB_RATP_TYPE_PING 2
+#define BB_RATP_TYPE_GETENV 3
+#define BB_RATP_TYPE_FS 4
+#define BB_RATP_TYPE_RESET 5
+
+#define BB_RATP_FLAG_NONE 0
+#define BB_RATP_FLAG_RESPONSE (1 << 0) /* Packet is a response */
+#define BB_RATP_FLAG_INDICATION (1 << 1) /* Packet is an indication */
+
+struct ratp_bb {
+ uint16_t type;
+ uint16_t flags;
+ uint8_t data[];
+};
+
struct ratp_bb_pkt {
unsigned int len;
uint8_t data[];
@@ -11,4 +29,33 @@ void barebox_ratp_command_run(void);
int barebox_ratp_fs_call(struct ratp_bb_pkt *tx, struct ratp_bb_pkt **rx);
int barebox_ratp_fs_mount(const char *path);
+/*
+ * RATP commands definition
+ */
+
+struct ratp_command {
+ struct list_head list;
+ uint16_t id;
+ int (*cmd)(const struct ratp_bb *req,
+ int req_len,
+ struct ratp_bb **rsp,
+ int *rsp_len);
+}
+#ifdef __x86_64__
+/* This is required because the linker will put symbols on a 64 bit alignment */
+__attribute__((aligned(64)))
+#endif
+;
+
+#define BAREBOX_RATP_CMD_START(_name) \
+extern const struct ratp_command __barebox_cmd_##_name; \
+const struct ratp_command __barebox_cmd_##_name \
+ __attribute__ ((unused,section (".barebox_ratp_cmd_" __stringify(_name)))) = { \
+ .id = BB_RATP_TYPE_##_name,
+
+#define BAREBOX_RATP_CMD_END \
+};
+
+int register_ratp_command(struct ratp_command *cmd);
+
#endif /* __RATP_BB_H */
--
2.15.1
More information about the barebox
mailing list