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