176db5a27SMasami Hiramatsu /* SPDX-License-Identifier: GPL-2.0 */ 276db5a27SMasami Hiramatsu #ifndef _LINUX_XBC_H 376db5a27SMasami Hiramatsu #define _LINUX_XBC_H 476db5a27SMasami Hiramatsu /* 576db5a27SMasami Hiramatsu * Extra Boot Config 676db5a27SMasami Hiramatsu * Copyright (C) 2019 Linaro Ltd. 776db5a27SMasami Hiramatsu * Author: Masami Hiramatsu <mhiramat@kernel.org> 876db5a27SMasami Hiramatsu */ 976db5a27SMasami Hiramatsu 104ee1b4caSMasami Hiramatsu #ifdef __KERNEL__ 1176db5a27SMasami Hiramatsu #include <linux/kernel.h> 1276db5a27SMasami Hiramatsu #include <linux/types.h> 134ee1b4caSMasami Hiramatsu #else /* !__KERNEL__ */ 144ee1b4caSMasami Hiramatsu /* 154ee1b4caSMasami Hiramatsu * NOTE: This is only for tools/bootconfig, because tools/bootconfig will 164ee1b4caSMasami Hiramatsu * run the parser sanity test. 174ee1b4caSMasami Hiramatsu * This does NOT mean linux/bootconfig.h is available in the user space. 184ee1b4caSMasami Hiramatsu * However, if you change this file, please make sure the tools/bootconfig 194ee1b4caSMasami Hiramatsu * has no issue on building and running. 204ee1b4caSMasami Hiramatsu */ 214ee1b4caSMasami Hiramatsu #endif 2276db5a27SMasami Hiramatsu 2385c46b78SMasami Hiramatsu #define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" 2485c46b78SMasami Hiramatsu #define BOOTCONFIG_MAGIC_LEN 12 25e1cef2d4SMasami Hiramatsu #define BOOTCONFIG_ALIGN_SHIFT 2 26e1cef2d4SMasami Hiramatsu #define BOOTCONFIG_ALIGN (1 << BOOTCONFIG_ALIGN_SHIFT) 27e1cef2d4SMasami Hiramatsu #define BOOTCONFIG_ALIGN_MASK (BOOTCONFIG_ALIGN - 1) 2885c46b78SMasami Hiramatsu 2999f4f5d6SMasami Hiramatsu /** 3099f4f5d6SMasami Hiramatsu * xbc_calc_checksum() - Calculate checksum of bootconfig 3199f4f5d6SMasami Hiramatsu * @data: Bootconfig data. 3299f4f5d6SMasami Hiramatsu * @size: The size of the bootconfig data. 3399f4f5d6SMasami Hiramatsu * 3499f4f5d6SMasami Hiramatsu * Calculate the checksum value of the bootconfig data. 3599f4f5d6SMasami Hiramatsu * The checksum will be used with the BOOTCONFIG_MAGIC and the size for 3699f4f5d6SMasami Hiramatsu * embedding the bootconfig in the initrd image. 3799f4f5d6SMasami Hiramatsu */ 384f292c48SMasami Hiramatsu static inline __init uint32_t xbc_calc_checksum(void *data, uint32_t size) 3999f4f5d6SMasami Hiramatsu { 4099f4f5d6SMasami Hiramatsu unsigned char *p = data; 414f292c48SMasami Hiramatsu uint32_t ret = 0; 4299f4f5d6SMasami Hiramatsu 4399f4f5d6SMasami Hiramatsu while (size--) 4499f4f5d6SMasami Hiramatsu ret += *p++; 4599f4f5d6SMasami Hiramatsu 4699f4f5d6SMasami Hiramatsu return ret; 4799f4f5d6SMasami Hiramatsu } 4899f4f5d6SMasami Hiramatsu 4976db5a27SMasami Hiramatsu /* XBC tree node */ 5076db5a27SMasami Hiramatsu struct xbc_node { 514f292c48SMasami Hiramatsu uint16_t next; 524f292c48SMasami Hiramatsu uint16_t child; 534f292c48SMasami Hiramatsu uint16_t parent; 544f292c48SMasami Hiramatsu uint16_t data; 5576db5a27SMasami Hiramatsu } __attribute__ ((__packed__)); 5676db5a27SMasami Hiramatsu 5776db5a27SMasami Hiramatsu #define XBC_KEY 0 5876db5a27SMasami Hiramatsu #define XBC_VALUE (1 << 15) 5976db5a27SMasami Hiramatsu /* Maximum size of boot config is 32KB - 1 */ 6076db5a27SMasami Hiramatsu #define XBC_DATA_MAX (XBC_VALUE - 1) 6176db5a27SMasami Hiramatsu 626c406249SSouradeep Chowdhury #define XBC_NODE_MAX 8192 6376db5a27SMasami Hiramatsu #define XBC_KEYLEN_MAX 256 6476db5a27SMasami Hiramatsu #define XBC_DEPTH_MAX 16 6576db5a27SMasami Hiramatsu 6676db5a27SMasami Hiramatsu /* Node tree access raw APIs */ 6776db5a27SMasami Hiramatsu struct xbc_node * __init xbc_root_node(void); 6876db5a27SMasami Hiramatsu int __init xbc_node_index(struct xbc_node *node); 6976db5a27SMasami Hiramatsu struct xbc_node * __init xbc_node_get_parent(struct xbc_node *node); 7076db5a27SMasami Hiramatsu struct xbc_node * __init xbc_node_get_child(struct xbc_node *node); 7176db5a27SMasami Hiramatsu struct xbc_node * __init xbc_node_get_next(struct xbc_node *node); 7276db5a27SMasami Hiramatsu const char * __init xbc_node_get_data(struct xbc_node *node); 7376db5a27SMasami Hiramatsu 7476db5a27SMasami Hiramatsu /** 7576db5a27SMasami Hiramatsu * xbc_node_is_value() - Test the node is a value node 7676db5a27SMasami Hiramatsu * @node: An XBC node. 7776db5a27SMasami Hiramatsu * 7876db5a27SMasami Hiramatsu * Test the @node is a value node and return true if a value node, false if not. 7976db5a27SMasami Hiramatsu */ 8076db5a27SMasami Hiramatsu static inline __init bool xbc_node_is_value(struct xbc_node *node) 8176db5a27SMasami Hiramatsu { 8276db5a27SMasami Hiramatsu return node->data & XBC_VALUE; 8376db5a27SMasami Hiramatsu } 8476db5a27SMasami Hiramatsu 8576db5a27SMasami Hiramatsu /** 8676db5a27SMasami Hiramatsu * xbc_node_is_key() - Test the node is a key node 8776db5a27SMasami Hiramatsu * @node: An XBC node. 8876db5a27SMasami Hiramatsu * 8976db5a27SMasami Hiramatsu * Test the @node is a key node and return true if a key node, false if not. 9076db5a27SMasami Hiramatsu */ 9176db5a27SMasami Hiramatsu static inline __init bool xbc_node_is_key(struct xbc_node *node) 9276db5a27SMasami Hiramatsu { 9376db5a27SMasami Hiramatsu return !xbc_node_is_value(node); 9476db5a27SMasami Hiramatsu } 9576db5a27SMasami Hiramatsu 9676db5a27SMasami Hiramatsu /** 9776db5a27SMasami Hiramatsu * xbc_node_is_array() - Test the node is an arraied value node 9876db5a27SMasami Hiramatsu * @node: An XBC node. 9976db5a27SMasami Hiramatsu * 10076db5a27SMasami Hiramatsu * Test the @node is an arraied value node. 10176db5a27SMasami Hiramatsu */ 10276db5a27SMasami Hiramatsu static inline __init bool xbc_node_is_array(struct xbc_node *node) 10376db5a27SMasami Hiramatsu { 104ca24306dSMasami Hiramatsu return xbc_node_is_value(node) && node->child != 0; 10576db5a27SMasami Hiramatsu } 10676db5a27SMasami Hiramatsu 10776db5a27SMasami Hiramatsu /** 10876db5a27SMasami Hiramatsu * xbc_node_is_leaf() - Test the node is a leaf key node 10976db5a27SMasami Hiramatsu * @node: An XBC node. 11076db5a27SMasami Hiramatsu * 11176db5a27SMasami Hiramatsu * Test the @node is a leaf key node which is a key node and has a value node 11276db5a27SMasami Hiramatsu * or no child. Returns true if it is a leaf node, or false if not. 113e5efaeb8SMasami Hiramatsu * Note that the leaf node can have subkey nodes in addition to the 114e5efaeb8SMasami Hiramatsu * value node. 11576db5a27SMasami Hiramatsu */ 11676db5a27SMasami Hiramatsu static inline __init bool xbc_node_is_leaf(struct xbc_node *node) 11776db5a27SMasami Hiramatsu { 11876db5a27SMasami Hiramatsu return xbc_node_is_key(node) && 11976db5a27SMasami Hiramatsu (!node->child || xbc_node_is_value(xbc_node_get_child(node))); 12076db5a27SMasami Hiramatsu } 12176db5a27SMasami Hiramatsu 12276db5a27SMasami Hiramatsu /* Tree-based key-value access APIs */ 1235dfe50b0SMasami Hiramatsu struct xbc_node * __init xbc_node_find_subkey(struct xbc_node *parent, 12476db5a27SMasami Hiramatsu const char *key); 12576db5a27SMasami Hiramatsu 12676db5a27SMasami Hiramatsu const char * __init xbc_node_find_value(struct xbc_node *parent, 12776db5a27SMasami Hiramatsu const char *key, 12876db5a27SMasami Hiramatsu struct xbc_node **vnode); 12976db5a27SMasami Hiramatsu 13076db5a27SMasami Hiramatsu struct xbc_node * __init xbc_node_find_next_leaf(struct xbc_node *root, 13176db5a27SMasami Hiramatsu struct xbc_node *leaf); 13276db5a27SMasami Hiramatsu 13376db5a27SMasami Hiramatsu const char * __init xbc_node_find_next_key_value(struct xbc_node *root, 13476db5a27SMasami Hiramatsu struct xbc_node **leaf); 13576db5a27SMasami Hiramatsu 13676db5a27SMasami Hiramatsu /** 13776db5a27SMasami Hiramatsu * xbc_find_value() - Find a value which matches the key 13876db5a27SMasami Hiramatsu * @key: Search key 13976db5a27SMasami Hiramatsu * @vnode: A container pointer of XBC value node. 14076db5a27SMasami Hiramatsu * 14176db5a27SMasami Hiramatsu * Search a value whose key matches @key from whole of XBC tree and return 14276db5a27SMasami Hiramatsu * the value if found. Found value node is stored in *@vnode. 14376db5a27SMasami Hiramatsu * Note that this can return 0-length string and store NULL in *@vnode for 14476db5a27SMasami Hiramatsu * key-only (non-value) entry. 14576db5a27SMasami Hiramatsu */ 14676db5a27SMasami Hiramatsu static inline const char * __init 14776db5a27SMasami Hiramatsu xbc_find_value(const char *key, struct xbc_node **vnode) 14876db5a27SMasami Hiramatsu { 14976db5a27SMasami Hiramatsu return xbc_node_find_value(NULL, key, vnode); 15076db5a27SMasami Hiramatsu } 15176db5a27SMasami Hiramatsu 15276db5a27SMasami Hiramatsu /** 15376db5a27SMasami Hiramatsu * xbc_find_node() - Find a node which matches the key 15476db5a27SMasami Hiramatsu * @key: Search key 15576db5a27SMasami Hiramatsu * 15676db5a27SMasami Hiramatsu * Search a (key) node whose key matches @key from whole of XBC tree and 15776db5a27SMasami Hiramatsu * return the node if found. If not found, returns NULL. 15876db5a27SMasami Hiramatsu */ 15976db5a27SMasami Hiramatsu static inline struct xbc_node * __init xbc_find_node(const char *key) 16076db5a27SMasami Hiramatsu { 1615dfe50b0SMasami Hiramatsu return xbc_node_find_subkey(NULL, key); 16276db5a27SMasami Hiramatsu } 16376db5a27SMasami Hiramatsu 16476db5a27SMasami Hiramatsu /** 165e5efaeb8SMasami Hiramatsu * xbc_node_get_subkey() - Return the first subkey node if exists 166e5efaeb8SMasami Hiramatsu * @node: Parent node 167e5efaeb8SMasami Hiramatsu * 168e5efaeb8SMasami Hiramatsu * Return the first subkey node of the @node. If the @node has no child 169e5efaeb8SMasami Hiramatsu * or only value node, this will return NULL. 170e5efaeb8SMasami Hiramatsu */ 171e5efaeb8SMasami Hiramatsu static inline struct xbc_node * __init xbc_node_get_subkey(struct xbc_node *node) 172e5efaeb8SMasami Hiramatsu { 173e5efaeb8SMasami Hiramatsu struct xbc_node *child = xbc_node_get_child(node); 174e5efaeb8SMasami Hiramatsu 175e5efaeb8SMasami Hiramatsu if (child && xbc_node_is_value(child)) 176e5efaeb8SMasami Hiramatsu return xbc_node_get_next(child); 177e5efaeb8SMasami Hiramatsu else 178e5efaeb8SMasami Hiramatsu return child; 179e5efaeb8SMasami Hiramatsu } 180e5efaeb8SMasami Hiramatsu 181e5efaeb8SMasami Hiramatsu /** 18276db5a27SMasami Hiramatsu * xbc_array_for_each_value() - Iterate value nodes on an array 18376db5a27SMasami Hiramatsu * @anode: An XBC arraied value node 18476db5a27SMasami Hiramatsu * @value: A value 18576db5a27SMasami Hiramatsu * 18676db5a27SMasami Hiramatsu * Iterate array value nodes and values starts from @anode. This is expected to 18776db5a27SMasami Hiramatsu * be used with xbc_find_value() and xbc_node_find_value(), so that user can 18876db5a27SMasami Hiramatsu * process each array entry node. 18976db5a27SMasami Hiramatsu */ 19076db5a27SMasami Hiramatsu #define xbc_array_for_each_value(anode, value) \ 19176db5a27SMasami Hiramatsu for (value = xbc_node_get_data(anode); anode != NULL ; \ 192ca24306dSMasami Hiramatsu anode = xbc_node_get_child(anode), \ 19376db5a27SMasami Hiramatsu value = anode ? xbc_node_get_data(anode) : NULL) 19476db5a27SMasami Hiramatsu 19576db5a27SMasami Hiramatsu /** 19676db5a27SMasami Hiramatsu * xbc_node_for_each_child() - Iterate child nodes 19776db5a27SMasami Hiramatsu * @parent: An XBC node. 19876db5a27SMasami Hiramatsu * @child: Iterated XBC node. 19976db5a27SMasami Hiramatsu * 20076db5a27SMasami Hiramatsu * Iterate child nodes of @parent. Each child nodes are stored to @child. 201e5efaeb8SMasami Hiramatsu * The @child can be mixture of a value node and subkey nodes. 20276db5a27SMasami Hiramatsu */ 20376db5a27SMasami Hiramatsu #define xbc_node_for_each_child(parent, child) \ 20476db5a27SMasami Hiramatsu for (child = xbc_node_get_child(parent); child != NULL ; \ 20576db5a27SMasami Hiramatsu child = xbc_node_get_next(child)) 20676db5a27SMasami Hiramatsu 20776db5a27SMasami Hiramatsu /** 208e5efaeb8SMasami Hiramatsu * xbc_node_for_each_subkey() - Iterate child subkey nodes 209e5efaeb8SMasami Hiramatsu * @parent: An XBC node. 210e5efaeb8SMasami Hiramatsu * @child: Iterated XBC node. 211e5efaeb8SMasami Hiramatsu * 212e5efaeb8SMasami Hiramatsu * Iterate subkey nodes of @parent. Each child nodes are stored to @child. 213e5efaeb8SMasami Hiramatsu * The @child is only the subkey node. 214e5efaeb8SMasami Hiramatsu */ 215e5efaeb8SMasami Hiramatsu #define xbc_node_for_each_subkey(parent, child) \ 216e5efaeb8SMasami Hiramatsu for (child = xbc_node_get_subkey(parent); child != NULL ; \ 217e5efaeb8SMasami Hiramatsu child = xbc_node_get_next(child)) 218e5efaeb8SMasami Hiramatsu 219e5efaeb8SMasami Hiramatsu /** 22076db5a27SMasami Hiramatsu * xbc_node_for_each_array_value() - Iterate array entries of geven key 22176db5a27SMasami Hiramatsu * @node: An XBC node. 22276db5a27SMasami Hiramatsu * @key: A key string searched under @node 22376db5a27SMasami Hiramatsu * @anode: Iterated XBC node of array entry. 22476db5a27SMasami Hiramatsu * @value: Iterated value of array entry. 22576db5a27SMasami Hiramatsu * 22676db5a27SMasami Hiramatsu * Iterate array entries of given @key under @node. Each array entry node 227c23c8082SZhen Lei * is stored to @anode and @value. If the @node doesn't have @key node, 22876db5a27SMasami Hiramatsu * it does nothing. 22976db5a27SMasami Hiramatsu * Note that even if the found key node has only one value (not array) 230c23c8082SZhen Lei * this executes block once. However, if the found key node has no value 23176db5a27SMasami Hiramatsu * (key-only node), this does nothing. So don't use this for testing the 23276db5a27SMasami Hiramatsu * key-value pair existence. 23376db5a27SMasami Hiramatsu */ 23476db5a27SMasami Hiramatsu #define xbc_node_for_each_array_value(node, key, anode, value) \ 23576db5a27SMasami Hiramatsu for (value = xbc_node_find_value(node, key, &anode); value != NULL; \ 236ca24306dSMasami Hiramatsu anode = xbc_node_get_child(anode), \ 23776db5a27SMasami Hiramatsu value = anode ? xbc_node_get_data(anode) : NULL) 23876db5a27SMasami Hiramatsu 23976db5a27SMasami Hiramatsu /** 24076db5a27SMasami Hiramatsu * xbc_node_for_each_key_value() - Iterate key-value pairs under a node 24176db5a27SMasami Hiramatsu * @node: An XBC node. 24276db5a27SMasami Hiramatsu * @knode: Iterated key node 24376db5a27SMasami Hiramatsu * @value: Iterated value string 24476db5a27SMasami Hiramatsu * 24576db5a27SMasami Hiramatsu * Iterate key-value pairs under @node. Each key node and value string are 24676db5a27SMasami Hiramatsu * stored in @knode and @value respectively. 24776db5a27SMasami Hiramatsu */ 24876db5a27SMasami Hiramatsu #define xbc_node_for_each_key_value(node, knode, value) \ 24976db5a27SMasami Hiramatsu for (knode = NULL, value = xbc_node_find_next_key_value(node, &knode);\ 25076db5a27SMasami Hiramatsu knode != NULL; value = xbc_node_find_next_key_value(node, &knode)) 25176db5a27SMasami Hiramatsu 25276db5a27SMasami Hiramatsu /** 25376db5a27SMasami Hiramatsu * xbc_for_each_key_value() - Iterate key-value pairs 25476db5a27SMasami Hiramatsu * @knode: Iterated key node 25576db5a27SMasami Hiramatsu * @value: Iterated value string 25676db5a27SMasami Hiramatsu * 25776db5a27SMasami Hiramatsu * Iterate key-value pairs in whole XBC tree. Each key node and value string 25876db5a27SMasami Hiramatsu * are stored in @knode and @value respectively. 25976db5a27SMasami Hiramatsu */ 26076db5a27SMasami Hiramatsu #define xbc_for_each_key_value(knode, value) \ 26176db5a27SMasami Hiramatsu xbc_node_for_each_key_value(NULL, knode, value) 26276db5a27SMasami Hiramatsu 26376db5a27SMasami Hiramatsu /* Compose partial key */ 26476db5a27SMasami Hiramatsu int __init xbc_node_compose_key_after(struct xbc_node *root, 26576db5a27SMasami Hiramatsu struct xbc_node *node, char *buf, size_t size); 26676db5a27SMasami Hiramatsu 26776db5a27SMasami Hiramatsu /** 26876db5a27SMasami Hiramatsu * xbc_node_compose_key() - Compose full key string of the XBC node 26976db5a27SMasami Hiramatsu * @node: An XBC node. 27076db5a27SMasami Hiramatsu * @buf: A buffer to store the key. 27176db5a27SMasami Hiramatsu * @size: The size of the @buf. 27276db5a27SMasami Hiramatsu * 27376db5a27SMasami Hiramatsu * Compose the full-length key of the @node into @buf. Returns the total 27476db5a27SMasami Hiramatsu * length of the key stored in @buf. Or returns -EINVAL if @node is NULL, 27576db5a27SMasami Hiramatsu * and -ERANGE if the key depth is deeper than max depth. 27676db5a27SMasami Hiramatsu */ 27776db5a27SMasami Hiramatsu static inline int __init xbc_node_compose_key(struct xbc_node *node, 27876db5a27SMasami Hiramatsu char *buf, size_t size) 27976db5a27SMasami Hiramatsu { 28076db5a27SMasami Hiramatsu return xbc_node_compose_key_after(NULL, node, buf, size); 28176db5a27SMasami Hiramatsu } 28276db5a27SMasami Hiramatsu 28376db5a27SMasami Hiramatsu /* XBC node initializer */ 284bdac5c2bSMasami Hiramatsu int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos); 28589b74cacSMasami Hiramatsu 286e306220cSMasami Hiramatsu /* XBC node and size information */ 287e306220cSMasami Hiramatsu int __init xbc_get_info(int *node_size, size_t *data_size); 28876db5a27SMasami Hiramatsu 28976db5a27SMasami Hiramatsu /* XBC cleanup data structures */ 290e46d3be7SQiang Zhang void __init _xbc_exit(bool early); 291e46d3be7SQiang Zhang 292e46d3be7SQiang Zhang static inline void xbc_exit(void) 293e46d3be7SQiang Zhang { 294e46d3be7SQiang Zhang _xbc_exit(false); 295e46d3be7SQiang Zhang } 29676db5a27SMasami Hiramatsu 297a2a9d67aSMasami Hiramatsu /* XBC embedded bootconfig data in kernel */ 298a2a9d67aSMasami Hiramatsu #ifdef CONFIG_BOOT_CONFIG_EMBED 299a2a9d67aSMasami Hiramatsu const char * __init xbc_get_embedded_bootconfig(size_t *size); 300a2a9d67aSMasami Hiramatsu #else 301a2a9d67aSMasami Hiramatsu static inline const char *xbc_get_embedded_bootconfig(size_t *size) 302a2a9d67aSMasami Hiramatsu { 303a2a9d67aSMasami Hiramatsu return NULL; 304a2a9d67aSMasami Hiramatsu } 305a2a9d67aSMasami Hiramatsu #endif 306a2a9d67aSMasami Hiramatsu 30776db5a27SMasami Hiramatsu #endif 308