xref: /DragonOS/kernel/src/init/cmdline.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1f9fe30beSLoGin use core::{
2f9fe30beSLoGin     str,
3f9fe30beSLoGin     sync::atomic::{fence, Ordering},
4f9fe30beSLoGin };
5f9fe30beSLoGin 
6f9fe30beSLoGin use alloc::{ffi::CString, vec::Vec};
7f9fe30beSLoGin 
8f9fe30beSLoGin use crate::libs::spinlock::SpinLock;
9f9fe30beSLoGin 
10f9fe30beSLoGin use super::boot_params;
11f9fe30beSLoGin 
12f9fe30beSLoGin #[::linkme::distributed_slice]
13f9fe30beSLoGin pub static KCMDLINE_PARAM_EARLY_KV: [KernelCmdlineParameter] = [..];
14f9fe30beSLoGin 
15f9fe30beSLoGin #[::linkme::distributed_slice]
16f9fe30beSLoGin pub static KCMDLINE_PARAM_KV: [KernelCmdlineParameter] = [..];
17f9fe30beSLoGin 
18f9fe30beSLoGin #[::linkme::distributed_slice]
19f9fe30beSLoGin pub static KCMDLINE_PARAM_ARG: [KernelCmdlineParameter] = [..];
20f9fe30beSLoGin 
21f9fe30beSLoGin static KERNEL_CMDLINE_PARAM_MANAGER: KernelCmdlineManager = KernelCmdlineManager::new();
22f9fe30beSLoGin 
23f9fe30beSLoGin #[inline(always)]
kenrel_cmdline_param_manager() -> &'static KernelCmdlineManager24f9fe30beSLoGin pub fn kenrel_cmdline_param_manager() -> &'static KernelCmdlineManager {
25f9fe30beSLoGin     &KERNEL_CMDLINE_PARAM_MANAGER
26f9fe30beSLoGin }
27f9fe30beSLoGin 
28f9fe30beSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)]
29f9fe30beSLoGin pub enum KCmdlineParamType {
30f9fe30beSLoGin     /// bool类型参数
31f9fe30beSLoGin     Arg,
32f9fe30beSLoGin     /// key-value类型参数
33f9fe30beSLoGin     KV,
34f9fe30beSLoGin     /// 内存管理初始化之前的KV参数
35f9fe30beSLoGin     EarlyKV,
36f9fe30beSLoGin }
37f9fe30beSLoGin 
38f9fe30beSLoGin pub struct KernelCmdlineParamBuilder {
39f9fe30beSLoGin     name: &'static str,
40f9fe30beSLoGin     ty: KCmdlineParamType,
41f9fe30beSLoGin     default_str: &'static str,
42f9fe30beSLoGin     default_bool: bool,
43f9fe30beSLoGin     inv: bool,
44f9fe30beSLoGin }
45f9fe30beSLoGin 
46*7c28051eSlinfeng #[allow(dead_code)]
47f9fe30beSLoGin impl KernelCmdlineParamBuilder {
new(name: &'static str, ty: KCmdlineParamType) -> Self48f9fe30beSLoGin     pub const fn new(name: &'static str, ty: KCmdlineParamType) -> Self {
49f9fe30beSLoGin         Self {
50f9fe30beSLoGin             name,
51f9fe30beSLoGin             ty,
52f9fe30beSLoGin             default_str: "",
53f9fe30beSLoGin             default_bool: false,
54f9fe30beSLoGin             inv: false,
55f9fe30beSLoGin         }
56f9fe30beSLoGin     }
57f9fe30beSLoGin 
default_str(mut self, default_str: &'static str) -> Self58f9fe30beSLoGin     pub const fn default_str(mut self, default_str: &'static str) -> Self {
59f9fe30beSLoGin         self.default_str = default_str;
60f9fe30beSLoGin         self
61f9fe30beSLoGin     }
62f9fe30beSLoGin 
default_bool(mut self, default_bool: bool) -> Self63f9fe30beSLoGin     pub const fn default_bool(mut self, default_bool: bool) -> Self {
64f9fe30beSLoGin         self.default_bool = default_bool;
65f9fe30beSLoGin         self
66f9fe30beSLoGin     }
67f9fe30beSLoGin 
inv(mut self, inv: bool) -> Self68f9fe30beSLoGin     pub const fn inv(mut self, inv: bool) -> Self {
69f9fe30beSLoGin         self.inv = inv;
70f9fe30beSLoGin         self
71f9fe30beSLoGin     }
72f9fe30beSLoGin 
build_early_kv(self) -> Option<KernelCmdlineEarlyKV>73f9fe30beSLoGin     pub const fn build_early_kv(self) -> Option<KernelCmdlineEarlyKV> {
74f9fe30beSLoGin         if matches!(self.ty, KCmdlineParamType::EarlyKV) {
75f9fe30beSLoGin             Some(KernelCmdlineEarlyKV {
76f9fe30beSLoGin                 name: self.name,
77f9fe30beSLoGin                 value: [0; KernelCmdlineEarlyKV::VALUE_MAX_LEN],
78f9fe30beSLoGin                 index: 0,
79f9fe30beSLoGin                 initialized: false,
80f9fe30beSLoGin                 default: self.default_str,
81f9fe30beSLoGin             })
82f9fe30beSLoGin         } else {
83f9fe30beSLoGin             None
84f9fe30beSLoGin         }
85f9fe30beSLoGin     }
86f9fe30beSLoGin 
build(self) -> Option<KernelCmdlineParameter>87f9fe30beSLoGin     pub const fn build(self) -> Option<KernelCmdlineParameter> {
88f9fe30beSLoGin         match self.ty {
89f9fe30beSLoGin             KCmdlineParamType::Arg => Some(KernelCmdlineParameter::Arg(KernelCmdlineArg {
90f9fe30beSLoGin                 name: self.name,
91f9fe30beSLoGin                 value: self.default_bool,
92f9fe30beSLoGin                 initialized: false,
93f9fe30beSLoGin                 inv: self.inv,
94f9fe30beSLoGin                 default: self.default_bool,
95f9fe30beSLoGin             })),
96f9fe30beSLoGin             KCmdlineParamType::KV => Some(KernelCmdlineParameter::KV(KernelCmdlineKV {
97f9fe30beSLoGin                 name: self.name,
98f9fe30beSLoGin                 value: None,
99f9fe30beSLoGin                 initialized: false,
100f9fe30beSLoGin                 default: self.default_str,
101f9fe30beSLoGin             })),
102f9fe30beSLoGin             _ => None,
103f9fe30beSLoGin         }
104f9fe30beSLoGin     }
105f9fe30beSLoGin }
106f9fe30beSLoGin 
107f9fe30beSLoGin #[allow(dead_code)]
108f9fe30beSLoGin pub enum KernelCmdlineParameter {
109f9fe30beSLoGin     Arg(KernelCmdlineArg),
110f9fe30beSLoGin     KV(KernelCmdlineKV),
111f9fe30beSLoGin     EarlyKV(&'static KernelCmdlineEarlyKV),
112f9fe30beSLoGin }
113f9fe30beSLoGin 
114*7c28051eSlinfeng #[allow(dead_code)]
115f9fe30beSLoGin impl KernelCmdlineParameter {
name(&self) -> &str116f9fe30beSLoGin     pub fn name(&self) -> &str {
117f9fe30beSLoGin         match self {
118f9fe30beSLoGin             KernelCmdlineParameter::Arg(v) => v.name,
119f9fe30beSLoGin             KernelCmdlineParameter::KV(v) => v.name,
120f9fe30beSLoGin             KernelCmdlineParameter::EarlyKV(v) => v.name,
121f9fe30beSLoGin         }
122f9fe30beSLoGin     }
123f9fe30beSLoGin 
124f9fe30beSLoGin     /// 获取bool类型参数的值
value_bool(&self) -> Option<bool>125f9fe30beSLoGin     pub fn value_bool(&self) -> Option<bool> {
126f9fe30beSLoGin         match self {
127f9fe30beSLoGin             KernelCmdlineParameter::Arg(v) => Some(v.value()),
128f9fe30beSLoGin             _ => None,
129f9fe30beSLoGin         }
130f9fe30beSLoGin     }
131f9fe30beSLoGin 
132f9fe30beSLoGin     /// 获取key-value类型参数的值
value_str(&self) -> Option<&str>133f9fe30beSLoGin     pub fn value_str(&self) -> Option<&str> {
134f9fe30beSLoGin         match self {
135f9fe30beSLoGin             KernelCmdlineParameter::Arg(_) => None,
136f9fe30beSLoGin             KernelCmdlineParameter::KV(v) => v
137f9fe30beSLoGin                 .value
138f9fe30beSLoGin                 .as_ref()
139f9fe30beSLoGin                 .and_then(|v| str::from_utf8(v.as_bytes()).ok()),
140f9fe30beSLoGin             KernelCmdlineParameter::EarlyKV(v) => v.value_str(),
141f9fe30beSLoGin         }
142f9fe30beSLoGin     }
143f9fe30beSLoGin 
is_arg(&self) -> bool144f9fe30beSLoGin     pub fn is_arg(&self) -> bool {
145f9fe30beSLoGin         matches!(self, KernelCmdlineParameter::Arg(_))
146f9fe30beSLoGin     }
147f9fe30beSLoGin 
is_kv(&self) -> bool148f9fe30beSLoGin     pub fn is_kv(&self) -> bool {
149f9fe30beSLoGin         matches!(self, KernelCmdlineParameter::KV(_))
150f9fe30beSLoGin     }
151f9fe30beSLoGin 
is_early_kv(&self) -> bool152f9fe30beSLoGin     pub fn is_early_kv(&self) -> bool {
153f9fe30beSLoGin         matches!(self, KernelCmdlineParameter::EarlyKV(_))
154f9fe30beSLoGin     }
155f9fe30beSLoGin 
156f9fe30beSLoGin     /// 强行获取可变引用
157f9fe30beSLoGin     ///
158f9fe30beSLoGin     /// # Safety
159f9fe30beSLoGin     ///
160f9fe30beSLoGin     /// 只能在内核初始化阶段pid0使用!
161f9fe30beSLoGin     #[allow(clippy::mut_from_ref)]
force_mut(&self) -> &mut Self162f9fe30beSLoGin     unsafe fn force_mut(&self) -> &mut Self {
163f9fe30beSLoGin         let p = self as *const Self as *mut Self;
164f9fe30beSLoGin         p.as_mut().unwrap()
165f9fe30beSLoGin     }
166f9fe30beSLoGin }
167f9fe30beSLoGin 
168f9fe30beSLoGin #[derive(Debug)]
169f9fe30beSLoGin pub struct KernelCmdlineArg {
170f9fe30beSLoGin     name: &'static str,
171f9fe30beSLoGin     value: bool,
172f9fe30beSLoGin     initialized: bool,
173f9fe30beSLoGin     /// 是否反转
174f9fe30beSLoGin     inv: bool,
175f9fe30beSLoGin     default: bool,
176f9fe30beSLoGin }
177f9fe30beSLoGin 
178f9fe30beSLoGin impl KernelCmdlineArg {
value(&self) -> bool179f9fe30beSLoGin     pub fn value(&self) -> bool {
180f9fe30beSLoGin         volatile_read!(self.value)
181f9fe30beSLoGin     }
182f9fe30beSLoGin }
183f9fe30beSLoGin 
184f9fe30beSLoGin pub struct KernelCmdlineKV {
185f9fe30beSLoGin     name: &'static str,
186f9fe30beSLoGin     value: Option<CString>,
187f9fe30beSLoGin     initialized: bool,
188f9fe30beSLoGin     default: &'static str,
189f9fe30beSLoGin }
190f9fe30beSLoGin 
191f9fe30beSLoGin /// 在内存管理初始化之前的KV参数
192f9fe30beSLoGin pub struct KernelCmdlineEarlyKV {
193f9fe30beSLoGin     name: &'static str,
194f9fe30beSLoGin     value: [u8; Self::VALUE_MAX_LEN],
195f9fe30beSLoGin     index: usize,
196f9fe30beSLoGin     initialized: bool,
197f9fe30beSLoGin     default: &'static str,
198f9fe30beSLoGin }
199f9fe30beSLoGin 
200*7c28051eSlinfeng #[allow(dead_code)]
201f9fe30beSLoGin impl KernelCmdlineEarlyKV {
202f9fe30beSLoGin     pub const VALUE_MAX_LEN: usize = 256;
203f9fe30beSLoGin 
value(&self) -> &[u8]204f9fe30beSLoGin     pub fn value(&self) -> &[u8] {
205f9fe30beSLoGin         &self.value[..self.index]
206f9fe30beSLoGin     }
207f9fe30beSLoGin 
value_str(&self) -> Option<&str>208f9fe30beSLoGin     pub fn value_str(&self) -> Option<&str> {
209f9fe30beSLoGin         core::str::from_utf8(&self.value[..self.index]).ok()
210f9fe30beSLoGin     }
211f9fe30beSLoGin 
212f9fe30beSLoGin     /// 强行获取可变引用
213f9fe30beSLoGin     ///
214f9fe30beSLoGin     /// # Safety
215f9fe30beSLoGin     ///
216f9fe30beSLoGin     /// 只能在内核初始化阶段pid0使用!
217f9fe30beSLoGin     #[allow(clippy::mut_from_ref)]
force_mut(&self) -> &mut Self218f9fe30beSLoGin     unsafe fn force_mut(&self) -> &mut Self {
219f9fe30beSLoGin         let p = self as *const Self as *mut Self;
220f9fe30beSLoGin         p.as_mut().unwrap()
221f9fe30beSLoGin     }
222f9fe30beSLoGin }
223f9fe30beSLoGin 
224f9fe30beSLoGin pub struct KernelCmdlineManager {
225f9fe30beSLoGin     inner: SpinLock<InnerKernelCmdlineManager>,
226f9fe30beSLoGin }
227f9fe30beSLoGin 
228f9fe30beSLoGin pub(super) struct InnerKernelCmdlineManager {
229f9fe30beSLoGin     /// init进程的路径
230f9fe30beSLoGin     init_path: Option<CString>,
231f9fe30beSLoGin     init_args: Vec<CString>,
232f9fe30beSLoGin     init_envs: Vec<CString>,
233f9fe30beSLoGin }
234f9fe30beSLoGin 
235f9fe30beSLoGin impl KernelCmdlineManager {
new() -> Self236f9fe30beSLoGin     const fn new() -> Self {
237f9fe30beSLoGin         Self {
238f9fe30beSLoGin             inner: SpinLock::new(InnerKernelCmdlineManager {
239f9fe30beSLoGin                 init_path: None,
240f9fe30beSLoGin                 init_args: Vec::new(),
241f9fe30beSLoGin                 init_envs: Vec::new(),
242f9fe30beSLoGin             }),
243f9fe30beSLoGin         }
244f9fe30beSLoGin     }
245f9fe30beSLoGin 
init_proc_path(&self) -> Option<CString>246f9fe30beSLoGin     pub(super) fn init_proc_path(&self) -> Option<CString> {
247f9fe30beSLoGin         self.inner.lock().init_path.clone()
248f9fe30beSLoGin     }
249f9fe30beSLoGin 
init_proc_args(&self) -> Vec<CString>250f9fe30beSLoGin     pub(super) fn init_proc_args(&self) -> Vec<CString> {
251f9fe30beSLoGin         self.inner.lock().init_args.clone()
252f9fe30beSLoGin     }
253f9fe30beSLoGin 
init_proc_envs(&self) -> Vec<CString>254f9fe30beSLoGin     pub(super) fn init_proc_envs(&self) -> Vec<CString> {
255f9fe30beSLoGin         self.inner.lock().init_envs.clone()
256f9fe30beSLoGin     }
257f9fe30beSLoGin 
258f9fe30beSLoGin     /// 在内存管理初始化之前设置部分参数
early_init(&self)259f9fe30beSLoGin     pub fn early_init(&self) {
260f9fe30beSLoGin         let boot_params = boot_params().read();
261f9fe30beSLoGin 
262f9fe30beSLoGin         for argument in self.split_args(boot_params.boot_cmdline_str()) {
263f9fe30beSLoGin             let (node, option, value) = match self.split_arg(argument) {
264f9fe30beSLoGin                 Some(v) => v,
265f9fe30beSLoGin                 None => continue,
266f9fe30beSLoGin             };
267f9fe30beSLoGin             // 查找参数
268f9fe30beSLoGin             if let Some(param) = self.find_param(node, option, KCmdlineParamType::EarlyKV) {
269f9fe30beSLoGin                 let param = unsafe { param.force_mut() };
270f9fe30beSLoGin                 match param {
271f9fe30beSLoGin                     KernelCmdlineParameter::EarlyKV(p) => {
272f9fe30beSLoGin                         let p = unsafe { p.force_mut() };
273f9fe30beSLoGin                         if let Some(value) = value {
274f9fe30beSLoGin                             let value = value.as_bytes();
275f9fe30beSLoGin                             let len = value.len().min(KernelCmdlineEarlyKV::VALUE_MAX_LEN);
276f9fe30beSLoGin                             p.value[..len].copy_from_slice(&value[..len]);
277f9fe30beSLoGin                             p.index = len;
278f9fe30beSLoGin                         }
279f9fe30beSLoGin                         p.initialized = true;
280f9fe30beSLoGin                     }
281f9fe30beSLoGin                     _ => unreachable!(),
282f9fe30beSLoGin                 }
283f9fe30beSLoGin                 fence(Ordering::SeqCst);
284f9fe30beSLoGin             }
285f9fe30beSLoGin         }
286f9fe30beSLoGin 
287f9fe30beSLoGin         // 初始化默认值
288f9fe30beSLoGin         KCMDLINE_PARAM_EARLY_KV.iter().for_each(|x| {
289f9fe30beSLoGin             let x = unsafe { x.force_mut() };
290f9fe30beSLoGin             if let KernelCmdlineParameter::EarlyKV(v) = x {
291f9fe30beSLoGin                 if !v.initialized {
292f9fe30beSLoGin                     let v = unsafe { v.force_mut() };
293f9fe30beSLoGin                     let len = v.default.len().min(KernelCmdlineEarlyKV::VALUE_MAX_LEN);
294f9fe30beSLoGin                     v.value[..len].copy_from_slice(v.default.as_bytes());
295f9fe30beSLoGin                     v.index = len;
296f9fe30beSLoGin                     v.initialized = true;
297f9fe30beSLoGin                 }
298f9fe30beSLoGin             }
299f9fe30beSLoGin         });
300f9fe30beSLoGin     }
301f9fe30beSLoGin 
302f9fe30beSLoGin     /// 在内存管理初始化之后设置命令行参数
init(&self)303f9fe30beSLoGin     pub fn init(&self) {
304f9fe30beSLoGin         let mut inner = self.inner.lock();
305f9fe30beSLoGin         let boot_params = boot_params().read();
306f9fe30beSLoGin         // `--`以后的参数都是init进程的参数
307f9fe30beSLoGin         let mut kernel_cmdline_end = false;
308f9fe30beSLoGin         for argument in self.split_args(boot_params.boot_cmdline_str()) {
309f9fe30beSLoGin             if kernel_cmdline_end {
310f9fe30beSLoGin                 if inner.init_path.is_none() {
311f9fe30beSLoGin                     panic!("cmdline: init proc path is not set while init proc args are set");
312f9fe30beSLoGin                 }
313f9fe30beSLoGin                 if !argument.is_empty() {
314f9fe30beSLoGin                     inner.init_args.push(CString::new(argument).unwrap());
315f9fe30beSLoGin                 }
316f9fe30beSLoGin                 continue;
317f9fe30beSLoGin             }
318f9fe30beSLoGin 
319f9fe30beSLoGin             if argument == "--" {
320f9fe30beSLoGin                 kernel_cmdline_end = true;
321f9fe30beSLoGin                 continue;
322f9fe30beSLoGin             }
323f9fe30beSLoGin 
324f9fe30beSLoGin             let (node, option, value) = match self.split_arg(argument) {
325f9fe30beSLoGin                 Some(v) => v,
326f9fe30beSLoGin                 None => continue,
327f9fe30beSLoGin             };
328f9fe30beSLoGin             if option == "init" && value.is_some() {
329f9fe30beSLoGin                 if inner.init_path.is_some() {
330f9fe30beSLoGin                     panic!("cmdline: init proc path is set twice");
331f9fe30beSLoGin                 }
332f9fe30beSLoGin                 inner.init_path = Some(CString::new(value.unwrap()).unwrap());
333f9fe30beSLoGin                 continue;
334f9fe30beSLoGin             }
335f9fe30beSLoGin             // log::debug!(
336f9fe30beSLoGin             //     "cmdline: node: {:?}, option: {:?}, value: {:?}",
337f9fe30beSLoGin             //     node,
338f9fe30beSLoGin             //     option,
339f9fe30beSLoGin             //     value
340f9fe30beSLoGin             // );
341f9fe30beSLoGin             if let Some(param) = self.find_param(node, option, KCmdlineParamType::KV) {
342f9fe30beSLoGin                 let param = unsafe { param.force_mut() };
343f9fe30beSLoGin                 match param {
344f9fe30beSLoGin                     KernelCmdlineParameter::KV(p) => {
345f9fe30beSLoGin                         if p.value.is_some() {
346f9fe30beSLoGin                             log::warn!("cmdline: parameter {} is set twice", p.name);
347f9fe30beSLoGin                             continue;
348f9fe30beSLoGin                         }
349f9fe30beSLoGin                         p.value = Some(CString::new(value.unwrap()).unwrap());
350f9fe30beSLoGin                         p.initialized = true;
351f9fe30beSLoGin                     }
352f9fe30beSLoGin                     _ => unreachable!(),
353f9fe30beSLoGin                 }
354f9fe30beSLoGin                 fence(Ordering::SeqCst);
355f9fe30beSLoGin             } else if let Some(param) = self.find_param(node, option, KCmdlineParamType::Arg) {
356f9fe30beSLoGin                 let param = unsafe { param.force_mut() };
357f9fe30beSLoGin                 match param {
358f9fe30beSLoGin                     KernelCmdlineParameter::Arg(p) => {
359f9fe30beSLoGin                         if p.initialized {
360f9fe30beSLoGin                             log::warn!("cmdline: parameter {} is set twice", p.name);
361f9fe30beSLoGin                             continue;
362f9fe30beSLoGin                         }
363f9fe30beSLoGin                         p.value = !p.inv;
364f9fe30beSLoGin                         p.initialized = true;
365f9fe30beSLoGin                     }
366f9fe30beSLoGin                     _ => unreachable!(),
367f9fe30beSLoGin                 }
368f9fe30beSLoGin                 fence(Ordering::SeqCst);
369f9fe30beSLoGin             } else if node.is_none() {
370f9fe30beSLoGin                 if let Some(val) = value {
371f9fe30beSLoGin                     inner
372f9fe30beSLoGin                         .init_envs
373f9fe30beSLoGin                         .push(CString::new(format!("{}={}", option, val)).unwrap());
374f9fe30beSLoGin                 } else if !option.is_empty() {
375f9fe30beSLoGin                     inner.init_args.push(CString::new(option).unwrap());
376f9fe30beSLoGin                 }
377f9fe30beSLoGin             }
378f9fe30beSLoGin         }
379f9fe30beSLoGin         fence(Ordering::SeqCst);
380f9fe30beSLoGin         // 初始化默认值
381f9fe30beSLoGin         self.default_initialize();
382f9fe30beSLoGin         fence(Ordering::SeqCst);
383f9fe30beSLoGin     }
384f9fe30beSLoGin 
default_initialize(&self)385f9fe30beSLoGin     fn default_initialize(&self) {
386f9fe30beSLoGin         KCMDLINE_PARAM_ARG.iter().for_each(|x| {
387f9fe30beSLoGin             let x = unsafe { x.force_mut() };
388f9fe30beSLoGin             if let KernelCmdlineParameter::Arg(v) = x {
389f9fe30beSLoGin                 if !v.initialized {
390f9fe30beSLoGin                     v.value = v.default;
391f9fe30beSLoGin                     v.initialized = true;
392f9fe30beSLoGin                 }
393f9fe30beSLoGin             }
394f9fe30beSLoGin             fence(Ordering::SeqCst);
395f9fe30beSLoGin         });
396f9fe30beSLoGin 
397f9fe30beSLoGin         KCMDLINE_PARAM_KV.iter().for_each(|x| {
398f9fe30beSLoGin             let x = unsafe { x.force_mut() };
399f9fe30beSLoGin             if let KernelCmdlineParameter::KV(v) = x {
400f9fe30beSLoGin                 if !v.initialized {
401f9fe30beSLoGin                     v.value = Some(CString::new(v.default).unwrap());
402f9fe30beSLoGin                     v.initialized = true;
403f9fe30beSLoGin                 }
404f9fe30beSLoGin             }
405f9fe30beSLoGin             fence(Ordering::SeqCst);
406f9fe30beSLoGin         });
407f9fe30beSLoGin     }
408f9fe30beSLoGin 
find_param( &self, node: Option<&str>, option: &str, param_typ: KCmdlineParamType, ) -> Option<&KernelCmdlineParameter>409f9fe30beSLoGin     fn find_param(
410f9fe30beSLoGin         &self,
411f9fe30beSLoGin         node: Option<&str>,
412f9fe30beSLoGin         option: &str,
413f9fe30beSLoGin         param_typ: KCmdlineParamType,
414f9fe30beSLoGin     ) -> Option<&KernelCmdlineParameter> {
415f9fe30beSLoGin         let list = match param_typ {
416f9fe30beSLoGin             KCmdlineParamType::Arg => &KCMDLINE_PARAM_ARG,
417f9fe30beSLoGin             KCmdlineParamType::KV => &KCMDLINE_PARAM_KV,
418f9fe30beSLoGin             KCmdlineParamType::EarlyKV => &KCMDLINE_PARAM_EARLY_KV,
419f9fe30beSLoGin         };
420f9fe30beSLoGin 
421f9fe30beSLoGin         list.iter().find(|x| {
422f9fe30beSLoGin             let name = x.name();
423f9fe30beSLoGin             if let Some(node) = node {
424f9fe30beSLoGin                 // 加1是因为有一个点号
425f9fe30beSLoGin                 name.len() == (node.len() + option.len() + 1)
426f9fe30beSLoGin                     && name.starts_with(node)
427f9fe30beSLoGin                     && name[node.len() + 1..].starts_with(option)
428f9fe30beSLoGin             } else {
429f9fe30beSLoGin                 name == option
430f9fe30beSLoGin             }
431f9fe30beSLoGin         })
432f9fe30beSLoGin     }
433f9fe30beSLoGin 
split_arg<'a>(&self, arg: &'a str) -> Option<(Option<&'a str>, &'a str, Option<&'a str>)>434f9fe30beSLoGin     fn split_arg<'a>(&self, arg: &'a str) -> Option<(Option<&'a str>, &'a str, Option<&'a str>)> {
435f9fe30beSLoGin         let mut iter = arg.splitn(2, '=');
436f9fe30beSLoGin         let key = iter.next().unwrap();
437f9fe30beSLoGin         let value = iter.next();
438f9fe30beSLoGin         let value = value.map(|v| v.trim());
439f9fe30beSLoGin         if value.is_some() && iter.next().is_some() {
440f9fe30beSLoGin             log::warn!("cmdline: invalid argument: {}", arg);
441f9fe30beSLoGin             return None;
442f9fe30beSLoGin         }
443f9fe30beSLoGin 
444f9fe30beSLoGin         let mut iter = key.splitn(2, '.');
445f9fe30beSLoGin         let v1 = iter.next().map(|v| v.trim());
446f9fe30beSLoGin         let v2 = iter.next().map(|v| v.trim());
447f9fe30beSLoGin         let v3 = iter.next().map(|v| v.trim());
448f9fe30beSLoGin         let v = [v1, v2, v3];
449f9fe30beSLoGin 
450f9fe30beSLoGin         let mut key_split_len = 0;
451f9fe30beSLoGin         v.iter().for_each(|x| {
452f9fe30beSLoGin             if x.is_some() {
453f9fe30beSLoGin                 key_split_len += 1
454f9fe30beSLoGin             }
455f9fe30beSLoGin         });
456f9fe30beSLoGin 
457f9fe30beSLoGin         let (node, option) = match key_split_len {
458f9fe30beSLoGin             1 => (None, v[0].unwrap()),
459f9fe30beSLoGin             2 => (Some(v[0].unwrap()), v[1].unwrap()),
460f9fe30beSLoGin             _ => {
461f9fe30beSLoGin                 log::warn!("cmdline: invalid argument: {}", arg);
462f9fe30beSLoGin                 return None;
463f9fe30beSLoGin             }
464f9fe30beSLoGin         };
465f9fe30beSLoGin 
466f9fe30beSLoGin         Some((node, option, value))
467f9fe30beSLoGin     }
468f9fe30beSLoGin 
split_args<'a>(&self, cmdline: &'a str) -> impl Iterator<Item = &'a str>469f9fe30beSLoGin     fn split_args<'a>(&self, cmdline: &'a str) -> impl Iterator<Item = &'a str> {
470f9fe30beSLoGin         // 是否在引号内
471f9fe30beSLoGin         let mut in_quote = false;
472f9fe30beSLoGin         cmdline.split(move |c: char| {
473f9fe30beSLoGin             if c == '"' {
474f9fe30beSLoGin                 in_quote = !in_quote;
475f9fe30beSLoGin             }
476f9fe30beSLoGin             !in_quote && c.is_whitespace()
477f9fe30beSLoGin         })
478f9fe30beSLoGin     }
479f9fe30beSLoGin }
480