1#include "internal.h"
2
3#define CMDLINE_MAX_TREE_DEPTH 16
4
5void cmdline_functional_name(const struct cmdline_entry *ent,
6 char name_out[CMDLINE_ENTRY_NAME_LEN_MAX]) {
7 const struct cmdline_entry *chain[CMDLINE_MAX_TREE_DEPTH];
8 size_t depth = 0;
9
10 for (const struct cmdline_entry *curr = ent; curr != NULL;
11 curr = curr->parent) {
12 enforce(depth < CMDLINE_MAX_TREE_DEPTH, CAPACITY_EXCEEDED);
13 chain[depth++] = curr;
14 }
15
16 size_t idx = 0;
17 for (size_t i = depth; i > 0; i--) {
18 const struct cmdline_entry *node = chain[i - 1];
19 size_t len = strlen(str: node->name);
20 if (idx + len >= CMDLINE_ENTRY_NAME_LEN_MAX - 1)
21 len = (CMDLINE_ENTRY_NAME_LEN_MAX - 1 > idx)
22 ? (CMDLINE_ENTRY_NAME_LEN_MAX - 1 - idx)
23 : 0;
24
25 memcpy(name_out + idx, node->name, len);
26 idx += len;
27
28 if (i > 1 && idx < CMDLINE_ENTRY_NAME_LEN_MAX - 1)
29 name_out[idx++] = '.';
30 }
31 name_out[idx] = '\0';
32}
33
34void cmdline_check_for_duplicates(void) {
35 size_t count =
36 (size_t) (__ekernel_cmdline_entries - __skernel_cmdline_entries);
37 if (count == 0)
38 return;
39
40 char (*names)[CMDLINE_ENTRY_NAME_LEN_MAX] = nofail_vnews(names, count);
41
42 for (size_t i = 0; i < count; i++) {
43 cmdline_functional_name(ent: &__skernel_cmdline_entries[i], name_out: names[i]);
44 }
45
46 size_t dupes = 0;
47 for (size_t i = 0; i < count; i++) {
48 const char *name_a = names[i];
49
50 for (size_t j = i + 1; j < count; j++) {
51 const char *name_b = names[j];
52
53 if (strcmp(str1: name_a, str2: name_b) == 0) {
54 log_msg(LOG_ERROR, "duplicate command line entry: %s", name_a);
55 dupes++;
56 }
57 }
58 }
59
60 vfree(names);
61
62 if (dupes)
63 panic("%zu duplicate command line entries", dupes);
64}
65
66void cmdline_check_for_unfilled(void) {
67 size_t found = 0;
68 for (struct cmdline_entry *e = __skernel_cmdline_entries;
69 e < __ekernel_cmdline_entries; e++) {
70 if ((e->flags & CMDLINE_ENTRY_REQUIRED) &&
71 e->status == CMDLINE_ENTRY_NOT_FOUND) {
72 char name[CMDLINE_ENTRY_NAME_LEN_MAX];
73 cmdline_functional_name(ent: e, name_out: name);
74 log_msg(LOG_ERROR, "Required command line entry %s not present",
75 name);
76 found++;
77 }
78 }
79 if (found)
80 panic("%zu required command line entries not present", found);
81}
82
83void cmdline_apply_defaults(void) {
84 for (struct cmdline_entry *e = __skernel_cmdline_entries;
85 e < __ekernel_cmdline_entries; e++) {
86 if (e->status == CMDLINE_ENTRY_NOT_FOUND && e->default_val) {
87 char name[CMDLINE_ENTRY_NAME_LEN_MAX];
88 cmdline_functional_name(ent: e, name_out: name);
89
90 dispatch_parse_value(e, name, var: name, val: e->default_val);
91 e->status = CMDLINE_ENTRY_DEFAULTED;
92 log_msg(LOG_INFO, "command line entry '%s' defaulted to '%s'", name,
93 e->default_val);
94 }
95 }
96}
97
98void cmdline_print_all(void) {
99#ifdef DEBUG_CMDLINE
100 for (struct cmdline_entry *e = __skernel_cmdline_entries;
101 e < __ekernel_cmdline_entries; e++) {
102 if (e->flags & CMDLINE_ENTRY_SYMBOLIC)
103 continue;
104
105 char name[CMDLINE_ENTRY_NAME_LEN_MAX];
106 cmdline_functional_name(e, name);
107 log_msg(LOG_INFO, "command line entry %s", name);
108 }
109#endif
110}
111