Message ID | 20231110013817.2378507-2-danielwa@cisco.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | generic command line v6 | expand |
Hi Daniel, kernel test robot noticed the following build errors: [auto build test ERROR on v6.6] [cannot apply to arm64/for-next/core efi/next tip/x86/core robh/for-next linus/master next-20231110] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Daniel-Walker/CMDLINE-add-generic-builtin-command-line/20231110-094423 base: v6.6 patch link: https://lore.kernel.org/r/20231110013817.2378507-2-danielwa%40cisco.com patch subject: [PATCH 1/8] CMDLINE: add generic builtin command line config: sparc-allyesconfig (https://download.01.org/0day-ci/archive/20231110/202311102331.GllFaI9t-lkp@intel.com/config) compiler: sparc64-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231110/202311102331.GllFaI9t-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202311102331.GllFaI9t-lkp@intel.com/ All error/warnings (new ones prefixed by >>): In file included from include/linux/kernel.h:15, from include/linux/interrupt.h:6, from arch/sparc/include/asm/setup.h:8, from lib/generic_cmdline.S:5: >> include/linux/align.h:8: warning: "ALIGN" redefined 8 | #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) | In file included from include/linux/export.h:6, from lib/generic_cmdline.S:2: include/linux/linkage.h:103: note: this is the location of the previous definition 103 | #define ALIGN __ALIGN | In file included from include/linux/kcsan-checks.h:13, from include/linux/instrumented.h:12, from include/linux/atomic/atomic-instrumented.h:17, from include/linux/atomic.h:82, from include/asm-generic/bitops/lock.h:5, from arch/sparc/include/asm/bitops_64.h:52, from arch/sparc/include/asm/bitops.h:5, from include/linux/bitops.h:68, from include/linux/kernel.h:22: >> include/linux/compiler_attributes.h:55: warning: "__always_inline" redefined 55 | #define __always_inline inline __attribute__((__always_inline__)) | In file included from include/linux/stddef.h:5, from include/linux/kernel.h:18: include/uapi/linux/stddef.h:8: note: this is the location of the previous definition 8 | #define __always_inline inline | >> include/linux/compiler_attributes.h:91:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 91 | #if __has_attribute(__copy__) | ^~~~~~~~~~~~~~~ >> include/linux/compiler_attributes.h:91:20: error: missing binary operator before token "(" 91 | #if __has_attribute(__copy__) | ^ include/linux/compiler_attributes.h:104:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 104 | #if __has_attribute(__counted_by__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:104:20: error: missing binary operator before token "(" 104 | #if __has_attribute(__counted_by__) | ^ >> include/linux/compiler_attributes.h:107: warning: "__counted_by" redefined 107 | # define __counted_by(member) | include/uapi/linux/stddef.h:55: note: this is the location of the previous definition 55 | #define __counted_by(m) | include/linux/compiler_attributes.h:116:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 116 | #if __has_attribute(__diagnose_as_builtin__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:116:20: error: missing binary operator before token "(" 116 | #if __has_attribute(__diagnose_as_builtin__) | ^ include/linux/compiler_attributes.h:139:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 139 | #if __has_attribute(__designated_init__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:139:20: error: missing binary operator before token "(" 139 | #if __has_attribute(__designated_init__) | ^ include/linux/compiler_attributes.h:150:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 150 | #if __has_attribute(__error__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:150:20: error: missing binary operator before token "(" 150 | #if __has_attribute(__error__) | ^ include/linux/compiler_attributes.h:161:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 161 | #if __has_attribute(__externally_visible__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:161:20: error: missing binary operator before token "(" 161 | #if __has_attribute(__externally_visible__) | ^ include/linux/compiler_attributes.h:198:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 198 | #if __has_attribute(__no_caller_saved_registers__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:198:20: error: missing binary operator before token "(" 198 | #if __has_attribute(__no_caller_saved_registers__) | ^ include/linux/compiler_attributes.h:209:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 209 | #if __has_attribute(__noclone__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:209:20: error: missing binary operator before token "(" 209 | #if __has_attribute(__noclone__) | ^ include/linux/compiler_attributes.h:226:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 226 | #if __has_attribute(__fallthrough__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:226:20: error: missing binary operator before token "(" 226 | #if __has_attribute(__fallthrough__) | ^ include/linux/compiler_attributes.h:252:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 252 | #if __has_attribute(__nonstring__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:252:20: error: missing binary operator before token "(" 252 | #if __has_attribute(__nonstring__) | ^ include/linux/compiler_attributes.h:264:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 264 | #if __has_attribute(__no_profile_instrument_function__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:264:20: error: missing binary operator before token "(" 264 | #if __has_attribute(__no_profile_instrument_function__) | ^ include/linux/compiler_attributes.h:283:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 283 | #if __has_attribute(__no_stack_protector__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:283:20: error: missing binary operator before token "(" 283 | #if __has_attribute(__no_stack_protector__) | ^ include/linux/compiler_attributes.h:294:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 294 | #if __has_attribute(__overloadable__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:294:20: error: missing binary operator before token "(" 294 | #if __has_attribute(__overloadable__) | ^ include/linux/compiler_attributes.h:313:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 313 | #if __has_attribute(__pass_dynamic_object_size__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:313:20: error: missing binary operator before token "(" 313 | #if __has_attribute(__pass_dynamic_object_size__) | ^ include/linux/compiler_attributes.h:318:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 318 | #if __has_attribute(__pass_object_size__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:318:20: error: missing binary operator before token "(" 318 | #if __has_attribute(__pass_object_size__) | ^ include/linux/compiler_attributes.h:363:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 363 | #if __has_attribute(__warning__) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:363:20: error: missing binary operator before token "(" 363 | #if __has_attribute(__warning__) | ^ include/linux/compiler_attributes.h:380:5: warning: "__has_attribute" is not defined, evaluates to 0 [-Wundef] 380 | #if __has_attribute(disable_sanitizer_instrumentation) | ^~~~~~~~~~~~~~~ include/linux/compiler_attributes.h:380:20: error: missing binary operator before token "(" 380 | #if __has_attribute(disable_sanitizer_instrumentation) | ^ vim +91 include/linux/compiler_attributes.h 86cffecdeaa278 Kees Cook 2021-11-05 45 a3f8a30f3f0079 Miguel Ojeda 2018-08-30 46 /* a3f8a30f3f0079 Miguel Ojeda 2018-08-30 47 * Note: users of __always_inline currently do not write "inline" themselves, a3f8a30f3f0079 Miguel Ojeda 2018-08-30 48 * which seems to be required by gcc to apply the attribute according a3f8a30f3f0079 Miguel Ojeda 2018-08-30 49 * to its docs (and also "warning: always_inline function might not be a3f8a30f3f0079 Miguel Ojeda 2018-08-30 50 * inlinable [-Wattributes]" is emitted). a3f8a30f3f0079 Miguel Ojeda 2018-08-30 51 * a3f8a30f3f0079 Miguel Ojeda 2018-08-30 52 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute a3f8a30f3f0079 Miguel Ojeda 2018-08-30 53 * clang: mentioned a3f8a30f3f0079 Miguel Ojeda 2018-08-30 54 */ a3f8a30f3f0079 Miguel Ojeda 2018-08-30 @55 #define __always_inline inline __attribute__((__always_inline__)) a3f8a30f3f0079 Miguel Ojeda 2018-08-30 56 a3f8a30f3f0079 Miguel Ojeda 2018-08-30 57 /* a3f8a30f3f0079 Miguel Ojeda 2018-08-30 58 * The second argument is optional (default 0), so we use a variadic macro a3f8a30f3f0079 Miguel Ojeda 2018-08-30 59 * to make the shorthand. a3f8a30f3f0079 Miguel Ojeda 2018-08-30 60 * a3f8a30f3f0079 Miguel Ojeda 2018-08-30 61 * Beware: Do not apply this to functions which may return a3f8a30f3f0079 Miguel Ojeda 2018-08-30 62 * ERR_PTRs. Also, it is probably unwise to apply it to functions a3f8a30f3f0079 Miguel Ojeda 2018-08-30 63 * returning extra information in the low bits (but in that case the a3f8a30f3f0079 Miguel Ojeda 2018-08-30 64 * compiler should see some alignment anyway, when the return value is a3f8a30f3f0079 Miguel Ojeda 2018-08-30 65 * massaged by 'flags = ptr & 3; ptr &= ~3;'). a3f8a30f3f0079 Miguel Ojeda 2018-08-30 66 * a3f8a30f3f0079 Miguel Ojeda 2018-08-30 67 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-assume_005faligned-function-attribute a3f8a30f3f0079 Miguel Ojeda 2018-08-30 68 * clang: https://clang.llvm.org/docs/AttributeReference.html#assume-aligned a3f8a30f3f0079 Miguel Ojeda 2018-08-30 69 */ a3f8a30f3f0079 Miguel Ojeda 2018-08-30 70 #define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) a3f8a30f3f0079 Miguel Ojeda 2018-08-30 71 54da6a0924311c Peter Zijlstra 2023-05-26 72 /* 54da6a0924311c Peter Zijlstra 2023-05-26 73 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute 54da6a0924311c Peter Zijlstra 2023-05-26 74 * clang: https://clang.llvm.org/docs/AttributeReference.html#cleanup 54da6a0924311c Peter Zijlstra 2023-05-26 75 */ 54da6a0924311c Peter Zijlstra 2023-05-26 76 #define __cleanup(func) __attribute__((__cleanup__(func))) 54da6a0924311c Peter Zijlstra 2023-05-26 77 a3f8a30f3f0079 Miguel Ojeda 2018-08-30 78 /* a3f8a30f3f0079 Miguel Ojeda 2018-08-30 79 * Note the long name. a3f8a30f3f0079 Miguel Ojeda 2018-08-30 80 * a3f8a30f3f0079 Miguel Ojeda 2018-08-30 81 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute a3f8a30f3f0079 Miguel Ojeda 2018-08-30 82 */ a3f8a30f3f0079 Miguel Ojeda 2018-08-30 83 #define __attribute_const__ __attribute__((__const__)) a3f8a30f3f0079 Miguel Ojeda 2018-08-30 84 c0d9782f5b6d71 Miguel Ojeda 2019-02-08 85 /* c0d9782f5b6d71 Miguel Ojeda 2019-02-08 86 * Optional: only supported since gcc >= 9 c0d9782f5b6d71 Miguel Ojeda 2019-02-08 87 * Optional: not supported by clang c0d9782f5b6d71 Miguel Ojeda 2019-02-08 88 * c0d9782f5b6d71 Miguel Ojeda 2019-02-08 89 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute c0d9782f5b6d71 Miguel Ojeda 2019-02-08 90 */ c0d9782f5b6d71 Miguel Ojeda 2019-02-08 @91 #if __has_attribute(__copy__) c0d9782f5b6d71 Miguel Ojeda 2019-02-08 92 # define __copy(symbol) __attribute__((__copy__(symbol))) c0d9782f5b6d71 Miguel Ojeda 2019-02-08 93 #else c0d9782f5b6d71 Miguel Ojeda 2019-02-08 94 # define __copy(symbol) c0d9782f5b6d71 Miguel Ojeda 2019-02-08 95 #endif c0d9782f5b6d71 Miguel Ojeda 2019-02-08 96 c8248faf3ca276 Kees Cook 2023-08-17 97 /* c8248faf3ca276 Kees Cook 2023-08-17 98 * Optional: only supported since gcc >= 14 c8248faf3ca276 Kees Cook 2023-08-17 99 * Optional: only supported since clang >= 18 c8248faf3ca276 Kees Cook 2023-08-17 100 * c8248faf3ca276 Kees Cook 2023-08-17 101 * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 c8248faf3ca276 Kees Cook 2023-08-17 102 * clang: https://reviews.llvm.org/D148381 c8248faf3ca276 Kees Cook 2023-08-17 103 */ c8248faf3ca276 Kees Cook 2023-08-17 104 #if __has_attribute(__counted_by__) c8248faf3ca276 Kees Cook 2023-08-17 105 # define __counted_by(member) __attribute__((__counted_by__(member))) c8248faf3ca276 Kees Cook 2023-08-17 106 #else c8248faf3ca276 Kees Cook 2023-08-17 @107 # define __counted_by(member) c8248faf3ca276 Kees Cook 2023-08-17 108 #endif c8248faf3ca276 Kees Cook 2023-08-17 109
Le 10/11/2023 à 02:38, Daniel Walker a écrit : > This code allows architectures to use a generic builtin command line. > The state of the builtin command line options across architecture is > diverse. MIPS and X86 once has similar systems, then mips added some > options to allow extending the command line. Powerpc did something > simiar in adding the ability to extend. Even with mips and powerpc > enhancement the needs of Cisco are not met on these platforms. What are those needs, can you list them in the cover letter, and probably also in here ? Are those needs specific to Cisco or can they interest the entire Linux community ? > > The code in this commit unifies the code into a generic > header file under the CONFIG_GENERIC_CMDLINE option. When this > option is enabled the architecture can call the cmdline_add_builtin() > to add the builtin command line. The generic code provides both > append and/or prepend options and provides a way to redefine these > option after the kernel is compiled. Explain how. > > This code also includes test's which are meant to confirm > functionality. Would be better to have test part as a separate patch if possible. > > This unified implementation offers the same functionality needed by > Cisco on all platform which we enable it on. Cisco ... cisco ... cisco ... > > Cc: xe-linux-external@cisco.com > Signed-off-by: Ruslan Bilovol <rbilovol@cisco.com> > Signed-off-by: Daniel Walker <danielwa@cisco.com> > --- > include/linux/cmdline.h | 106 ++++++++++++++++++++++++++++++ > init/Kconfig | 79 +++++++++++++++++++++++ > lib/Kconfig | 4 ++ > lib/Makefile | 3 + > lib/generic_cmdline.S | 53 +++++++++++++++ > lib/test_cmdline1.c | 139 ++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 384 insertions(+) > create mode 100644 include/linux/cmdline.h > create mode 100644 lib/generic_cmdline.S > create mode 100644 lib/test_cmdline1.c > > diff --git a/include/linux/cmdline.h b/include/linux/cmdline.h > new file mode 100644 > index 000000000000..a94758a0f257 > --- /dev/null > +++ b/include/linux/cmdline.h > @@ -0,0 +1,106 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef _LINUX_CMDLINE_H > +#define _LINUX_CMDLINE_H > +/* > + * > + * Copyright (C) 2006,2021. Cisco Systems, Inc. > + * > + * Generic Append/Prepend cmdline support. > + */ > + > + > +#include <linux/ctype.h> > +#include <linux/cache.h> > +#include <asm/setup.h> > + > +#ifdef CONFIG_CMDLINE_BOOL > +extern char cmdline_prepend[]; > +extern char cmdline_append[]; > +extern char cmdline_tmp[]; > +#define CMDLINE_PREPEND cmdline_prepend > +#define CMDLINE_APPEND cmdline_append > +#define CMDLINE_TMP cmdline_tmp > +#define CMDLINE_STATIC_PREPEND CONFIG_CMDLINE_PREPEND > +#define CMDLINE_STATIC_APPEND CONFIG_CMDLINE_APPEND Too many macros reduces the readability of code, avoid them when possible. > +#else Explain why this else leg is needed. It should be possible to set default values directly in Kconfig. > +#define CMDLINE_PREPEND "" > +#define CMDLINE_APPEND "" > +#define CMDLINE_TMP "" > +#define CMDLINE_STATIC_PREPEND "" > +#define CMDLINE_STATIC_APPEND "" > +#endif > + > +#ifndef CMDLINE_STRLCAT > +#define CMDLINE_STRLCAT strlcat > +#endif > + > +#ifndef CMDLINE_STRLEN > +#define CMDLINE_STRLEN strlen > +#endif > + > +/* > + * This function will append or prepend a builtin command line to the command > + * line provided by the bootloader. Kconfig options can be used to alter > + * the behavior of this builtin command line. > + * @dest: The destination of the final appended/prepended string > + * @tmp: temporary space used for prepending > + * @prepend: string to prepend to @dest > + * @append: string to append to @dest > + * @length: the maximum length of the strings above. > + * @cmdline_strlen: point to a compatible strlen Remove that function pointer argument and use macros. > + * @cmdline_strlcat: point to a compatible strlcat Same > + * This function returns true when the builtin command line was copied successfully > + * and false when there was not enough room to copy all parts of the command line. What happens when it returns false, is it partially copied or nothing is done ? > + */ > +static inline bool > +__cmdline_add_builtin( > + char *dest, > + char *tmp, > + char *prepend, > + char *append, > + unsigned long length, > + size_t (*cmdline_strlen)(const char *s), > + size_t (*cmdline_strlcat)(char *dest, const char *src, size_t count)) This cmdline feature is used in early deep parts of architectures, so in a way more or less comparable to linux-mm. Approach with linux-mm has always been to define macros that can be overriden by architectures. Please do the same and define cmdline_strlen() and cmdline_strlcat() as macros that can be overriden by architectures instead of passing function pointers. And keep macro names as lower case for this type of macros. > +{ > + size_t total_length = 0, tmp_length; Try to use shorter names for local variables, see kernel codying style. > + > + if (!IS_ENABLED(CONFIG_GENERIC_CMDLINE)) > + return true; > + > + if (!IS_ENABLED(CONFIG_CMDLINE_BOOL)) > + return true; > + > + if (IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) > + dest[0] = '\0'; > + else > + total_length += cmdline_strlen(dest); All those Kconfig options should be explained in the commit message, that would help understanding the patch. Impact on existing defconfigs should also be taken care of and minimised. > + > + tmp_length = cmdline_strlen(append); > + if (tmp_length > 0) { > + cmdline_strlcat(dest, append, length); > + total_length += tmp_length; > + } > + > + tmp_length = cmdline_strlen(prepend); > + if (tmp_length > 0) { > + cmdline_strlcat(tmp, prepend, length); > + cmdline_strlcat(tmp, dest, length); > + dest[0] = '\0'; > + cmdline_strlcat(dest, tmp, length); > + total_length += tmp_length; > + } > + > + tmp[0] = '\0'; What's the purpose of setting tmp[0] to 0 ? > + > + if (total_length > length) > + return false; > + > + return true; Can be writen as: return total_length <= length; > +} > + > +#define cmdline_add_builtin(dest) \ > + __cmdline_add_builtin(dest, CMDLINE_TMP, CMDLINE_PREPEND, CMDLINE_APPEND, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT) > + > +#define cmdline_get_static_builtin(dest) \ > + (CMDLINE_STATIC_PREPEND CMDLINE_STATIC_APPEND) > +#endif > diff --git a/init/Kconfig b/init/Kconfig > index 6d35728b94b2..703eed88d140 100644 > --- a/init/Kconfig > +++ b/init/Kconfig > @@ -1922,6 +1922,85 @@ config TRACEPOINTS > > source "kernel/Kconfig.kexec" > > +config GENERIC_CMDLINE > + bool > + > +if GENERIC_CMDLINE > + > +config CMDLINE_BOOL > + bool "Built-in kernel command line" > + help > + Allow for specifying boot arguments to the kernel at > + build time. On some systems (e.g. embedded ones), it is > + necessary or convenient to provide some or all of the > + kernel boot arguments with the kernel itself (that is, > + to not rely on the boot loader to provide them.) > + > + To compile command line arguments into the kernel, > + set this option to 'Y', then fill in the > + the boot arguments in CONFIG_CMDLINE. > + > + Systems with fully functional boot loaders (i.e. non-embedded) > + should leave this option set to 'N'. > + > +config CMDLINE_APPEND > + string "Built-in kernel command string append" > + depends on CMDLINE_BOOL > + default "" > + help > + Enter arguments here that should be compiled into the kernel > + image and used at boot time. If the boot loader provides a > + command line at boot time, this string is appended to it to > + form the full kernel command line, when the system boots. > + > + However, you can use the CONFIG_CMDLINE_OVERRIDE option to > + change this behavior. > + > + In most cases, the command line (whether built-in or provided > + by the boot loader) should specify the device for the root > + file system. > + > +config CMDLINE_PREPEND > + string "Built-in kernel command string prepend" > + depends on CMDLINE_BOOL > + default "" > + help > + Enter arguments here that should be compiled into the kernel > + image and used at boot time. If the boot loader provides a > + command line at boot time, this string is prepended to it to > + form the full kernel command line, when the system boots. > + > + However, you can use the CONFIG_CMDLINE_OVERRIDE option to > + change this behavior. > + > + In most cases, the command line (whether built-in or provided > + by the boot loader) should specify the device for the root > + file system. > + > +config CMDLINE_EXTRA > + bool "Reserve more space for inserting prepend and append without recompiling" > + depends on CMDLINE_BOOL > + select SYSTEM_EXTRA_CERTIFICATE > + help > + If set, space for an append and prepend will be reserved in the kernel > + image. This allows updating or changing the append and prepend to a large > + string then the kernel was compiled for without recompiling the kernel. s/large/larger s/then/than > + > + The maximum size is the command line size for each prepend and append. > + > +config CMDLINE_OVERRIDE > + bool "Built-in command line overrides boot loader arguments" > + depends on CMDLINE_BOOL > + help > + Set this option to 'Y' to have the kernel ignore the boot loader > + command line, and use ONLY the built-in command line. In this case > + append and prepend strings are concatenated to form the full > + command line. > + > + This is used to work around broken boot loaders. This should > + be set to 'N' under normal conditions. > +endif An analysis of what exists on each existing architecture should demonstrate that you have defined all needed options. > + > endmenu # General setup > > source "arch/Kconfig" > diff --git a/lib/Kconfig b/lib/Kconfig > index c686f4adc124..d520f1aa7c32 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -729,6 +729,10 @@ config PARMAN > config OBJAGG > tristate "objagg" if COMPILE_TEST > > +config TEST_CMDLINE > + depends on CMDLINE_BOOL && !CMDLINE_OVERRIDE > + tristate "Test generic command line handling" > + Put the test part in a second patch. > endmenu > > config GENERIC_IOREMAP > diff --git a/lib/Makefile b/lib/Makefile > index 740109b6e2c8..aa7b14a0ced7 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -438,3 +438,6 @@ $(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE > ifeq ($(CONFIG_FORTIFY_SOURCE),y) > $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) > endif > + > +obj-$(CONFIG_TEST_CMDLINE) += test_cmdline1.o > +obj-$(CONFIG_CMDLINE_BOOL) += generic_cmdline.o > diff --git a/lib/generic_cmdline.S b/lib/generic_cmdline.S > new file mode 100644 > index 000000000000..223763f9eeb6 > --- /dev/null > +++ b/lib/generic_cmdline.S > @@ -0,0 +1,53 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#include <linux/export.h> > +#include <linux/init.h> > + > +#include <asm/setup.h> > + > + __INITDATA > + > + .align 8 > + .global cmdline_prepend > +cmdline_prepend: > + .ifnc CONFIG_CMDLINE_PREPEND,"" > + .ascii CONFIG_CMDLINE_PREPEND > + .string " " > + .else > + .byte 0x0 > + .endif > +#ifdef CONFIG_CMDLINE_EXTRA > + .space COMMAND_LINE_SIZE - (.-cmdline_prepend) > + .size cmdline_prepend, COMMAND_LINE_SIZE > +#endif /* CONFIG_CMDLINE_EXTRA */ > + > +cmdline_prepend_end: > + .size cmdline_prepend, (cmdline_prepend_end - cmdline_prepend) > + > + .align 8 > + .global cmdline_tmp > +cmdline_tmp: > + .ifnc CONFIG_CMDLINE_PREPEND,"" > + .size cmdline_tmp, COMMAND_LINE_SIZE > + .space COMMAND_LINE_SIZE > + .else > + .byte 0x0 > + .endif > +cmdline_tmp_end: > + .size cmdline_tmp, (cmdline_tmp_end - cmdline_tmp) > + > + .align 8 > + .global cmdline_append > + .size cmdline_append, COMMAND_LINE_SIZE > +cmdline_append: > + .ifnc CONFIG_CMDLINE_APPEND,"" > + .ascii " " > + .string CONFIG_CMDLINE_APPEND > + .else > + .byte 0x0 > + .endif > +#ifdef CONFIG_CMDLINE_EXTRA > + .space COMMAND_LINE_SIZE - (.-cmdline_append) > +#endif /* CONFIG_CMDLINE_EXTRA */ > +cmdline_append_end: > + .size cmdline_append, (cmdline_append_end - cmdline_append) > + Can all this be done in a C file, possibly with inline assembly if required, instead of an assembly file ? > diff --git a/lib/test_cmdline1.c b/lib/test_cmdline1.c > new file mode 100644 > index 000000000000..bcaffcc024e4 > --- /dev/null > +++ b/lib/test_cmdline1.c > @@ -0,0 +1,139 @@ > +// SPDX-License-Identifier: GPL-2.0-only Why 2.0-only ? Not sure it is the preferred licence for new files unless they are tied to something already existing. > + > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > + > +#include <linux/bitmap.h> > +#include <linux/init.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/printk.h> > +#include <linux/slab.h> > +#include <linux/string.h> > +#include <linux/cmdline.h> > +#include <linux/uaccess.h> > + > +#include "../tools/testing/selftests/kselftest_module.h" Is it common practice to include tools/testing/ stuff into kernel ? > + > +KSTM_MODULE_GLOBALS(); > + > +char test1_prepend[] = "prepend "; > +char test1_append[] = " append"; > +char test1_bootloader_args[] = "console=ttyS0 log_level=3"; > +char test1_result[] = "prepend console=ttyS0 log_level=3 append"; > + > +char test2_append[] = " append"; > +char test2_bootloader_args[] = "console=ttyS0 log_level=3"; > +char test2_result[] = "console=ttyS0 log_level=3 append"; > + > +char test3_prepend[] = "prepend "; > +char test3_bootloader_args[] = "console=ttyS0 log_level=3"; > +char test3_result[] = "prepend console=ttyS0 log_level=3"; > + > +char test4_bootloader_args[] = "console=ttyS0 log_level=3"; > +char test4_result[] = "console=ttyS0 log_level=3"; > + > +char test5_prepend[] = "prepend "; > +char test5_append[] = " append"; > +static char test5_bootloader_args[] = > +"00000000000000 011111111111111 0222222222222222 033333333333333 " > +"10000000000000 111111111111111 1222222222222222 133333333333333 " > +"20000000000000 211111111111111 2222222222222222 233333333333333 " > +"30000000000000 311111111111111 3222222222222222 333333333333333 " > +"40000000000000 411111111111111 4222222222222222 433333333333333 " > +"50000000000000 511111111111111 5222222222222222 533333333333333 " > +"60000000000000 611111111111111 6222222222222222 633333333333333 " > +"70000000000000 711111111111111 7222222222222222 733333333333333"; > +static char test5_result[] = > +"prepend 00000000000000 011111111111111 0222222222222222 033333333333333 " > +"10000000000000 111111111111111 1222222222222222 133333333333333 " > +"20000000000000 211111111111111 2222222222222222 233333333333333 " > +"30000000000000 311111111111111 3222222222222222 333333333333333 " > +"40000000000000 411111111111111 4222222222222222 433333333333333 " > +"50000000000000 511111111111111 5222222222222222 533333333333333 " > +"60000000000000 611111111111111 6222222222222222 633333333333333 " > +"70000000000000 711111111111111 7222222222222222 7333333"; > + > +char test5_boot_command_line[COMMAND_LINE_SIZE]; > + > +char test_tmp[COMMAND_LINE_SIZE]; > + > +char test_boot_command_line[COMMAND_LINE_SIZE]; > + > +static void __init selftest(void) > +{ > + bool result; > + > + /* Normal operation */ > + strcpy(test_boot_command_line, test1_bootloader_args); > + test_tmp[0] = '\0'; > + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, test1_prepend, test1_append, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); > + > + if (result == true && !strncmp(test_boot_command_line, test1_result, COMMAND_LINE_SIZE)) { > + pr_info("test1 success.\n"); > + } else { > + pr_info("test1 failed. OUTPUT BELOW:\n"); > + pr_info("\"%s\"\n", test_boot_command_line); > + failed_tests++; > + } > + total_tests++; > + > + /* Missing prepend */ > + strcpy(test_boot_command_line, test2_bootloader_args); > + test_tmp[0] = '\0'; > + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, "", test2_append, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); > + > + if (result == true && !strncmp(test_boot_command_line, test2_result, COMMAND_LINE_SIZE)) { > + pr_info("test2 success.\n"); > + } else { > + pr_info("test2 failed. OUTPUT BELOW:\n"); > + pr_info("\"%s\"\n", test_boot_command_line); > + failed_tests++; > + } Can you refactor and avoid repeating those 7 lines five times ? > + total_tests++; > + > + /* Missing append */ > + strcpy(test_boot_command_line, test3_bootloader_args); > + test_tmp[0] = '\0'; > + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, test3_prepend, "", COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); > + > + if (result == true && !strncmp(test_boot_command_line, test3_result, COMMAND_LINE_SIZE)) { > + pr_info("test3 success.\n"); > + } else { > + pr_info("test3 failed. OUTPUT BELOW:\n"); > + pr_info("\"%s\"\n", test_boot_command_line); > + failed_tests++; > + } > + total_tests++; > + > + /* Missing append and prepend */ > + strcpy(test_boot_command_line, test4_bootloader_args); > + test_tmp[0] = '\0'; > + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, "", "", COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); > + > + if (result == true && !strncmp(test_boot_command_line, test4_result, COMMAND_LINE_SIZE)) { > + pr_info("test4 success.\n"); > + } else { > + pr_info("test4 failed. OUTPUT BELOW:\n"); > + pr_info("\"%s\"\n", test_boot_command_line); > + failed_tests++; > + } > + total_tests++; > + > + /* Already full boot arguments */ > + strcpy(test5_boot_command_line, test5_bootloader_args); > + test_tmp[0] = '\0'; > + result = __cmdline_add_builtin(test5_boot_command_line, test_tmp, test5_prepend, test5_append, 512, CMDLINE_STRLEN, CMDLINE_STRLCAT); > + > + if (result == false && !strncmp(test5_boot_command_line, test5_result, COMMAND_LINE_SIZE)) { > + pr_info("test5 success.\n"); > + } else { > + pr_info("test5 failed. OUTPUT BELOW:\n"); > + pr_info("\"%s\"\n", test5_boot_command_line); > + failed_tests++; > + } > + total_tests++; > +} > + > +KSTM_MODULE_LOADERS(cmdline_test); > +MODULE_AUTHOR("Daniel Walker <danielwa@cisco.com>"); > +MODULE_LICENSE("GPL");
On 11/10/2023 7:08 AM, Daniel Walker wrote: > diff --git a/lib/generic_cmdline.S b/lib/generic_cmdline.S > new file mode 100644 > index 000000000000..223763f9eeb6 > --- /dev/null > +++ b/lib/generic_cmdline.S > @@ -0,0 +1,53 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#include <linux/export.h> > +#include <linux/init.h> > + > +#include <asm/setup.h> > + > + __INITDATA > + > + .align 8 > + .global cmdline_prepend > +cmdline_prepend: > + .ifnc CONFIG_CMDLINE_PREPEND,"" > + .ascii CONFIG_CMDLINE_PREPEND > + .string " " > + .else > + .byte 0x0 > + .endif > +#ifdef CONFIG_CMDLINE_EXTRA > + .space COMMAND_LINE_SIZE - (.-cmdline_prepend) > + .size cmdline_prepend, COMMAND_LINE_SIZE > +#endif /* CONFIG_CMDLINE_EXTRA */ > + > +cmdline_prepend_end: > + .size cmdline_prepend, (cmdline_prepend_end - cmdline_prepend) > + > + .align 8 > + .global cmdline_tmp > +cmdline_tmp: > + .ifnc CONFIG_CMDLINE_PREPEND,"" > + .size cmdline_tmp, COMMAND_LINE_SIZE > + .space COMMAND_LINE_SIZE > + .else > + .byte 0x0 > + .endif > +cmdline_tmp_end: > + .size cmdline_tmp, (cmdline_tmp_end - cmdline_tmp) > + > + .align 8 > + .global cmdline_append > + .size cmdline_append, COMMAND_LINE_SIZE > +cmdline_append: > + .ifnc CONFIG_CMDLINE_APPEND,"" > + .ascii " " > + .string CONFIG_CMDLINE_APPEND > + .else > + .byte 0x0 > + .endif > +#ifdef CONFIG_CMDLINE_EXTRA > + .space COMMAND_LINE_SIZE - (.-cmdline_append) > +#endif /* CONFIG_CMDLINE_EXTRA */ > +cmdline_append_end: > + .size cmdline_append, (cmdline_append_end - cmdline_append) > + Hi Daniel, I picked these patches to test a usecase of ours. generic_cmdline.S does not escape semicolons in the CMDLINE_APPEND and CMDLINE_PREPEND strings. Take this config snippet for example: CONFIG_CMDLINE_APPEND="slub_debug=FZP,zs_handle,zspage;FZPU page_owner=on" CONFIG_CMDLINE_BOOL=y # CONFIG_CMDLINE_EXTRA is not set # CONFIG_CMDLINE_OVERRIDE is not set # CONFIG_CMDLINE_PREPEND is not set # CONFIG_TEST_CMDLINE is not set While compiling, the word FZPU is considered as a mnemonic because of the semicolon preceding it causing parsing to fail: kernel/lib/generic_cmdline.S: Assembler messages: kernel/lib/generic_cmdline.S:42: Warning: missing closing `"' kernel/lib/generic_cmdline.S:42: Error: unknown mnemonic `fzpu' -- `fzpu page_owner=on",""' Maybe Christophe's suggestion of moving this code to a C file and using inline assembly helps mitigate similar problems? Thanks, Jaskaran.
diff --git a/include/linux/cmdline.h b/include/linux/cmdline.h new file mode 100644 index 000000000000..a94758a0f257 --- /dev/null +++ b/include/linux/cmdline.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_CMDLINE_H +#define _LINUX_CMDLINE_H +/* + * + * Copyright (C) 2006,2021. Cisco Systems, Inc. + * + * Generic Append/Prepend cmdline support. + */ + + +#include <linux/ctype.h> +#include <linux/cache.h> +#include <asm/setup.h> + +#ifdef CONFIG_CMDLINE_BOOL +extern char cmdline_prepend[]; +extern char cmdline_append[]; +extern char cmdline_tmp[]; +#define CMDLINE_PREPEND cmdline_prepend +#define CMDLINE_APPEND cmdline_append +#define CMDLINE_TMP cmdline_tmp +#define CMDLINE_STATIC_PREPEND CONFIG_CMDLINE_PREPEND +#define CMDLINE_STATIC_APPEND CONFIG_CMDLINE_APPEND +#else +#define CMDLINE_PREPEND "" +#define CMDLINE_APPEND "" +#define CMDLINE_TMP "" +#define CMDLINE_STATIC_PREPEND "" +#define CMDLINE_STATIC_APPEND "" +#endif + +#ifndef CMDLINE_STRLCAT +#define CMDLINE_STRLCAT strlcat +#endif + +#ifndef CMDLINE_STRLEN +#define CMDLINE_STRLEN strlen +#endif + +/* + * This function will append or prepend a builtin command line to the command + * line provided by the bootloader. Kconfig options can be used to alter + * the behavior of this builtin command line. + * @dest: The destination of the final appended/prepended string + * @tmp: temporary space used for prepending + * @prepend: string to prepend to @dest + * @append: string to append to @dest + * @length: the maximum length of the strings above. + * @cmdline_strlen: point to a compatible strlen + * @cmdline_strlcat: point to a compatible strlcat + * This function returns true when the builtin command line was copied successfully + * and false when there was not enough room to copy all parts of the command line. + */ +static inline bool +__cmdline_add_builtin( + char *dest, + char *tmp, + char *prepend, + char *append, + unsigned long length, + size_t (*cmdline_strlen)(const char *s), + size_t (*cmdline_strlcat)(char *dest, const char *src, size_t count)) +{ + size_t total_length = 0, tmp_length; + + if (!IS_ENABLED(CONFIG_GENERIC_CMDLINE)) + return true; + + if (!IS_ENABLED(CONFIG_CMDLINE_BOOL)) + return true; + + if (IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) + dest[0] = '\0'; + else + total_length += cmdline_strlen(dest); + + tmp_length = cmdline_strlen(append); + if (tmp_length > 0) { + cmdline_strlcat(dest, append, length); + total_length += tmp_length; + } + + tmp_length = cmdline_strlen(prepend); + if (tmp_length > 0) { + cmdline_strlcat(tmp, prepend, length); + cmdline_strlcat(tmp, dest, length); + dest[0] = '\0'; + cmdline_strlcat(dest, tmp, length); + total_length += tmp_length; + } + + tmp[0] = '\0'; + + if (total_length > length) + return false; + + return true; +} + +#define cmdline_add_builtin(dest) \ + __cmdline_add_builtin(dest, CMDLINE_TMP, CMDLINE_PREPEND, CMDLINE_APPEND, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT) + +#define cmdline_get_static_builtin(dest) \ + (CMDLINE_STATIC_PREPEND CMDLINE_STATIC_APPEND) +#endif diff --git a/init/Kconfig b/init/Kconfig index 6d35728b94b2..703eed88d140 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1922,6 +1922,85 @@ config TRACEPOINTS source "kernel/Kconfig.kexec" +config GENERIC_CMDLINE + bool + +if GENERIC_CMDLINE + +config CMDLINE_BOOL + bool "Built-in kernel command line" + help + Allow for specifying boot arguments to the kernel at + build time. On some systems (e.g. embedded ones), it is + necessary or convenient to provide some or all of the + kernel boot arguments with the kernel itself (that is, + to not rely on the boot loader to provide them.) + + To compile command line arguments into the kernel, + set this option to 'Y', then fill in the + the boot arguments in CONFIG_CMDLINE. + + Systems with fully functional boot loaders (i.e. non-embedded) + should leave this option set to 'N'. + +config CMDLINE_APPEND + string "Built-in kernel command string append" + depends on CMDLINE_BOOL + default "" + help + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, this string is appended to it to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_PREPEND + string "Built-in kernel command string prepend" + depends on CMDLINE_BOOL + default "" + help + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, this string is prepended to it to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_EXTRA + bool "Reserve more space for inserting prepend and append without recompiling" + depends on CMDLINE_BOOL + select SYSTEM_EXTRA_CERTIFICATE + help + If set, space for an append and prepend will be reserved in the kernel + image. This allows updating or changing the append and prepend to a large + string then the kernel was compiled for without recompiling the kernel. + + The maximum size is the command line size for each prepend and append. + +config CMDLINE_OVERRIDE + bool "Built-in command line overrides boot loader arguments" + depends on CMDLINE_BOOL + help + Set this option to 'Y' to have the kernel ignore the boot loader + command line, and use ONLY the built-in command line. In this case + append and prepend strings are concatenated to form the full + command line. + + This is used to work around broken boot loaders. This should + be set to 'N' under normal conditions. +endif + endmenu # General setup source "arch/Kconfig" diff --git a/lib/Kconfig b/lib/Kconfig index c686f4adc124..d520f1aa7c32 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -729,6 +729,10 @@ config PARMAN config OBJAGG tristate "objagg" if COMPILE_TEST +config TEST_CMDLINE + depends on CMDLINE_BOOL && !CMDLINE_OVERRIDE + tristate "Test generic command line handling" + endmenu config GENERIC_IOREMAP diff --git a/lib/Makefile b/lib/Makefile index 740109b6e2c8..aa7b14a0ced7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -438,3 +438,6 @@ $(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE ifeq ($(CONFIG_FORTIFY_SOURCE),y) $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) endif + +obj-$(CONFIG_TEST_CMDLINE) += test_cmdline1.o +obj-$(CONFIG_CMDLINE_BOOL) += generic_cmdline.o diff --git a/lib/generic_cmdline.S b/lib/generic_cmdline.S new file mode 100644 index 000000000000..223763f9eeb6 --- /dev/null +++ b/lib/generic_cmdline.S @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> +#include <linux/init.h> + +#include <asm/setup.h> + + __INITDATA + + .align 8 + .global cmdline_prepend +cmdline_prepend: + .ifnc CONFIG_CMDLINE_PREPEND,"" + .ascii CONFIG_CMDLINE_PREPEND + .string " " + .else + .byte 0x0 + .endif +#ifdef CONFIG_CMDLINE_EXTRA + .space COMMAND_LINE_SIZE - (.-cmdline_prepend) + .size cmdline_prepend, COMMAND_LINE_SIZE +#endif /* CONFIG_CMDLINE_EXTRA */ + +cmdline_prepend_end: + .size cmdline_prepend, (cmdline_prepend_end - cmdline_prepend) + + .align 8 + .global cmdline_tmp +cmdline_tmp: + .ifnc CONFIG_CMDLINE_PREPEND,"" + .size cmdline_tmp, COMMAND_LINE_SIZE + .space COMMAND_LINE_SIZE + .else + .byte 0x0 + .endif +cmdline_tmp_end: + .size cmdline_tmp, (cmdline_tmp_end - cmdline_tmp) + + .align 8 + .global cmdline_append + .size cmdline_append, COMMAND_LINE_SIZE +cmdline_append: + .ifnc CONFIG_CMDLINE_APPEND,"" + .ascii " " + .string CONFIG_CMDLINE_APPEND + .else + .byte 0x0 + .endif +#ifdef CONFIG_CMDLINE_EXTRA + .space COMMAND_LINE_SIZE - (.-cmdline_append) +#endif /* CONFIG_CMDLINE_EXTRA */ +cmdline_append_end: + .size cmdline_append, (cmdline_append_end - cmdline_append) + diff --git a/lib/test_cmdline1.c b/lib/test_cmdline1.c new file mode 100644 index 000000000000..bcaffcc024e4 --- /dev/null +++ b/lib/test_cmdline1.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/bitmap.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/cmdline.h> +#include <linux/uaccess.h> + +#include "../tools/testing/selftests/kselftest_module.h" + +KSTM_MODULE_GLOBALS(); + +char test1_prepend[] = "prepend "; +char test1_append[] = " append"; +char test1_bootloader_args[] = "console=ttyS0 log_level=3"; +char test1_result[] = "prepend console=ttyS0 log_level=3 append"; + +char test2_append[] = " append"; +char test2_bootloader_args[] = "console=ttyS0 log_level=3"; +char test2_result[] = "console=ttyS0 log_level=3 append"; + +char test3_prepend[] = "prepend "; +char test3_bootloader_args[] = "console=ttyS0 log_level=3"; +char test3_result[] = "prepend console=ttyS0 log_level=3"; + +char test4_bootloader_args[] = "console=ttyS0 log_level=3"; +char test4_result[] = "console=ttyS0 log_level=3"; + +char test5_prepend[] = "prepend "; +char test5_append[] = " append"; +static char test5_bootloader_args[] = +"00000000000000 011111111111111 0222222222222222 033333333333333 " +"10000000000000 111111111111111 1222222222222222 133333333333333 " +"20000000000000 211111111111111 2222222222222222 233333333333333 " +"30000000000000 311111111111111 3222222222222222 333333333333333 " +"40000000000000 411111111111111 4222222222222222 433333333333333 " +"50000000000000 511111111111111 5222222222222222 533333333333333 " +"60000000000000 611111111111111 6222222222222222 633333333333333 " +"70000000000000 711111111111111 7222222222222222 733333333333333"; +static char test5_result[] = +"prepend 00000000000000 011111111111111 0222222222222222 033333333333333 " +"10000000000000 111111111111111 1222222222222222 133333333333333 " +"20000000000000 211111111111111 2222222222222222 233333333333333 " +"30000000000000 311111111111111 3222222222222222 333333333333333 " +"40000000000000 411111111111111 4222222222222222 433333333333333 " +"50000000000000 511111111111111 5222222222222222 533333333333333 " +"60000000000000 611111111111111 6222222222222222 633333333333333 " +"70000000000000 711111111111111 7222222222222222 7333333"; + +char test5_boot_command_line[COMMAND_LINE_SIZE]; + +char test_tmp[COMMAND_LINE_SIZE]; + +char test_boot_command_line[COMMAND_LINE_SIZE]; + +static void __init selftest(void) +{ + bool result; + + /* Normal operation */ + strcpy(test_boot_command_line, test1_bootloader_args); + test_tmp[0] = '\0'; + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, test1_prepend, test1_append, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); + + if (result == true && !strncmp(test_boot_command_line, test1_result, COMMAND_LINE_SIZE)) { + pr_info("test1 success.\n"); + } else { + pr_info("test1 failed. OUTPUT BELOW:\n"); + pr_info("\"%s\"\n", test_boot_command_line); + failed_tests++; + } + total_tests++; + + /* Missing prepend */ + strcpy(test_boot_command_line, test2_bootloader_args); + test_tmp[0] = '\0'; + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, "", test2_append, COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); + + if (result == true && !strncmp(test_boot_command_line, test2_result, COMMAND_LINE_SIZE)) { + pr_info("test2 success.\n"); + } else { + pr_info("test2 failed. OUTPUT BELOW:\n"); + pr_info("\"%s\"\n", test_boot_command_line); + failed_tests++; + } + total_tests++; + + /* Missing append */ + strcpy(test_boot_command_line, test3_bootloader_args); + test_tmp[0] = '\0'; + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, test3_prepend, "", COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); + + if (result == true && !strncmp(test_boot_command_line, test3_result, COMMAND_LINE_SIZE)) { + pr_info("test3 success.\n"); + } else { + pr_info("test3 failed. OUTPUT BELOW:\n"); + pr_info("\"%s\"\n", test_boot_command_line); + failed_tests++; + } + total_tests++; + + /* Missing append and prepend */ + strcpy(test_boot_command_line, test4_bootloader_args); + test_tmp[0] = '\0'; + result = __cmdline_add_builtin(test_boot_command_line, test_tmp, "", "", COMMAND_LINE_SIZE, CMDLINE_STRLEN, CMDLINE_STRLCAT); + + if (result == true && !strncmp(test_boot_command_line, test4_result, COMMAND_LINE_SIZE)) { + pr_info("test4 success.\n"); + } else { + pr_info("test4 failed. OUTPUT BELOW:\n"); + pr_info("\"%s\"\n", test_boot_command_line); + failed_tests++; + } + total_tests++; + + /* Already full boot arguments */ + strcpy(test5_boot_command_line, test5_bootloader_args); + test_tmp[0] = '\0'; + result = __cmdline_add_builtin(test5_boot_command_line, test_tmp, test5_prepend, test5_append, 512, CMDLINE_STRLEN, CMDLINE_STRLCAT); + + if (result == false && !strncmp(test5_boot_command_line, test5_result, COMMAND_LINE_SIZE)) { + pr_info("test5 success.\n"); + } else { + pr_info("test5 failed. OUTPUT BELOW:\n"); + pr_info("\"%s\"\n", test5_boot_command_line); + failed_tests++; + } + total_tests++; +} + +KSTM_MODULE_LOADERS(cmdline_test); +MODULE_AUTHOR("Daniel Walker <danielwa@cisco.com>"); +MODULE_LICENSE("GPL");