On Tue, Feb 13, 2024 at 10:45:08AM +0200, Tony Lindgren wrote: > Driver subsystems may need to translate the preferred console name to the > character device name used. We already do some of this in console_setup() > with a few hardcoded names, but that does not scale well. > > The console options are parsed early in console_setup(), and the consoles > are added with __add_preferred_console(). At this point we don't know much > about the character device names and device drivers getting probed. > > To allow driver subsystems to set up a preferred console, let's save the > kernel command line console options. To add a preferred console from a > driver subsystem with optional character device name translation, let's > add a new function add_preferred_console_match(). > > This allows the serial core layer to support console=DEVNAME:0.0 style > hardware based addressing in addition to the current console=ttyS0 style > naming. And we can start moving console_setup() character device parsing > to the driver subsystem specific code. > > We use a separate array from the console_cmdline array as the character > device name and index may be unknown at the console_setup() time. And > eventually there's no need to call __add_preferred_console() until the > subsystem is ready to handle the console. > > Adding the console name in addition to the character device name, and a > flag for an added console, could be added to the struct console_cmdline. > And the console_cmdline array handling could be modified accordingly. But > that complicates things compared saving the console options, and then > adding the consoles when the subsystems handling the consoles are ready. ... > +int __init console_opt_save(const char *str, const char *brl_opt) > +{ > + struct console_option *con; > + const char *opt = NULL; > + size_t namelen, optlen; > + int i; > + namelen = strcspn(str, ","); > + if (!namelen) > + return -EINVAL; > + > + optlen = strlen(str) - namelen; > + if (optlen > 1) > + opt = str + namelen + 1; > + > + if (namelen >= CONSOLE_NAME_MAX || optlen >= CONSOLE_OPT_MAX) > + return -EINVAL; > + > + for (i = 0; i < MAX_CMDLINECONSOLES; i++) { > + con = &conopt[i]; > + > + if (con->name[0]) { > + if (!strncmp(str, con->name, namelen)) > + return 0; > + continue; > + } > + strscpy(con->name, str, namelen + 1); > + if (opt) > + strscpy(con->opt, opt, optlen + 1); > + /* See _braille_console_setup(), both empty and NULL are valid */ > + if (brl_opt) { > + strscpy(con->brl_opt, brl_opt, CONSOLE_BRL_OPT_MAX); > + con->has_brl_opt = 1; > + } > + > + return 0; > + } > + > + return -ENOMEM; > +} With fresh look at the above, can we amend it like below? (dropped NULL assignment, optimized strlen(), split checks, dropped unneeded +1 in strscpy() calls) int __init console_opt_save(const char *str, const char *brl_opt) { struct console_option *con; size_t namelen, optlen; const char *opt; int i; namelen = strcspn(str, ","); if (namelen == 0 || namelen >= CONSOLE_NAME_MAX) return -EINVAL; opt = str + namelen; if (*opt == ',') opt++; optlen = strlen(opt); if (optlen >= CONSOLE_OPT_MAX) return -EINVAL; for (i = 0; i < MAX_CMDLINECONSOLES; i++) { con = &conopt[i]; if (con->name[0]) { if (!strncmp(str, con->name, namelen)) return 0; continue; } strscpy(con->name, str, namelen); strscpy(con->opt, opt, optlen); // not sure if emptying opt is okay /* See _braille_console_setup(), both empty and NULL are valid */ if (brl_opt) { strscpy(con->brl_opt, brl_opt, CONSOLE_BRL_OPT_MAX); con->has_brl_opt = 1; } return 0; } return -ENOMEM; } -- With Best Regards, Andy Shevchenko