From e1202569ce995200fbbcb5de083876e502ec3f34 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Tue, 22 Apr 2025 16:34:10 +1000 Subject: [PATCH] `switch`-based handlers. --- .../xap/firmware/xap_generated.inl.j2 | 68 +++++------ quantum/xap/xap.c | 107 ++---------------- 2 files changed, 38 insertions(+), 137 deletions(-) diff --git a/data/templates/xap/firmware/xap_generated.inl.j2 b/data/templates/xap/firmware/xap_generated.inl.j2 index 208b977a97c..8c6ac52e531 100755 --- a/data/templates/xap/firmware/xap_generated.inl.j2 +++ b/data/templates/xap/firmware/xap_generated.inl.j2 @@ -106,61 +106,49 @@ static const {{ data.return_type | type_to_c_before }} {{ this_prefix_lc }}_data //////////////////////////////////////////////////////////////////////////////// // Routes -{% macro append_routing_table(prefix, container, route_stack) %} +{% macro append_routing_function(prefix, container, route_stack) %} {% set this_route_stack = route_stack.copy() %} {{ this_route_stack.append(container) or '' }} {% if 'routes' in container %} {% for route, data in container.routes | dictsort %} {% set this_prefix_uc = (prefix + '_' + data.define) | upper %} {% set this_prefix_lc = this_prefix_uc | lower %} -{{ append_routing_table(this_prefix_lc, data, this_route_stack) }} +{{ append_routing_function(this_prefix_lc, data, this_route_stack) }} {% endfor %} {% call route_conditions(this_route_stack) %} -static const xap_route_t {{ prefix | lower}}_table[] PROGMEM = { +bool {{ prefix | lower }}_route_handler(xap_token_t token, const uint8_t *data, size_t data_len) { + switch (data[0]) { {% for route, data in container.routes | dictsort %} {% set inner_route_stack = this_route_stack.copy() %} {{ inner_route_stack.append(data) or '' }} -{% if 'permissions' in data %} -{% set secure_status = 'ROUTE_PERMISSIONS_SECURE' %} -{% else %} -{% set secure_status = 'ROUTE_PERMISSIONS_INSECURE' %} -{% endif %} {% call route_conditions(inner_route_stack) %} - [{{ prefix | upper }}_{{ data.define }}] = { -{% if 'routes' in data %} - .flags = { - .type = XAP_ROUTE, - .secure = {{ secure_status }}, - }, - .child_routes = {{ prefix | lower }}_{{ data.define | lower }}_table, - .child_routes_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_table)/sizeof(xap_route_t), -{% elif 'return_execute' in data %} - .flags = { - .type = XAP_EXECUTE, - .secure = {{ secure_status }}, - }, - .handler = xap_respond_{{ data.return_execute | lower }}, -{% elif 'return_constant' in data and data.return_type == 'string' %} - .flags = { - .type = XAP_CONST_MEM, - .secure = {{ secure_status }}, - }, - .const_data = {{ prefix | lower }}_{{ data.define | lower }}_str, - .const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_str) - 1, -{% elif 'return_constant' in data %} - .flags = { - .type = XAP_CONST_MEM, - .secure = {{ secure_status }}, - }, - .const_data = &{{ prefix | lower }}_{{ data.define | lower }}_data, - .const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_data), -{% endif %} - }, + case {{ prefix | upper }}_{{ data.define }}: + { + {% if 'permissions' in data %} + if(xap_ensure_unlocked(token)) { return true; } // Route requires secure unlock + {% else %} + secure_activity_event(); + {% endif %} + {% if 'routes' in data %} + extern bool {{ prefix | lower }}_{{ data.define | lower }}_route_handler(xap_token_t token, const uint8_t *data, size_t data_len); + return {{ prefix | lower }}_{{ data.define | lower }}_route_handler(token, &data[1], data_len - 1); + {% elif 'return_execute' in data %} + return xap_respond_{{ data.return_execute | lower }}(token, &data[1], data_len - 1); + {% elif 'return_constant' in data and data.return_type == 'string' %} + return xap_respond_data_P(token, {{ prefix | lower }}_{{ data.define | lower }}_str, sizeof({{ prefix | lower }}_{{ data.define | lower }}_str) - 1); + {% elif 'return_constant' in data %} + return xap_respond_data(token, &{{ prefix | lower }}_{{ data.define | lower }}_data, sizeof({{ prefix | lower }}_{{ data.define | lower }}_data)); + {% endif %} + } {% endcall %} {% endfor %} -}; + default: + break; + } + return false; +} {% endcall %} {% endif %} {% endmacro %} -{{ append_routing_table("xap_route", xap, []) }} +{{ append_routing_function("xap_route", xap, []) }} diff --git a/quantum/xap/xap.c b/quantum/xap/xap.c index 491f27c8d77..6921ebb8354 100644 --- a/quantum/xap/xap.c +++ b/quantum/xap/xap.c @@ -49,61 +49,9 @@ bool get_config_blob_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) { # define ENABLED_BACKLIGHT_EFFECTS 0b00000000 #endif -#define QSTR2(z) #z -#define QSTR(z) QSTR2(z) - -typedef enum xap_route_type_t { - XAP_UNUSED = 0, // "Unused" needs to be zero -- undefined routes (through preprocessor) will be skipped - XAP_ROUTE, - XAP_EXECUTE, - XAP_VALUE, - XAP_CONST_MEM, - TOTAL_XAP_ROUTE_TYPES -} xap_route_type_t; - -#define XAP_ROUTE_TYPE_BIT_COUNT 3 - -typedef enum xap_route_secure_t { - ROUTE_PERMISSIONS_INSECURE, - ROUTE_PERMISSIONS_SECURE, -} xap_route_secure_t; - -#define XAP_ROUTE_SECURE_BIT_COUNT 2 - -typedef struct __attribute__((packed)) xap_route_flags_t { - xap_route_type_t type : XAP_ROUTE_TYPE_BIT_COUNT; - xap_route_secure_t secure : XAP_ROUTE_SECURE_BIT_COUNT; -} xap_route_flags_t; - -_Static_assert(TOTAL_XAP_ROUTE_TYPES <= (1 << (XAP_ROUTE_TYPE_BIT_COUNT)), "Number of XAP route types is too large for XAP_ROUTE_TYPE_BITS."); -_Static_assert(sizeof(xap_route_flags_t) == 1, "xap_route_flags_t is not length of 1"); - -typedef struct xap_route_t xap_route_t; -struct __attribute__((packed)) xap_route_t { - const xap_route_flags_t flags; - union { - // XAP_ROUTE - struct { - const xap_route_t *child_routes; - const uint8_t child_routes_len; - }; - - // XAP_EXECUTE - bool (*handler)(xap_token_t token, const uint8_t *data, size_t data_len); - - // XAP_VALUE / XAP_CONST_MEM - struct { - const void * const_data; - const uint8_t const_data_len; - }; - }; -}; - -#include - -bool xap_pre_execute_route(xap_token_t token, const xap_route_t *route) { +bool xap_ensure_unlocked(xap_token_t token) { #ifdef SECURE_ENABLE - if (!secure_is_unlocked() && (route->flags.secure == ROUTE_PERMISSIONS_SECURE)) { + if (!secure_is_unlocked()) { xap_respond_failure(token, XAP_RESPONSE_FLAG_SECURE_FAILURE); return true; } @@ -114,50 +62,15 @@ bool xap_pre_execute_route(xap_token_t token, const xap_route_t *route) { return false; } -void xap_execute_route(xap_token_t token, const xap_route_t *routes, size_t max_routes, const uint8_t *data, size_t data_len) { - if (data_len == 0) return; - xap_identifier_t id = data[0]; +#define QSTR2(z) #z +#define QSTR(z) QSTR2(z) - if (id < max_routes) { - xap_route_t route; - memcpy_P(&route, &routes[id], sizeof(xap_route_t)); - - if (xap_pre_execute_route(token, &route)) { - return; - } - - switch (route.flags.type) { - case XAP_ROUTE: - if (route.child_routes != NULL && route.child_routes_len > 0 && data_len > 0) { - xap_execute_route(token, route.child_routes, route.child_routes_len, &data[1], data_len - 1); - return; - } - break; - - case XAP_EXECUTE: - if (route.handler != NULL) { - bool ok = (route.handler)(token, data_len == 1 ? NULL : &data[1], data_len - 1); - if (ok) return; - } - break; - - case XAP_VALUE: - xap_respond_data(token, route.const_data, route.const_data_len); - return; - - case XAP_CONST_MEM: - xap_respond_data_P(token, route.const_data, route.const_data_len); - return; - - default: - break; - } - } - - // Nothing got handled, so we respond with failure. - xap_respond_failure(token, XAP_RESPONSE_FLAG_FAILED); -} +#include void xap_receive(xap_token_t token, const uint8_t *data, size_t length) { - xap_execute_route(token, xap_route_table, sizeof(xap_route_table) / sizeof(xap_route_t), data, length); + extern bool xap_route_route_handler(xap_token_t token, const uint8_t *data, size_t data_len); + if (!xap_route_route_handler(token, data, length)) { + // Nothing got handled, so we respond with failure. + xap_respond_failure(token, XAP_RESPONSE_FLAG_FAILED); + } }