diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7c206ce734f6dabc49c2a97767f19917767a3107..b885b9e146fcec53754aebafe41926c9d8528e92 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -938,6 +938,7 @@ config ARCH_QEMU select OF_CONTROL select PL01X_SERIAL imply CMD_DM + imply DM_RNG imply DM_RTC imply RTC_PL031 diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index c76ecc013c98143b54b3be4d563bb90cd80b1d14..0faad3f3195429299ea7dc6d65a00a5235218eb5 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -18,14 +18,14 @@ buttons { compatible = "gpio-keys"; - summer { + btn1 { gpios = <&gpio_a 3 0>; - label = "summer"; + label = "button1"; }; - christmas { + btn2 { gpios = <&gpio_a 4 0>; - label = "christmas"; + label = "button2"; }; }; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index c7d137691163e664d34b87e0e72d64735a2a5774..fa84b2c10f3bc8af412478b3eede0c300de294b5 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -55,14 +55,14 @@ buttons { compatible = "gpio-keys"; - summer { + btn1 { gpios = <&gpio_a 3 0>; - label = "summer"; + label = "button1"; }; - christmas { + btn2 { gpios = <&gpio_a 4 0>; - label = "christmas"; + label = "button2"; }; }; diff --git a/cmd/Kconfig b/cmd/Kconfig index 4cb171790b34c994bd30dbbc68f6034978b98158..a3166e4f31428c5cf75fe90b3f34072a330d5cfa 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1751,6 +1751,77 @@ config CMD_QFW feature is to allow easy loading of files passed to qemu-system via -kernel / -initrd +config CMD_PSTORE + bool "pstore" + help + This provides access to Linux PStore with Rammoops backend. The main + feature is to allow to display or save PStore records. + + See doc/pstore.rst for more information. + +if CMD_PSTORE + +config CMD_PSTORE_MEM_ADDR + hex "Memory Address" + depends on CMD_PSTORE + help + Base addr used for PStore ramoops memory, should be identical to + ramoops.mem_address parameter used by kernel + +config CMD_PSTORE_MEM_SIZE + hex "Memory size" + depends on CMD_PSTORE + default "0x10000" + help + Size of PStore ramoops memory, should be identical to ramoops.mem_size + parameter used by kernel, a power of 2 and larger than the sum of the + record sizes + +config CMD_PSTORE_RECORD_SIZE + hex "Dump record size" + depends on CMD_PSTORE + default "0x1000" + help + Size of each dump done on oops/panic, should be identical to + ramoops.record_size parameter used by kernel and a power of 2 + Must be non-zero + +config CMD_PSTORE_CONSOLE_SIZE + hex "Kernel console log size" + depends on CMD_PSTORE + default "0x1000" + help + Size of kernel console log, should be identical to + ramoops.console_size parameter used by kernel and a power of 2 + Must be non-zero + +config CMD_PSTORE_FTRACE_SIZE + hex "FTrace log size" + depends on CMD_PSTORE + default "0x1000" + help + Size of ftrace log, should be identical to ramoops.ftrace_size + parameter used by kernel and a power of 2 + +config CMD_PSTORE_PMSG_SIZE + hex "User space message log size" + depends on CMD_PSTORE + default "0x1000" + help + Size of user space message log, should be identical to + ramoops.pmsg_size parameter used by kernel and a power of 2 + +config CMD_PSTORE_ECC_SIZE + int "ECC size" + depends on CMD_PSTORE + default "0" + help + if non-zero, the option enables ECC support and specifies ECC buffer + size in bytes (1 is a special value, means 16 bytes ECC), should be + identical to ramoops.ramoops_ecc parameter used by kernel + +endif + source "cmd/mvebu/Kconfig" config CMD_TERMINAL diff --git a/cmd/Makefile b/cmd/Makefile index 015b83764c68cf5390b89bb21674be038e986d1a..19a891633f67ed4a34038fc6c5c84e3c1f53cfb5 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -116,6 +116,7 @@ obj-$(CONFIG_CMD_PCI) += pci.o endif obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PMC) += pmc.o +obj-$(CONFIG_CMD_PSTORE) += pstore.o obj-$(CONFIG_CMD_PXE) += pxe.o pxe_utils.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_CMD_QFW) += qfw.o diff --git a/cmd/button.c b/cmd/button.c index 84ad1653c7b5b1dcdfb0089cd0756548cb7280a5..64c5a8fa046727f34e2e1c68e00a3b1d96b17c9a 100644 --- a/cmd/button.c +++ b/cmd/button.c @@ -75,11 +75,11 @@ int do_button(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ret = show_button_state(dev); - return 0; + return !ret; } U_BOOT_CMD( - button, 4, 1, do_button, + button, 2, 1, do_button, "manage buttons", " \tGet button state\n" "button list\t\tShow a list of buttons" diff --git a/cmd/pstore.c b/cmd/pstore.c new file mode 100644 index 0000000000000000000000000000000000000000..9a8b38c7f26ef3aff169253b2c9df6474c25409c --- /dev/null +++ b/cmd/pstore.c @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright © 2019 Collabora Ltd + */ + +#include +#include +#include +#include +#include +#include +#include + +struct persistent_ram_buffer { + u32 sig; + u32 start; + u32 size; + u8 data[0]; +}; + +#define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ +#define RAMOOPS_KERNMSG_HDR "====" + +#define PSTORE_TYPE_DMESG 0 +#define PSTORE_TYPE_CONSOLE 2 +#define PSTORE_TYPE_FTRACE 3 +#define PSTORE_TYPE_PMSG 7 +#define PSTORE_TYPE_ALL 255 + +static phys_addr_t pstore_addr = CONFIG_CMD_PSTORE_MEM_ADDR; +static phys_size_t pstore_length = CONFIG_CMD_PSTORE_MEM_SIZE; +static unsigned int pstore_record_size = CONFIG_CMD_PSTORE_RECORD_SIZE; +static unsigned int pstore_console_size = CONFIG_CMD_PSTORE_CONSOLE_SIZE; +static unsigned int pstore_ftrace_size = CONFIG_CMD_PSTORE_FTRACE_SIZE; +static unsigned int pstore_pmsg_size = CONFIG_CMD_PSTORE_PMSG_SIZE; +static unsigned int pstore_ecc_size = CONFIG_CMD_PSTORE_ECC_SIZE; +static unsigned int buffer_size; + + /** + * pstore_read_kmsg_hdr() - Check kernel header and get compression flag if + * available. + * @buffer: Kernel messages buffer. + * @compressed: Returns TRUE if kernel buffer is compressed, else FALSE. + * + * Check if buffer starts with a kernel header of the form: + * ====.[-]\n + * If is equal to 'C' then the buffer is compressed, else iter + * should be 'D'. + * + * Return: Length of kernel header. + */ +static int pstore_read_kmsg_hdr(char *buffer, bool *compressed) +{ + char *ptr = buffer; + *compressed = false; + + if (strncmp(RAMOOPS_KERNMSG_HDR, ptr, strlen(RAMOOPS_KERNMSG_HDR)) != 0) + return 0; + + ptr += strlen(RAMOOPS_KERNMSG_HDR); + + ptr = strchr(ptr, '\n'); + if (!ptr) + return 0; + + if (ptr[-2] == '-' && ptr[-1] == 'C') + *compressed = true; + + return ptr - buffer + 1; +} + +/** + * pstore_get_buffer() - Get unwrapped record buffer + * @sig: Signature to check + * @buffer: Buffer containing wrapped record + * @size: wrapped record size + * @dest: Buffer used to store unwrapped record + * + * The record starts with header. + * The signature is 'DBGC' for all records except for Ftrace's record(s) wich + * use LINUX_VERSION_CODE ^ 'DBGC'. + * Use 0 for @sig to prevent checking signature. + * Start and size are 4 bytes long. + * + * Return: record's length + */ +static u32 pstore_get_buffer(u32 sig, phys_addr_t buffer, u32 size, char *dest) +{ + struct persistent_ram_buffer *prb = + (struct persistent_ram_buffer *)map_sysmem(buffer, size); + u32 dest_size; + + if (sig == 0 || prb->sig == sig) { + if (prb->size == 0) { + log_debug("found existing empty buffer\n"); + return 0; + } + + if (prb->size > size) { + log_debug("found existing invalid buffer, size %u, start %u\n", + prb->size, prb->start); + return 0; + } + } else { + log_debug("no valid data in buffer (sig = 0x%08x)\n", prb->sig); + return 0; + } + + log_debug("found existing buffer, size %u, start %u\n", + prb->size, prb->start); + + memcpy(dest, &prb->data[prb->start], prb->size - prb->start); + memcpy(dest + prb->size - prb->start, &prb->data[0], prb->start); + + dest_size = prb->size; + unmap_sysmem(prb); + + return dest_size; +} + +/** + * pstore_init_buffer_size() - Init buffer size to largest record size + * + * Records, console, FTrace and user logs can use different buffer sizes. + * This function allows to retrieve the biggest one. + */ +static void pstore_init_buffer_size(void) +{ + if (pstore_record_size > buffer_size) + buffer_size = pstore_record_size; + + if (pstore_console_size > buffer_size) + buffer_size = pstore_console_size; + + if (pstore_ftrace_size > buffer_size) + buffer_size = pstore_ftrace_size; + + if (pstore_pmsg_size > buffer_size) + buffer_size = pstore_pmsg_size; +} + +/** + * pstore_set() - Initialize PStore settings from command line arguments + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Set pstore reserved memory info, starting at 'addr' for 'len' bytes. + * Default length for records is 4K. + * Mandatory arguments: + * - addr: ramoops starting address + * - len: ramoops total length + * Optional arguments: + * - record-size: size of one panic or oops record ('dump' type) + * - console-size: size of the kernel logs record + * - ftrace-size: size of the ftrace record(s), this can be a single record or + * divided in parts based on number of CPUs + * - pmsg-size: size of the user space logs record + * - ecc-size: enables/disables ECC support and specifies ECC buffer size in + * bytes (0 disables it, 1 is a special value, means 16 bytes ECC) + * + * Return: zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ +static int pstore_set(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc < 3) + return CMD_RET_USAGE; + + /* Address is specified since argc > 2 + */ + pstore_addr = simple_strtoul(argv[1], NULL, 16); + + /* Length is specified since argc > 2 + */ + pstore_length = simple_strtoul(argv[2], NULL, 16); + + if (argc > 3) + pstore_record_size = simple_strtoul(argv[3], NULL, 16); + + if (argc > 4) + pstore_console_size = simple_strtoul(argv[4], NULL, 16); + + if (argc > 5) + pstore_ftrace_size = simple_strtoul(argv[5], NULL, 16); + + if (argc > 6) + pstore_pmsg_size = simple_strtoul(argv[6], NULL, 16); + + if (argc > 7) + pstore_ecc_size = simple_strtoul(argv[7], NULL, 16); + + if (pstore_length < (pstore_record_size + pstore_console_size + + pstore_ftrace_size + pstore_pmsg_size)) { + printf("pstore should be larger than the sum of all records sizes\n"); + pstore_length = 0; + } + + log_debug("pstore set done: start 0x%08llx - length 0x%llx\n", + (unsigned long long)pstore_addr, + (unsigned long long)pstore_length); + + return 0; +} + +/** + * pstore_print_buffer() - Print buffer + * @type: buffer type + * @buffer: buffer to print + * @size: buffer size + * + * Print buffer type and content + */ +static void pstore_print_buffer(char *type, char *buffer, u32 size) +{ + u32 i = 0; + + printf("**** %s\n", type); + while (i < size && buffer[i] != 0) { + putc(buffer[i]); + i++; + } +} + +/** + * pstore_display() - Display existing records in pstore reserved memory + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * A 'record-type' can be given to only display records of this kind. + * If no 'record-type' is given, all valid records are dispayed. + * 'record-type' can be one of 'dump', 'console', 'ftrace' or 'user'. For 'dump' + * and 'ftrace' types, a 'nb' can be given to only display one record. + * + * Return: zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ +static int pstore_display(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + int type = PSTORE_TYPE_ALL; + phys_addr_t ptr; + char *buffer; + u32 size; + int header_len = 0; + bool compressed; + + if (argc > 1) { + if (!strcmp(argv[1], "dump")) + type = PSTORE_TYPE_DMESG; + else if (!strcmp(argv[1], "console")) + type = PSTORE_TYPE_CONSOLE; + else if (!strcmp(argv[1], "ftrace")) + type = PSTORE_TYPE_FTRACE; + else if (!strcmp(argv[1], "user")) + type = PSTORE_TYPE_PMSG; + else + return CMD_RET_USAGE; + } + + if (pstore_length == 0) { + printf("Please set PStore configuration\n"); + return CMD_RET_USAGE; + } + + if (buffer_size == 0) + pstore_init_buffer_size(); + + buffer = malloc_cache_aligned(buffer_size); + + if (type == PSTORE_TYPE_DMESG || type == PSTORE_TYPE_ALL) { + ptr = pstore_addr; + phys_addr_t ptr_end = ptr + pstore_length - pstore_pmsg_size + - pstore_ftrace_size - pstore_console_size; + + if (argc > 2) { + ptr += simple_strtoul(argv[2], NULL, 10) + * pstore_record_size; + ptr_end = ptr + pstore_record_size; + } + + while (ptr < ptr_end) { + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, + pstore_record_size, buffer); + ptr += pstore_record_size; + + if (size == 0) + continue; + + header_len = pstore_read_kmsg_hdr(buffer, &compressed); + if (header_len == 0) { + log_debug("no valid kernel header\n"); + continue; + } + + if (compressed) { + printf("Compressed buffer, display not available\n"); + continue; + } + + pstore_print_buffer("Dump", buffer + header_len, + size - header_len); + } + } + + if (type == PSTORE_TYPE_CONSOLE || type == PSTORE_TYPE_ALL) { + ptr = pstore_addr + pstore_length - pstore_pmsg_size + - pstore_ftrace_size - pstore_console_size; + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, + pstore_console_size, buffer); + if (size != 0) + pstore_print_buffer("Console", buffer, size); + } + + if (type == PSTORE_TYPE_FTRACE || type == PSTORE_TYPE_ALL) { + ptr = pstore_addr + pstore_length - pstore_pmsg_size + - pstore_ftrace_size; + /* The FTrace record(s) uses LINUX_VERSION_CODE ^ 'DBGC' + * signature, pass 0 to pstore_get_buffer to prevent + * checking it + */ + size = pstore_get_buffer(0, ptr, pstore_ftrace_size, buffer); + if (size != 0) + pstore_print_buffer("FTrace", buffer, size); + } + + if (type == PSTORE_TYPE_PMSG || type == PSTORE_TYPE_ALL) { + ptr = pstore_addr + pstore_length - pstore_pmsg_size; + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, + pstore_pmsg_size, buffer); + if (size != 0) + pstore_print_buffer("User", buffer, size); + } + + free(buffer); + + return 0; +} + +/** + * pstore_save() - Save existing records from pstore reserved memory + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * the records are saved under 'directory path', which should already exist, + * to partition 'part' on device type 'interface' instance 'dev' + * Filenames are automatically generated, depending on record type, like in + * /sys/fs/pstore under Linux + * + * Return: zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ +static int pstore_save(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + phys_addr_t ptr, ptr_end; + char *buffer; + char *save_argv[6]; + char addr[19], length[19]; + char path[256]; + u32 size; + unsigned int index; + int header_len = 0; + bool compressed; + + if (argc < 4) + return CMD_RET_USAGE; + + if (pstore_length == 0) { + printf("Please set PStore configuration\n"); + return CMD_RET_USAGE; + } + + if (buffer_size == 0) + pstore_init_buffer_size(); + + buffer = malloc_cache_aligned(buffer_size); + sprintf(addr, "0x%p", buffer); + + save_argv[0] = argv[0]; + save_argv[1] = argv[1]; + save_argv[2] = argv[2]; + save_argv[3] = addr; + save_argv[4] = path; + save_argv[5] = length; + + /* Save all Dump records */ + ptr = pstore_addr; + ptr_end = ptr + pstore_length - pstore_pmsg_size - pstore_ftrace_size + - pstore_console_size; + index = 0; + while (ptr < ptr_end) { + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, + pstore_record_size, buffer); + ptr += pstore_record_size; + + if (size == 0) + continue; + + header_len = pstore_read_kmsg_hdr(buffer, &compressed); + if (header_len == 0) { + log_debug("no valid kernel header\n"); + continue; + } + + sprintf(addr, "0x%08lx", (ulong)map_to_sysmem(buffer + header_len)); + sprintf(length, "0x%X", size - header_len); + sprintf(path, "%s/dmesg-ramoops-%u%s", argv[3], index, + compressed ? ".enc.z" : ""); + do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY); + index++; + } + + sprintf(addr, "0x%08lx", (ulong)map_to_sysmem(buffer)); + + /* Save Console record */ + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, pstore_console_size, + buffer); + if (size != 0) { + sprintf(length, "0x%X", size); + sprintf(path, "%s/console-ramoops-0", argv[3]); + do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY); + } + ptr += pstore_console_size; + + /* Save FTrace record(s) + * The FTrace record(s) uses LINUX_VERSION_CODE ^ 'DBGC' signature, + * pass 0 to pstore_get_buffer to prevent checking it + */ + size = pstore_get_buffer(0, ptr, pstore_ftrace_size, buffer); + if (size != 0) { + sprintf(length, "0x%X", size); + sprintf(path, "%s/ftrace-ramoops-0", argv[3]); + do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY); + } + ptr += pstore_ftrace_size; + + /* Save Console record */ + size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, pstore_pmsg_size, + buffer); + if (size != 0) { + sprintf(length, "0x%X", size); + sprintf(path, "%s/pmsg-ramoops-0", argv[3]); + do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY); + } + + free(buffer); + + return 0; +} + +static struct cmd_tbl cmd_pstore_sub[] = { + U_BOOT_CMD_MKENT(set, 8, 0, pstore_set, "", ""), + U_BOOT_CMD_MKENT(display, 3, 0, pstore_display, "", ""), + U_BOOT_CMD_MKENT(save, 4, 0, pstore_save, "", ""), +}; + +static int do_pstore(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) +{ + struct cmd_tbl *c; + + if (argc < 2) + return CMD_RET_USAGE; + + /* Strip off leading argument */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], cmd_pstore_sub, ARRAY_SIZE(cmd_pstore_sub)); + + if (!c) + return CMD_RET_USAGE; + + return c->cmd(cmdtp, flag, argc, argv); +} + +void fdt_fixup_pstore(void *blob) +{ + char node[32]; + int nodeoffset; /* node offset from libfdt */ + + nodeoffset = fdt_path_offset(blob, "/"); + if (nodeoffset < 0) { + /* Not found or something else bad happened. */ + log_err("fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); + return; + } + + nodeoffset = fdt_add_subnode(blob, nodeoffset, "reserved-memory"); + if (nodeoffset < 0) { + log_err("Add 'reserved-memory' node failed: %s\n", + fdt_strerror(nodeoffset)); + return; + } + fdt_setprop_u32(blob, nodeoffset, "#address-cells", 2); + fdt_setprop_u32(blob, nodeoffset, "#size-cells", 2); + fdt_setprop_empty(blob, nodeoffset, "ranges"); + + sprintf(node, "ramoops@%llx", (unsigned long long)pstore_addr); + nodeoffset = fdt_add_subnode(blob, nodeoffset, node); + if (nodeoffset < 0) { + log_err("Add '%s' node failed: %s\n", node, fdt_strerror(nodeoffset)); + return; + } + fdt_setprop_string(blob, nodeoffset, "compatible", "ramoops"); + fdt_setprop_u64(blob, nodeoffset, "reg", pstore_addr); + fdt_appendprop_u64(blob, nodeoffset, "reg", pstore_length); + fdt_setprop_u32(blob, nodeoffset, "record-size", pstore_record_size); + fdt_setprop_u32(blob, nodeoffset, "console-size", pstore_console_size); + fdt_setprop_u32(blob, nodeoffset, "ftrace-size", pstore_ftrace_size); + fdt_setprop_u32(blob, nodeoffset, "pmsg-size", pstore_pmsg_size); + fdt_setprop_u32(blob, nodeoffset, "ecc-size", pstore_ecc_size); +} + +U_BOOT_CMD(pstore, 10, 0, do_pstore, + "Manage Linux Persistent Storage", + "set [record-size] [console-size] [ftrace-size] [pmsg_size] [ecc-size]\n" + "- Set pstore reserved memory info, starting at 'addr' for 'len' bytes.\n" + " Default length for records is 4K.\n" + " 'record-size' is the size of one panic or oops record ('dump' type).\n" + " 'console-size' is the size of the kernel logs record.\n" + " 'ftrace-size' is the size of the ftrace record(s), this can be a single\n" + " record or divided in parts based on number of CPUs.\n" + " 'pmsg-size' is the size of the user space logs record.\n" + " 'ecc-size' enables/disables ECC support and specifies ECC buffer size in\n" + " bytes (0 disables it, 1 is a special value, means 16 bytes ECC).\n" + "pstore display [record-type] [nb]\n" + "- Display existing records in pstore reserved memory. A 'record-type' can\n" + " be given to only display records of this kind. 'record-type' can be one\n" + " of 'dump', 'console', 'ftrace' or 'user'. For 'dump' and 'ftrace' types,\n" + " a 'nb' can be given to only display one record.\n" + "pstore save \n" + "- Save existing records in pstore reserved memory under 'directory path'\n" + " to partition 'part' on device type 'interface' instance 'dev'.\n" + " Filenames are automatically generated, depending on record type, like\n" + " in /sys/fs/pstore under Linux.\n" + " The 'directory-path' should already exist.\n" +); diff --git a/common/image-fdt.c b/common/image-fdt.c index 3d6935ad40b6661aaa1d0989ad5a296cf7d54947..327a8c4c39591ba5867bd79d610e91fed3c81332 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -567,6 +567,10 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, /* Update ethernet nodes */ fdt_fixup_ethernet(blob); +#if CONFIG_IS_ENABLED(CMD_PSTORE) + /* Append PStore configuration */ + fdt_fixup_pstore(blob); +#endif if (IMAGE_OF_BOARD_SETUP) { fdt_ret = ft_board_setup(blob, gd->bd); if (fdt_ret) { diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 807b1dc05937a91112c97971accdabc50662762c..620ea1e8b43993e8180b595149486a2d38cd7aa7 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1237,6 +1237,7 @@ endchoice config SPL_USB_SDP_SUPPORT bool "Support SDP (Serial Download Protocol)" + depends on SPL_SERIAL_SUPPORT help Enable Serial Download Protocol (SDP) device support in SPL. This allows to download images into memory and execute (jump to) them diff --git a/common/spl/spl.c b/common/spl/spl.c index 4840d1d36707bbea20d2ff0214942d2f77c14b75..63c48fbf33df75a48ce3e4d52c1810761e411711 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -552,7 +552,9 @@ static int boot_from_devices(struct spl_image_info *spl_image, struct spl_image_loader *loader; loader = spl_ll_find_loader(spl_boot_list[i]); -#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT) +#if defined(CONFIG_SPL_SERIAL_SUPPORT) \ + && defined(CONFIG_SPL_LIBCOMMON_SUPPORT) \ + && !defined(CONFIG_SILENT_CONSOLE) if (loader) printf("Trying to boot from %s\n", loader->name); else diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index c3ca796d511a9c076921f4d99cb4f7353e9b5734..7c713cb4a4f7af9b7f3c7983f7ed87cd7ee3d52e 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -80,6 +80,8 @@ CONFIG_CMD_CBFS=y CONFIG_CMD_CRAMFS=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y +CONFIG_CMD_PSTORE=y +CONFIG_CMD_PSTORE_MEM_ADDR=0x3000000 CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 18f787cb518a99dca59981dd55a00149780b096c..6ac291997776d22ff79ee4a4136093a619fb727f 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -93,6 +93,8 @@ CONFIG_CMD_CRAMFS=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_SQUASHFS=y CONFIG_CMD_MTDPARTS=y +CONFIG_CMD_PSTORE=y +CONFIG_CMD_PSTORE_MEM_ADDR=0x3000000 CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y diff --git a/doc/develop/global_data.rst b/doc/develop/global_data.rst new file mode 100644 index 0000000000000000000000000000000000000000..9e7c8a24da093a91a0f089488ff32ab9318ad679 --- /dev/null +++ b/doc/develop/global_data.rst @@ -0,0 +1,53 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Global data +=========== + +Globally required fields are held in the global data structure. A pointer to the +structure is available as symbol gd. The symbol is made available by the macro +%DECLARE_GLOBAL_DATA_PTR. + +Register pointing to global data +-------------------------------- + +On most architectures the global data pointer is stored in a register. + ++------------+----------+ +| ARC | r25 | ++------------+----------+ +| ARM 32bit | r9 | ++------------+----------+ +| ARM 64bit | x18 | ++------------+----------+ +| M68000 | d7 | ++------------+----------+ +| MicroBlaze | r31 | ++------------+----------+ +| NDS32 | r10 | ++------------+----------+ +| Nios II | gp | ++------------+----------+ +| PowerPC | r2 | ++------------+----------+ +| RISC-V | gp (x3) | ++------------+----------+ +| SuperH | r13 | ++------------+----------+ + +The sandbox, x86, and Xtensa are notable exceptions. + +Clang for ARM does not support assigning a global register. When using Clang +gd is defined as an inline function using assembly code. This adds a few bytes +to the code size. + +Binaries called by U-Boot are not aware of the register usage and will not +conserve gd. UEFI binaries call the API provided by U-Boot and may return to +U-Boot. The value of gd has to be saved every time U-Boot is left and restored +whenever U-Boot is reentered. This is also relevant for the implementation of +function tracing. For setting the value of gd function set_gd() can be used. + +Global data structure +--------------------- + +.. kernel-doc:: include/asm-generic/global_data.h + :internal: diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 98a95ad434c4eed206359bc91946bb037806694f..89e80eab94583f9f0e7ac1daea48e9a3e046d945 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -9,4 +9,5 @@ Develop U-Boot coccinelle crash_dumps + global_data logging diff --git a/doc/index.rst b/doc/index.rst index fd9f10f28e4c6509101f6ee74296c25f3870254f..68a083b16ba8470142f10e34107d5a9a65ae00bb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -109,6 +109,13 @@ Android-specific features available in U-Boot. android/index +Command line +------------ +.. toctree:: + :maxdepth: 2 + + pstore.rst + Indices and tables ================== diff --git a/doc/pstore.rst b/doc/pstore.rst new file mode 100644 index 0000000000000000000000000000000000000000..8427d8fd97a9e8af9ff21e5f518205b6db0d6a49 --- /dev/null +++ b/doc/pstore.rst @@ -0,0 +1,82 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +PStore command +============== + +Design +------ + +Linux PStore and Ramoops modules (Linux config options PSTORE and PSTORE_RAM) +allow to use memory to pass data from the dying breath of a crashing kernel to +its successor. This command allows to read those records from U-Boot command +line. + +Ramoops is an oops/panic logger that writes its logs to RAM before the system +crashes. It works by logging oopses and panics in a circular buffer. Ramoops +needs a system with persistent RAM so that the content of that area can survive +after a restart. + +Ramoops uses a predefined memory area to store the dump. + +Ramoops parameters can be passed as kernel parameters or through Device Tree, +i.e.:: + + ramoops.mem_address=0x30000000 ramoops.mem_size=0x100000 ramoops.record_size=0x2000 ramoops.console_size=0x2000 memmap=0x100000$0x30000000 + +The same values should be set in U-Boot to be able to retrieve the records. +This values can be set at build time in U-Boot configuration file, or at runtime. +U-Boot automatically patches the Device Tree to pass the Ramoops parameters to +the kernel. + +The PStore configuration parameters are: + +======================= ========== + Name Default +======================= ========== +CMD_PSTORE_MEM_ADDR +CMD_PSTORE_MEM_SIZE 0x10000 +CMD_PSTORE_RECORD_SIZE 0x1000 +CMD_PSTORE_CONSOLE_SIZE 0x1000 +CMD_PSTORE_FTRACE_SIZE 0x1000 +CMD_PSTORE_PMSG_SIZE 0x1000 +CMD_PSTORE_ECC_SIZE 0 +======================= ========== + +Records sizes should be a power of 2. +The memory size and the record/console size must be non-zero. + +Multiple 'dump' records can be stored in the memory reserved for PStore. +The memory size has to be larger than the sum of the record sizes, i.e.:: + + MEM_SIZE >= RECORD_SIZE * n + CONSOLE_SIZE + FTRACE_SIZE + PMSG_SIZE + +Usage +----- + +Generate kernel crash +~~~~~~~~~~~~~~~~~~~~~ + +For test purpose, you can generate a kernel crash by setting reboot timeout to +10 seconds and trigger a panic:: + + $ sudo sh -c "echo 1 > /proc/sys/kernel/sysrq" + $ sudo sh -c "echo 10 > /proc/sys/kernel/panic" + $ sudo sh -c "echo c > /proc/sysrq-trigger" + +Retrieve logs in U-Boot +~~~~~~~~~~~~~~~~~~~~~~~ + +First of all, unless PStore parameters as been set during U-Boot configuration +and match kernel ramoops parameters, it needs to be set using 'pstore set', e.g.:: + + => pstore set 0x30000000 0x100000 0x2000 0x2000 + +Then all available dumps can be displayed +using:: + + => pstore display + +Or saved to an existing directory in an Ext2 or Ext4 partition, e.g. on root +directory of 1st partition of the 2nd MMC:: + + => pstore save mmc 1:1 / diff --git a/doc/sphinx/cdomain.py b/doc/sphinx/cdomain.py index cf13ff3a656cdeb60f4c56e1fc5f52d701c8256a..cbac8e608dc4df7c01a351ef1178ef3697b01209 100644 --- a/doc/sphinx/cdomain.py +++ b/doc/sphinx/cdomain.py @@ -48,7 +48,10 @@ major, minor, patch = sphinx.version_info[:3] def setup(app): - app.override_domain(CDomain) + if (major == 1 and minor < 8): + app.override_domain(CDomain) + else: + app.add_domain(CDomain, override=True) return dict( version = __version__, diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index 22c373a623ca96d2bc36aa45a23d61626f31cb4c..1ea41f3c5b2e1f8774d07a6a4117cc27ad5dcf1a 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -1592,7 +1592,7 @@ static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev) static int rk3399_pmuclk_bind(struct udevice *dev) { -#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP) +#if CONFIG_IS_ENABLED(RESET_ROCKCHIP) int ret; ret = offsetof(struct rk3399_pmucru, pmucru_softrst_con[0]); diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index c2f80472b83a8a900f813e2f66db51bfba3e23a5..eb2600de3111d8cea5f882ff5a3580fe257c4d96 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -185,7 +185,15 @@ static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, dir_flags = get_gpio_dir_flags(dev, offset); - *dir_flags = flags; + /* + * For testing purposes keep the output value when switching to input. + * This allows us to manipulate the input value via the gpio command. + */ + if (flags & GPIOD_IS_IN) + *dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) | + (*dir_flags & GPIOD_IS_OUT_ACTIVE); + else + *dir_flags = flags; return 0; } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d79cdef62ed21d1ce1993074cd625ba98f2d805e..11ce110df3e6962d7e0c8a3aa271313c5c9e071e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -3111,3 +3111,12 @@ int mmc_set_bkops_enable(struct mmc *mmc) return 0; } #endif + +__weak int mmc_get_env_dev(void) +{ +#ifdef CONFIG_SYS_MMC_ENV_DEV + return CONFIG_SYS_MMC_ENV_DEV; +#else + return 0; +#endif +} diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 49be76670214f4d04520a288d7beca6c4e47704d..8e6c755f641687e8ec27e7df37a20b342e1dc48e 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -1644,6 +1644,11 @@ e1000_reset_hw(struct e1000_hw *hw) E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); + if (hw->mac_type == e1000_igb) { + E1000_WRITE_REG(hw, RXPBS, I210_RXPBSIZE_DEFAULT); + E1000_WRITE_REG(hw, TXPBS, I210_TXPBSIZE_DEFAULT); + } + /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ hw->tbi_compatibility_on = false; diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index 19ed4777d9ab693eed0288b4fea04d03247cefc9..072851ba31c6642a9c0d58ed08e01b25f17f1764 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -735,6 +735,7 @@ struct e1000_ffvt_entry { #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ +#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ #define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ #define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ #define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ @@ -745,6 +746,7 @@ struct e1000_ffvt_entry { #define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ #define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ #define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ +#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ #define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ @@ -2589,4 +2591,8 @@ struct e1000_hw { #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ + +#define I210_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */ +#define I210_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */ + #endif /* _E1000_HW_H_ */ diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index c507437f2e7de95b2f5d38d30ea38f526e180345..ebd94925e99d050637f4cf998ca20a53612c0eff 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -520,7 +520,7 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, fspi_writel(f, FSPI_LCKER_LOCK, f->iobase + FSPI_LCKCR); } -#if CONFIG_IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f) { int ret; @@ -808,7 +808,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) int ret, i; u32 reg; -#if CONFIG_IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) /* disable and unprepare clock to avoid glitch pass to controller */ nxp_fspi_clk_disable_unprep(f); @@ -898,7 +898,7 @@ static int nxp_fspi_claim_bus(struct udevice *dev) static int nxp_fspi_set_speed(struct udevice *bus, uint speed) { -#if CONFIG_IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) struct nxp_fspi *f = dev_get_priv(bus); int ret; @@ -924,7 +924,7 @@ static int nxp_fspi_set_mode(struct udevice *bus, uint mode) static int nxp_fspi_ofdata_to_platdata(struct udevice *bus) { struct nxp_fspi *f = dev_get_priv(bus); -#if CONFIG_IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) int ret; #endif @@ -950,7 +950,7 @@ static int nxp_fspi_ofdata_to_platdata(struct udevice *bus) f->ahb_addr = map_physmem(ahb_addr, ahb_size, MAP_NOCACHE); f->memmap_phy_size = ahb_size; -#if CONFIG_IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) ret = clk_get_by_name(bus, "fspi_en", &f->clk_en); if (ret) { dev_err(bus, "failed to get fspi_en clock\n"); diff --git a/drivers/sysreset/sysreset_mpc83xx.c b/drivers/sysreset/sysreset_mpc83xx.c index 456f006bc1264f28b9d8de659f56f3f069cff370..4e89971840f226a24845e08e4799e7d7925edf2d 100644 --- a/drivers/sysreset/sysreset_mpc83xx.c +++ b/drivers/sysreset/sysreset_mpc83xx.c @@ -106,7 +106,7 @@ static int print_83xx_arb_event(bool force, char *buf, int size) if (!force && !gd->arch.arbiter_event_address) return 0; - if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL)) { + if (CONFIG_IS_ENABLED(DISPLAY_AER_FULL)) { res = snprintf(buf, size, "Arbiter Event Status:\n" " %s: 0x%08lX\n" @@ -119,7 +119,7 @@ static int print_83xx_arb_event(bool force, char *buf, int size) "Master ID", mstr_id, master[mstr_id], "Transfer Size", tsize_val, tsize_bytes, "Transfer Type", ttype, transfer[ttype]); - } else if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) { + } else if (CONFIG_IS_ENABLED(DISPLAY_AER_BRIEF)) { res = snprintf(buf, size, "Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n", gd->arch.arbiter_event_attributes, @@ -183,8 +183,8 @@ static int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size) * TODO(mario.six@gdsys.cc): Move this into a dedicated * arbiter driver */ - if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL) || - CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) { + if (CONFIG_IS_ENABLED(DISPLAY_AER_FULL) || + CONFIG_IS_ENABLED(DISPLAY_AER_BRIEF)) { /* * If there was a bus monitor reset event, we force the arbiter * event to be printed diff --git a/env/Kconfig b/env/Kconfig index c6ba08878d672d9e608fef0f4151df7a89365abb..aa63fae021e94fbf11b26c33a66b94343279de0b 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -477,6 +477,10 @@ config ENV_EXT4_DEVICE_AND_PART If none, first valid partition in device D. If no partition table then means device D. + If ENV_EXT4_INTERFACE is set to "mmc" then device 'D' can be omitted, + leaving the string starting with a colon, and the boot device will + be used. + config ENV_EXT4_FILE string "Name of the EXT4 file to use for the environment" depends on ENV_IS_IN_EXT4 diff --git a/env/ext4.c b/env/ext4.c index f823b694099bbe95e056f0cc462a912a0e15c409..e666f7b9455ad3d3abd561fcd913a51afec8f2dd 100644 --- a/env/ext4.c +++ b/env/ext4.c @@ -41,7 +41,21 @@ __weak const char *env_ext4_get_intf(void) __weak const char *env_ext4_get_dev_part(void) { +#ifdef CONFIG_MMC + static char *part_str; + + if (!part_str) { + part_str = CONFIG_ENV_EXT4_DEVICE_AND_PART; + if (!strcmp(CONFIG_ENV_EXT4_INTERFACE, "mmc") && part_str[0] == ':') { + part_str = "0" CONFIG_ENV_EXT4_DEVICE_AND_PART; + part_str[0] += mmc_get_env_dev(); + } + } + + return part_str; +#else return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART; +#endif } static int env_ext4_save_buffer(env_t *env_new) diff --git a/env/fat.c b/env/fat.c index 71bf8bfa18f9f99f158688f50706e85a99197ce9..653a38fd937c8d998ce719b0a911de68599f29ad 100644 --- a/env/fat.c +++ b/env/fat.c @@ -29,15 +29,6 @@ # define LOADENV #endif -__weak int mmc_get_env_dev(void) -{ -#ifdef CONFIG_SYS_MMC_ENV_DEV - return CONFIG_SYS_MMC_ENV_DEV; -#else - return 0; -#endif -} - static char *env_fat_device_and_part(void) { #ifdef CONFIG_MMC diff --git a/env/mmc.c b/env/mmc.c index ba872701b0d5bd9210eeb4329ee1060218d35154..4e67180b23a0ba0449072720f9caf54d85d7be47 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -24,11 +24,6 @@ DECLARE_GLOBAL_DATA_PTR; -__weak int mmc_get_env_dev(void) -{ - return CONFIG_SYS_MMC_ENV_DEV; -} - #if CONFIG_IS_ENABLED(OF_CONTROL) static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val) { diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index d4a4e2215dc613f23092ebbdb013c0a72b1986ff..ebb740d34f32ce996459e134e101f6d89a8b79e4 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -24,149 +24,473 @@ #include #include -typedef struct global_data { +typedef struct global_data gd_t; + +/** + * struct global_data - global data structure + */ +struct global_data { + /** + * @bd: board information + */ struct bd_info *bd; + /** + * @flags: global data flags + * + * See &enum gd_flags + */ unsigned long flags; + /** + * @baudrate: baud rate of the serial interface + */ unsigned int baudrate; - unsigned long cpu_clk; /* CPU clock in Hz! */ + /** + * @cpu_clk: CPU clock rate in Hz + */ + unsigned long cpu_clk; + /** + * @bus_clk: platform clock rate in Hz + */ unsigned long bus_clk; + /** + * @pci_clk: PCI clock rate in Hz + */ /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */ unsigned long pci_clk; + /** + * @mem_clk: memory clock rate in Hz + */ unsigned long mem_clk; #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) || defined(CONFIG_DM_VIDEO) - unsigned long fb_base; /* Base address of framebuffer mem */ + /** + * @fb_base: base address of frame buffer memory + */ + unsigned long fb_base; #endif #if defined(CONFIG_POST) - unsigned long post_log_word; /* Record POST activities */ - unsigned long post_log_res; /* success of POST test */ - unsigned long post_init_f_time; /* When post_init_f started */ + /** + * @post_log_word: active POST tests + * + * @post_log_word is a bit mask defining which POST tests are recorded + * (see constants POST_*). + */ + unsigned long post_log_word; + /** + * @post_log_res: POST results + * + * @post_log_res is a bit mask with the POST results. A bit with value 1 + * indicates successful execution. + */ + unsigned long post_log_res; + /** + * @post_init_f_time: time in ms when post_init_f() started + */ + unsigned long post_init_f_time; #endif #ifdef CONFIG_BOARD_TYPES + /** + * @board_type: board type + * + * If a U-Boot configuration supports multiple board types, the actual + * board type may be stored in this field. + */ unsigned long board_type; #endif - unsigned long have_console; /* serial_init() was called */ + /** + * @have_console: console is available + * + * A value of 1 indicates that serial_init() was called and a console + * is available. + * A value of 0 indicates that console input and output drivers shall + * not be called. + */ + unsigned long have_console; #if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER) - unsigned long precon_buf_idx; /* Pre-Console buffer index */ + /** + * @precon_buf_idx: pre-console buffer index + * + * @precon_buf_idx indicates the current position of the buffer used to + * collect output before the console becomes available + */ + unsigned long precon_buf_idx; #endif - unsigned long env_addr; /* Address of Environment struct */ - unsigned long env_valid; /* Environment valid? enum env_valid */ - unsigned long env_has_init; /* Bitmask of boolean of struct env_location offsets */ - int env_load_prio; /* Priority of the loaded environment */ - - unsigned long ram_base; /* Base address of RAM used by U-Boot */ - unsigned long ram_top; /* Top address of RAM used by U-Boot */ - unsigned long relocaddr; /* Start address of U-Boot in RAM */ - phys_size_t ram_size; /* RAM size */ - unsigned long mon_len; /* monitor len */ - unsigned long irq_sp; /* irq stack pointer */ - unsigned long start_addr_sp; /* start_addr_stackpointer */ + /** + * @env_addr: address of environment structure + * + * @env_addr contains the address of the structure holding the + * environment variables. + */ + unsigned long env_addr; + /** + * @env_valid: environment is valid + * + * See &enum env_valid + */ + unsigned long env_valid; + /** + * @env_has_init: bit mask indicating environment locations + * + * &enum env_location defines which bit relates to which location + */ + unsigned long env_has_init; + /** + * @env_load_prio: priority of the loaded environment + */ + int env_load_prio; + /** + * @ram_base: base address of RAM used by U-Boot + */ + unsigned long ram_base; + /** + * @ram_top: top address of RAM used by U-Boot + */ + unsigned long ram_top; + /** + * @relocaddr: start address of U-Boot in RAM + * + * After relocation this field indicates the address to which U-Boot + * has been relocated. It can be displayed using the bdinfo command. + * Its value is needed to display the source code when debugging with + * GDB using the 'add-symbol-file u-boot ' command. + */ + unsigned long relocaddr; + /** + * @ram_size: RAM size in bytes + */ + phys_size_t ram_size; + /** + * @mon_len: monitor length in bytes + */ + unsigned long mon_len; + /** + * @irq_sp: IRQ stack pointer + */ + unsigned long irq_sp; + /** + * @start_addr_sp: initial stack pointer address + */ + unsigned long start_addr_sp; + /** + * @reloc_off: relocation offset + */ unsigned long reloc_off; - struct global_data *new_gd; /* relocated global data */ + /** + * @new_gd: pointer to relocated global data + */ + struct global_data *new_gd; #ifdef CONFIG_DM - struct udevice *dm_root; /* Root instance for Driver Model */ - struct udevice *dm_root_f; /* Pre-relocation root instance */ - struct list_head uclass_root; /* Head of core tree */ + /** + * @dm_root: root instance for Driver Model + */ + struct udevice *dm_root; + /** + * @dm_root_f: pre-relocation root instance + */ + struct udevice *dm_root_f; + /** + * @uclass_root: head of core tree + */ + struct list_head uclass_root; #endif #ifdef CONFIG_TIMER - struct udevice *timer; /* Timer instance for Driver Model */ + /** + * @timer: timer instance for Driver Model + */ + struct udevice *timer; #endif - - const void *fdt_blob; /* Our device tree, NULL if none */ - void *new_fdt; /* Relocated FDT */ - unsigned long fdt_size; /* Space reserved for relocated FDT */ + /** + * @fdt_blob: U-Boot's own device tree, NULL if none + */ + const void *fdt_blob; + /** + * @new_fdt: relocated device tree + */ + void *new_fdt; + /** + * @fdt_size: space reserved for relocated device space + */ + unsigned long fdt_size; #ifdef CONFIG_OF_LIVE + /** + * @of_root: root node of the live tree + */ struct device_node *of_root; #endif #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) - const void *multi_dtb_fit; /* uncompressed multi-dtb FIT image */ + /** + * @multi_dtb_fit: pointer to uncompressed multi-dtb FIT image + */ + const void *multi_dtb_fit; #endif - struct jt_funcs *jt; /* jump table */ - char env_buf[32]; /* buffer for env_get() before reloc. */ + /** + * @jt: jump table + * + * The jump table contains pointers to exported functions. A pointer to + * the jump table is passed to standalone applications. + */ + struct jt_funcs *jt; + /** + * @env_buf: buffer for env_get() before reloc + */ + char env_buf[32]; #ifdef CONFIG_TRACE - void *trace_buff; /* The trace buffer */ + /** + * @trace_buff: trace buffer + * + * When tracing function in U-Boot this field points to the buffer + * recording the function calls. + */ + void *trace_buff; #endif #if defined(CONFIG_SYS_I2C) - int cur_i2c_bus; /* current used i2c bus */ + /** + * @cur_i2c_bus: currently used I2C bus + */ + int cur_i2c_bus; #endif + /** + * @timebase_h: high 32 bits of timer + */ unsigned int timebase_h; + /** + * @timebase_l: low 32 bits of timer + */ unsigned int timebase_l; #if CONFIG_VAL(SYS_MALLOC_F_LEN) - unsigned long malloc_base; /* base address of early malloc() */ - unsigned long malloc_limit; /* limit address */ - unsigned long malloc_ptr; /* current address */ + /** + * @malloc_base: base address of early malloc() + */ + unsigned long malloc_base; + /** + * @malloc_limit: limit address of early malloc() + */ + unsigned long malloc_limit; + /** + * @malloc_ptr: current address of early malloc() + */ + unsigned long malloc_ptr; #endif #ifdef CONFIG_PCI - struct pci_controller *hose; /* PCI hose for early use */ - phys_addr_t pci_ram_top; /* top of region accessible to PCI */ + /** + * @hose: PCI hose for early use + */ + struct pci_controller *hose; + /** + * @pci_ram_top: top of region accessible to PCI + */ + phys_addr_t pci_ram_top; #endif #ifdef CONFIG_PCI_BOOTDELAY + /** + * @pcidelay_done: delay time before scanning of PIC hose expired + * + * If CONFIG_PCI_BOOTDELAY=y, pci_hose_scan() waits for the number of + * milliseconds defined by environment variable pcidelay before + * scanning. Once this delay has expired the flag @pcidelay_done + * is set to 1. + */ int pcidelay_done; #endif - struct udevice *cur_serial_dev; /* current serial device */ - struct arch_global_data arch; /* architecture-specific data */ + /** + * @cur_serial_dev: current serial device + */ + struct udevice *cur_serial_dev; + /** + * @arch: architecture-specific data + */ + struct arch_global_data arch; #ifdef CONFIG_CONSOLE_RECORD - struct membuff console_out; /* console output */ - struct membuff console_in; /* console input */ + /** + * @console_out: output buffer for console recording + * + * This buffer is used to collect output during console recording. + */ + struct membuff console_out; + /** + * @console_in: input buffer for console recording + * + * If console recording is activated, this buffer can be used to + * emulate input. + */ + struct membuff console_in; #endif #ifdef CONFIG_DM_VIDEO - ulong video_top; /* Top of video frame buffer area */ - ulong video_bottom; /* Bottom of video frame buffer area */ + /** + * @video_top: top of video frame buffer area + */ + ulong video_top; + /** + * @video_bottom: bottom of video frame buffer area + */ + ulong video_bottom; #endif #ifdef CONFIG_BOOTSTAGE - struct bootstage_data *bootstage; /* Bootstage information */ - struct bootstage_data *new_bootstage; /* Relocated bootstage info */ + /** + * @bootstage: boot stage information + */ + struct bootstage_data *bootstage; + /** + * @new_bootstage: relocated boot stage information + */ + struct bootstage_data *new_bootstage; #endif #ifdef CONFIG_LOG - int log_drop_count; /* Number of dropped log messages */ - int default_log_level; /* For devices with no filters */ - struct list_head log_head; /* List of struct log_device */ - int log_fmt; /* Mask containing log format info */ + /** + * @log_drop_count: number of dropped log messages + * + * This counter is incremented for each log message which can not + * be processed because logging is not yet available as signaled by + * flag %GD_FLG_LOG_READY in @flags. + */ + int log_drop_count; + /** + * @default_log_level: default logging level + * + * For logging devices without filters @default_log_level defines the + * logging level, cf. &enum log_level_t. + */ + int default_log_level; + /** + * @log_head: list of logging devices + */ + struct list_head log_head; + /** + * @log_fmt: bit mask for logging format + * + * The @log_fmt bit mask selects the fields to be shown in log messages. + * &enum log_fmt defines the bits of the bit mask. + */ + int log_fmt; #endif #if CONFIG_IS_ENABLED(BLOBLIST) - struct bloblist_hdr *bloblist; /* Bloblist information */ - struct bloblist_hdr *new_bloblist; /* Relocated blolist info */ + /** + * @bloblist: blob list information + */ + struct bloblist_hdr *bloblist; + /** + * @new_bloblist: relocated blob list information + */ + struct bloblist_hdr *new_bloblist; # ifdef CONFIG_SPL + /** + * @spl_handoff: SPL hand-off information + */ struct spl_handoff *spl_handoff; # endif #endif #if defined(CONFIG_TRANSLATION_OFFSET) - fdt_addr_t translation_offset; /* optional translation offset */ + /** + * @translation_offset: optional translation offset + * + * See CONFIG_TRANSLATION_OFFSET. + */ + fdt_addr_t translation_offset; #endif #if CONFIG_IS_ENABLED(WDT) + /** + * @watchdog_dev: watchdog device + */ struct udevice *watchdog_dev; #endif -} gd_t; -#endif +}; +/** + * gd_board_type() - retrieve board type + * + * Return: global board type + */ #ifdef CONFIG_BOARD_TYPES #define gd_board_type() gd->board_type #else #define gd_board_type() 0 #endif -/* - * Global Data Flags +/** + * enum gd_flags - global data flags + * + * See field flags of &struct global_data. */ -#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ -#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ -#define GD_FLG_SILENT 0x00004 /* Silent mode */ -#define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ -#define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ -#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ -#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ -#define GD_FLG_ENV_READY 0x00080 /* Env. imported into hash table */ -#define GD_FLG_SERIAL_READY 0x00100 /* Pre-reloc serial console ready */ -#define GD_FLG_FULL_MALLOC_INIT 0x00200 /* Full malloc() is ready */ -#define GD_FLG_SPL_INIT 0x00400 /* spl_init() has been called */ -#define GD_FLG_SKIP_RELOC 0x00800 /* Don't relocate */ -#define GD_FLG_RECORD 0x01000 /* Record console */ -#define GD_FLG_ENV_DEFAULT 0x02000 /* Default variable flag */ -#define GD_FLG_SPL_EARLY_INIT 0x04000 /* Early SPL init is done */ -#define GD_FLG_LOG_READY 0x08000 /* Log system is ready for use */ -#define GD_FLG_WDT_READY 0x10000 /* Watchdog is ready for use */ -#define GD_FLG_SKIP_LL_INIT 0x20000 /* Don't perform low-level init */ -#define GD_FLG_SMP_READY 0x40000 /* SMP init is complete */ +enum gd_flags { + /** + * @GD_FLG_RELOC: code was relocated to RAM + */ + GD_FLG_RELOC = 0x00001, + /** + * @GD_FLG_DEVINIT: devices have been initialized + */ + GD_FLG_DEVINIT = 0x00002, + /** + * @GD_FLG_SILENT: silent mode + */ + GD_FLG_SILENT = 0x00004, + /** + * @GD_FLG_POSTFAIL: critical POST test failed + */ + GD_FLG_POSTFAIL = 0x00008, + /** + * @GD_FLG_POSTSTOP: POST sequence aborted + */ + GD_FLG_POSTSTOP = 0x00010, + /** + * @GD_FLG_LOGINIT: log Buffer has been initialized + */ + GD_FLG_LOGINIT = 0x00020, + /** + * @GD_FLG_DISABLE_CONSOLE: disable console (in & out) + */ + GD_FLG_DISABLE_CONSOLE = 0x00040, + /** + * @GD_FLG_ENV_READY: environment imported into hash table + */ + GD_FLG_ENV_READY = 0x00080, + /** + * @GD_FLG_SERIAL_READY: pre-relocation serial console ready + */ + GD_FLG_SERIAL_READY = 0x00100, + /** + * @GD_FLG_FULL_MALLOC_INIT: full malloc() is ready + */ + GD_FLG_FULL_MALLOC_INIT = 0x00200, + /** + * @GD_FLG_SPL_INIT: spl_init() has been called + */ + GD_FLG_SPL_INIT = 0x00400, + /** + * @GD_FLG_SKIP_RELOC: don't relocate + */ + GD_FLG_SKIP_RELOC = 0x00800, + /** + * @GD_FLG_RECORD: record console + */ + GD_FLG_RECORD = 0x01000, + /** + * @GD_FLG_ENV_DEFAULT: default variable flag + */ + GD_FLG_ENV_DEFAULT = 0x02000, + /** + * @GD_FLG_SPL_EARLY_INIT: early SPL initialization is done + */ + GD_FLG_SPL_EARLY_INIT = 0x04000, + /** + * @GD_FLG_LOG_READY: log system is ready for use + */ + GD_FLG_LOG_READY = 0x08000, + /** + * @GD_FLG_WDT_READY: watchdog is ready for use + */ + GD_FLG_WDT_READY = 0x10000, + /** + * @GD_FLG_SKIP_LL_INIT: don't perform low-level initialization + */ + GD_FLG_SKIP_LL_INIT = 0x20000, + /** + * @GD_FLG_SMP_READY: SMP initialization is complete + */ + GD_FLG_SMP_READY = 0x40000, +}; + +#endif /* __ASSEMBLY__ */ #endif /* __ASM_GENERIC_GBL_DATA_H */ diff --git a/include/bootm.h b/include/bootm.h index 0350c349f3770238724a949b1282c0ac4088508a..a812a6bf24fc46e3baa151ed13b07044acf105c4 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -75,4 +75,14 @@ void board_quiesce_devices(void); */ void switch_to_non_secure_mode(void); +/** + * arch_preboot_os() - arch specific configuration before booting + */ +void arch_preboot_os(void); + +/** + * board_preboot_os() - board specific configuration before booting + */ +void board_preboot_os(void); + #endif diff --git a/include/fdt_support.h b/include/fdt_support.h index 9684cffe80b2788ffd113a7c2ef71430fc9657f5..dbbac0fb6a3d161fbb4c68fad73a62d4ca02ff40 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -359,4 +359,7 @@ int fdt_update_ethernet_dt(void *blob); #ifdef CONFIG_FSL_MC_ENET void fdt_fixup_board_enet(void *blob); #endif +#ifdef CONFIG_CMD_PSTORE +void fdt_fixup_pstore(void *blob); +#endif #endif /* ifndef __FDT_SUPPORT_H */ diff --git a/lib/time.c b/lib/time.c index 47f8c84327d8829a923abd32e4892ca5ffc39a74..88bc50405ff39df143db028cfc6a90d988120506 100644 --- a/lib/time.c +++ b/lib/time.c @@ -91,13 +91,13 @@ uint64_t notrace get_ticks(void) ret = dm_timer_init(); if (ret) - return ret; + panic("Could not initialize timer (err %d)\n", ret); #endif } ret = timer_get_count(gd->timer, &count); if (ret) - return ret; + panic("Could not read count from timer (err %d)\n", ret); return count; } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 4bed2b0cdc7c2a59c7b620e89cd602933e8685b1..4ed7e124c9a24af180127386f876d21528978cf2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2365,6 +2365,12 @@ sub u_boot_line { ERROR("DISABLE_FDT_OR_INITRD_RELOC", "fdt or initrd relocation disabled at boot time\n" . $herecurr); } + + # Do not use CONFIG_ prefix in CONFIG_IS_ENABLED() calls + if ($line =~ /^\+.*CONFIG_IS_ENABLED\(CONFIG_\w*\).*/) { + ERROR("CONFIG_IS_ENABLED_CONFIG", + "CONFIG_IS_ENABLED() takes values without the CONFIG_ prefix\n" . $herecurr); + } } sub process { diff --git a/test/dm/button.c b/test/dm/button.c index 911780173657570a508e67be3ed4420ea8eb0f0b..ecaa47cf5f355bbd0a8fc85ef33424be29012f88 100644 --- a/test/dm/button.c +++ b/test/dm/button.c @@ -57,17 +57,17 @@ static int dm_test_button_label(struct unit_test_state *uts) { struct udevice *dev, *cmp; - ut_assertok(button_get_by_label("summer", &dev)); + ut_assertok(button_get_by_label("button1", &dev)); ut_asserteq(1, device_active(dev)); ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &cmp)); ut_asserteq_ptr(dev, cmp); - ut_assertok(button_get_by_label("christmas", &dev)); + ut_assertok(button_get_by_label("button2", &dev)); ut_asserteq(1, device_active(dev)); ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &cmp)); ut_asserteq_ptr(dev, cmp); - ut_asserteq(-ENODEV, button_get_by_label("spring", &dev)); + ut_asserteq(-ENODEV, button_get_by_label("nobutton", &dev)); return 0; } diff --git a/test/py/tests/test_button.py b/test/py/tests/test_button.py index 98067a98f2896c8c7a0ae97fbda186ccce015c72..3b7f148c8fcc48e6e51fed9f8f18674f489c9f74 100644 --- a/test/py/tests/test_button.py +++ b/test/py/tests/test_button.py @@ -4,16 +4,34 @@ import pytest @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_button') -def test_button_exit_statuses(u_boot_console): - """Test that non-input button commands correctly return the command - success/failure status.""" +def test_button_list(u_boot_console): + """Test listing buttons""" - expected_response = 'rc:0' response = u_boot_console.run_command('button list; echo rc:$?') - assert(expected_response in response) - response = u_boot_console.run_command('button summer; echo rc:$?') - assert(expected_response in response) + assert('button1' in response) + assert('button2' in response) + assert('rc:0' in response) + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('cmd_button') +@pytest.mark.buildconfigspec('cmd_gpio') +def test_button_return_code(u_boot_console): + """Test correct reporting of the button status + + The sandbox gpio driver reports the last output value as input value. + We can use this in our test to emulate different input statuses. + """ + + u_boot_console.run_command('gpio set a3; gpio input a3'); + response = u_boot_console.run_command('button button1; echo rc:$?') + assert('on' in response) + assert('rc:0' in response) + + u_boot_console.run_command('gpio clear a3; gpio input a3'); + response = u_boot_console.run_command('button button1; echo rc:$?') + assert('off' in response) + assert('rc:1' in response) - expected_response = 'rc:1' response = u_boot_console.run_command('button nonexistent-button; echo rc:$?') - assert(expected_response in response) + assert('not found' in response) + assert('rc:1' in response) diff --git a/test/py/tests/test_pstore.py b/test/py/tests/test_pstore.py new file mode 100644 index 0000000000000000000000000000000000000000..5a35724f60a70f39d15a85d40bf9a97620d29823 --- /dev/null +++ b/test/py/tests/test_pstore.py @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Collabora +# Author: Frédéric Danis + +import pytest +import u_boot_utils +import os +import tempfile +import shutil + +PSTORE_ADDR=0x3000000 +PSTORE_LENGTH=0x100000 +PSTORE_PANIC1='test/py/tests/test_pstore_data_panic1.hex' +PSTORE_PANIC2='test/py/tests/test_pstore_data_panic2.hex' +PSTORE_CONSOLE='test/py/tests/test_pstore_data_console.hex' +ADDR=0x01000008 + +def load_pstore(u_boot_console): + """Load PStore records from sample files""" + + output = u_boot_console.run_command_list([ + 'host load hostfs - 0x%x %s' % (PSTORE_ADDR, + os.path.join(u_boot_console.config.source_dir, PSTORE_PANIC1)), + 'host load hostfs - 0x%x %s' % (PSTORE_ADDR + 4096, + os.path.join(u_boot_console.config.source_dir, PSTORE_PANIC2)), + 'host load hostfs - 0x%x %s' % (PSTORE_ADDR + 253 * 4096, + os.path.join(u_boot_console.config.source_dir, PSTORE_CONSOLE)), + 'pstore set 0x%x 0x%x' % (PSTORE_ADDR, PSTORE_LENGTH)]) + +def checkfile(u_boot_console, path, filesize, checksum): + """Check file against MD5 checksum""" + + output = u_boot_console.run_command_list([ + 'load hostfs - %x %s' % (ADDR, path), + 'printenv filesize']) + assert('filesize=%x' % (filesize) in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(checksum in ''.join(output)) + +@pytest.mark.buildconfigspec('cmd_pstore') +def test_pstore_display_all_records(u_boot_console): + """Test that pstore displays all records.""" + + u_boot_console.run_command('') + load_pstore(u_boot_console) + response = u_boot_console.run_command('pstore display') + assert('**** Dump' in response) + assert('**** Console' in response) + +@pytest.mark.buildconfigspec('cmd_pstore') +def test_pstore_display_one_record(u_boot_console): + """Test that pstore displays only one record.""" + + u_boot_console.run_command('') + load_pstore(u_boot_console) + response = u_boot_console.run_command('pstore display dump 1') + assert('Panic#2 Part1' in response) + assert('**** Console' not in response) + +@pytest.mark.buildconfigspec('cmd_pstore') +def test_pstore_save_records(u_boot_console): + """Test that pstore saves all records.""" + + outdir = tempfile.mkdtemp() + + u_boot_console.run_command('') + load_pstore(u_boot_console) + u_boot_console.run_command('pstore save hostfs - %s' % (outdir)) + + checkfile(u_boot_console, '%s/dmesg-ramoops-0' % (outdir), 3798, '8059335ab4cfa62c77324c491659c503') + checkfile(u_boot_console, '%s/dmesg-ramoops-1' % (outdir), 4035, '3ff30df3429d81939c75d0070b5187b9') + checkfile(u_boot_console, '%s/console-ramoops-0' % (outdir), 4084, 'bb44de4a9b8ebd9b17ae98003287325b') + + shutil.rmtree(outdir) diff --git a/test/py/tests/test_pstore_data_console.hex b/test/py/tests/test_pstore_data_console.hex new file mode 100644 index 0000000000000000000000000000000000000000..e7f426e8928a2793457baced5f66ee165ef429f6 Binary files /dev/null and b/test/py/tests/test_pstore_data_console.hex differ diff --git a/test/py/tests/test_pstore_data_panic1.hex b/test/py/tests/test_pstore_data_panic1.hex new file mode 100644 index 0000000000000000000000000000000000000000..988929d12c25fee4c4242776a2ed0d78cdc55948 Binary files /dev/null and b/test/py/tests/test_pstore_data_panic1.hex differ diff --git a/test/py/tests/test_pstore_data_panic2.hex b/test/py/tests/test_pstore_data_panic2.hex new file mode 100644 index 0000000000000000000000000000000000000000..8f9d56cbe01e38f5f8fac6d46491497c9d7bda8f Binary files /dev/null and b/test/py/tests/test_pstore_data_panic2.hex differ diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py index 792196e6896e6c2350e3dd86909e06a127a84950..f71c70fb13a7587bdc026cace89dff2507c0f2b0 100644 --- a/tools/patman/test_checkpatch.py +++ b/tools/patman/test_checkpatch.py @@ -405,6 +405,12 @@ index 0000000..2234c87 pm.add_line('include/myfile.h', '#include ') self.checkSingleMessage(pm, 'BARRED_INCLUDE_IN_HDR', 'error') + def testConfigIsEnabledConfig(self): + """Test for accidental CONFIG_IS_ENABLED(CONFIG_*) calls""" + pm = PatchMaker() + pm.add_line('common/main.c', 'if (CONFIG_IS_ENABLED(CONFIG_CLK))') + self.checkSingleMessage(pm, 'CONFIG_IS_ENABLED_CONFIG', 'error') + if __name__ == "__main__": unittest.main()