os/kernel/syscall/
sys.rs

1//! 系统相关系统调用实现
2
3use core::{
4    ffi::{c_char, c_int, c_long, c_uint, c_ulong, c_void},
5    sync::atomic::Ordering,
6};
7
8use crate::{
9    arch::{
10        lib::sbi::shutdown,
11        timer::{TICKS_PER_SEC, TIMER_TICKS, clock_freq},
12        trap::SumGuard,
13    },
14    kernel::{
15        current_task,
16        syscall::util::{check_syslog_permission, validate_syslog_args},
17        time::update_realtime,
18    },
19    log::{
20        DEFAULT_CONSOLE_LEVEL, LogLevel, format_log_entry, get_console_level, read_log,
21        set_console_level,
22    },
23    pr_alert,
24    security::{BiogasPoll, EntropyPool},
25    uapi::{
26        errno::{EINVAL, ENOSYS},
27        log::SyslogAction,
28        reboot::{
29            REBOOT_CMD_POWER_OFF, REBOOT_MAGIC1, REBOOT_MAGIC2, REBOOT_MAGIC2A, REBOOT_MAGIC2B,
30            REBOOT_MAGIC2C,
31        },
32        sysinfo::SysInfo,
33        time::clock_id::{
34            CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_REALTIME,
35            CLOCK_REALTIME_COARSE, MAX_CLOCKS,
36        },
37        types::SizeT,
38        uts_namespace::{UTS_NAME_LEN, UtsNamespace},
39    },
40    util::{
41        cstr_copy,
42        user_buffer::{UserBuffer, write_to_user},
43    },
44    vfs::TimeSpec,
45};
46
47/// 重启系统调用
48/// # 参数
49/// - `magic`: 第一个魔数,必须为 REBOOT_MAGIC1
50/// - `magic2`: 第二个魔数,必须为 REBOOT_MAGIC2 或 REBOOT_MAGIC2A/B/C
51/// - `op`: 重启操作码,指定重启类型
52/// - `arg`: 可选参数,取决于操作码
53/// # 返回值
54/// 成功返回 0,失败返回负错误码
55/// 对于重启或关机操作,函数不会返回
56pub fn reboot(magic: c_int, magic2: c_int, op: c_int, _arg: *mut c_void) -> c_int {
57    // TODO: 支持更多重启操作码
58    if magic as u32 != REBOOT_MAGIC1 {
59        return -EINVAL;
60    }
61    if magic2 as u32 != REBOOT_MAGIC2
62        && magic2 as u32 != REBOOT_MAGIC2A
63        && magic2 as u32 != REBOOT_MAGIC2B
64        && magic2 as u32 != REBOOT_MAGIC2C
65    {
66        return -EINVAL;
67    }
68    match op as u32 {
69        REBOOT_CMD_POWER_OFF => {
70            shutdown(true);
71        }
72        _ => {
73            pr_alert!("reboot: unsupported reboot operation code {}\n", op);
74        }
75    }
76    0
77}
78
79/// 获取系统信息系统调用
80/// # 参数
81/// - `buf`: 指向用户空间缓冲区的指针,用于存储系统信息
82/// # 返回值
83/// 成功返回 0,失败返回负错误码
84pub fn uname(buf: *mut UtsNamespace) -> c_int {
85    let uts = {
86        let task = current_task();
87        let t = task.lock();
88        t.uts_namespace.clone()
89    };
90    let uts_lock = uts.lock();
91    unsafe {
92        write_to_user(buf, uts_lock.clone());
93    }
94    0
95    // TODO: EPERM 和 EFAULT
96}
97
98/// 设置主机名系统调用
99/// # 参数
100/// - `name`: 指向包含新主机名的用户缓冲区的指针
101/// - `len`: 主机名长度
102/// # 返回值
103/// 成功返回 0,失败返回负错误码
104pub fn set_hostname(name: *const c_char, len: usize) -> c_int {
105    if len > UTS_NAME_LEN {
106        return -EINVAL;
107    }
108    let uts = {
109        let task = current_task();
110        let t = task.lock();
111        t.uts_namespace.clone()
112    };
113    let name_buf = UserBuffer::new(name as *mut _, len);
114    let name = unsafe { name_buf.copy_from_user() };
115    {
116        let mut uts_lock = uts.lock();
117        cstr_copy(name.as_ptr(), &mut uts_lock.nodename, len);
118    }
119    0
120    // TODO: EPERM 和 EFAULT
121}
122
123/// 获取系统信息系统调用
124/// # 参数
125/// * `info` - 指向用户空间 SysInfo 结构体的指针
126/// # 返回值
127/// * **成功**:返回 0,`info` 被填充系统信息
128/// * **失败**:返回负的 errno
129pub fn sysinfo(info: *mut SysInfo) -> c_int {
130    // TODO: 填充更多系统信息字段
131    let mut sys_info = SysInfo::new();
132    sys_info.uptime = (TIMER_TICKS.load(Ordering::SeqCst) / TICKS_PER_SEC) as c_ulong;
133    unsafe {
134        write_to_user(info, sys_info);
135    }
136    0
137}
138
139/// 获取指定时钟的时间系统调用
140/// # 参数
141/// * `clk_id` - 时钟 ID(如 CLOCK_REALTIME)
142/// * `tp` - 指向用户空间 TimeSpec 结构体的指针,用于存储时间
143/// # 返回值
144/// * **成功**:返回 0,`tp` 被填充当前时间
145/// * **失败**:返回负的 errno
146pub fn clock_gettime(clk_id: c_int, tp: *mut TimeSpec) -> c_int {
147    let ts = match clk_id {
148        CLOCK_REALTIME | CLOCK_REALTIME_COARSE => TimeSpec::now(),
149        CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE | CLOCK_MONOTONIC_RAW => TimeSpec::monotonic_now(),
150        id if id < MAX_CLOCKS as c_int && id >= 0 => {
151            return -ENOSYS;
152        }
153        _ => {
154            return -EINVAL;
155        }
156    };
157
158    unsafe {
159        write_to_user(tp, ts);
160    }
161
162    0
163}
164
165/// 设置指定时钟的时间系统调用
166/// # 参数
167/// * `clk_id` - 时钟 ID(如 CLOCK_REALTIME)
168/// * `tp` - 指向用户空间 TimeSpec 结构体的指针,包含要设置的时间
169/// # 返回值
170/// * **成功**:返回 0,时钟时间被更新
171/// * **失败**:返回负的 errno
172pub fn clock_settime(clk_id: c_int, tp: *const TimeSpec) -> c_int {
173    match clk_id {
174        CLOCK_REALTIME | CLOCK_REALTIME_COARSE => {
175            let ts: TimeSpec = unsafe { core::ptr::read(tp) };
176            update_realtime(&ts);
177            0
178        }
179        CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE | CLOCK_MONOTONIC_RAW => {
180            // 单调时钟不可设置
181            -EINVAL
182        }
183        id if id < MAX_CLOCKS as c_int && id >= 0 => -ENOSYS,
184        _ => -EINVAL,
185    }
186}
187
188/// 获取指定时钟的分辨率系统调用
189/// # 参数
190/// * `clk_id` - 时钟 ID(如 CLOCK_REALTIME)
191/// * `tp` - 指向用户空间 TimeSpec 结构体的指针,用于存储分辨率
192/// # 返回值
193/// * **成功**:返回 0,`tp` 被填充时钟分辨率
194/// * **失败**:返回负的 errno
195pub fn clock_getres(clk_id: c_int, tp: *mut TimeSpec) -> c_int {
196    let res = match clk_id {
197        CLOCK_REALTIME | CLOCK_REALTIME_COARSE => TimeSpec {
198            tv_sec: 0,
199            tv_nsec: 1_000_000_000 / (clock_freq() as c_long),
200        },
201        CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE | CLOCK_MONOTONIC_RAW => TimeSpec {
202            tv_sec: 0,
203            tv_nsec: 1_000_000_000 / (clock_freq() as c_long),
204        },
205        id if id < MAX_CLOCKS as c_int && id >= 0 => {
206            return -ENOSYS;
207        }
208        _ => {
209            return -EINVAL;
210        }
211    };
212
213    unsafe {
214        write_to_user(tp, res);
215    }
216
217    0
218}
219
220/// 读取和控制内核日志缓冲区
221/// # 参数
222/// * `type_` - 操作类型 (0-10),详见 `SyslogAction`
223/// * `bufp` - 用户空间缓冲区指针(某些操作需要)
224/// * `len` - 缓冲区长度或命令参数(取决于操作类型)
225///
226/// # 返回值
227/// * **成功**:
228///   - 类型 2/3/4: 读取的字节数
229///   - 类型 8: 旧的 console_loglevel (1-8)
230///   - 类型 9: 未读字节数
231///   - 类型 10: 缓冲区总大小
232///   - 其他: 0
233/// * **失败**:负的 errno
234///   - `-EINVAL`: 无效参数
235///   - `-EPERM`: 权限不足
236///   - `-EINTR`: 被信号中断
237///   - `-EFAULT`: 无效的用户空间指针
238pub fn syslog(type_: i32, bufp: *mut u8, len: i32) -> isize {
239    // 将原始 i32 转换为类型安全的 enum
240    let action = match SyslogAction::from_i32(type_) {
241        Ok(a) => a,
242        Err(e) => return -(e as isize),
243    };
244
245    if let Err(e) = validate_syslog_args(action, bufp, len) {
246        return -(e as isize);
247    }
248
249    if let Err(e) = check_syslog_permission(action) {
250        return -(e as isize);
251    }
252
253    match action {
254        // 破坏性读取操作
255        SyslogAction::Read => {
256            // Read: 破坏性读取(移除已读条目)
257            let buf_len = len as usize;
258            let mut total_written = 0;
259
260            // 开启用户空间访问
261            let _guard = SumGuard::new();
262
263            while total_written < buf_len {
264                // TODO: 暂时移除,等待信号系统实现
265                /*
266                // 检查信号中断
267                if has_pending_signal() {
268                    if total_written == 0 {
269                        // 未读取任何数据,返回 EINTR
270                        return -(EINTR as isize);
271                    } else {
272                        // 已读取部分数据,返回已读字节数
273                        break;
274                    }
275                }
276                */
277
278                // 读取下一条日志
279                let entry = match read_log() {
280                    Some(e) => e,
281                    None => break, // 没有更多日志
282                };
283
284                // 格式化日志条目
285                let formatted = format_log_entry(&entry);
286                let bytes = formatted.as_bytes();
287
288                // 检查剩余空间
289                if total_written + bytes.len() > buf_len {
290                    // 缓冲区不足,停止读取
291                    // 注意:此条目已从缓冲区移除但未返回给用户
292                    // 这是 Linux 的行为
293                    break;
294                }
295
296                // 复制到用户空间
297                unsafe {
298                    core::ptr::copy_nonoverlapping(
299                        bytes.as_ptr(),
300                        bufp.add(total_written),
301                        bytes.len(),
302                    );
303                }
304
305                total_written += bytes.len();
306            }
307
308            // 关闭用户空间访问
309
310            total_written as isize
311        }
312
313        // 非破坏性读取操作
314        SyslogAction::ReadAll => {
315            // ReadAll: 非破坏性读取(保留条目)
316            use crate::log::{log_reader_index, log_writer_index, peek_log};
317
318            let buf_len = len as usize;
319            let mut total_written = 0;
320
321            // 获取当前可读范围
322            let start_index = log_reader_index();
323            let end_index = log_writer_index();
324
325            // 开启用户空间访问
326            let _guard = SumGuard::new();
327
328            // 遍历所有可用的日志条目
329            let mut current_index = start_index;
330            while current_index < end_index && total_written < buf_len {
331                // TODO: 暂时移除,等待信号系统实现
332                /*
333                // 检查信号中断
334                if has_pending_signal() {
335                    if total_written == 0 {
336                        return -(EINTR as isize);
337                    } else {
338                        break;
339                    }
340                }
341                */
342
343                let entry = match peek_log(current_index) {
344                    Some(e) => e,
345                    None => break, // 条目已被覆盖或无效
346                };
347
348                let formatted = format_log_entry(&entry);
349                let bytes = formatted.as_bytes();
350
351                if total_written + bytes.len() > buf_len {
352                    // 缓冲区不足,停止读取
353                    break;
354                }
355
356                unsafe {
357                    core::ptr::copy_nonoverlapping(
358                        bytes.as_ptr(),
359                        bufp.add(total_written),
360                        bytes.len(),
361                    );
362                }
363
364                total_written += bytes.len();
365                current_index += 1;
366            }
367
368            // 关闭用户空间访问
369
370            total_written as isize
371        }
372
373        SyslogAction::ReadClear => {
374            // 先读取所有日志(使用与 ReadAll 相同的逻辑)
375            let buf_len = len as usize;
376            let mut total_written = 0;
377
378            let _guard = SumGuard::new();
379
380            while total_written < buf_len {
381                let entry = match read_log() {
382                    Some(e) => e,
383                    None => break,
384                };
385
386                let formatted = format_log_entry(&entry);
387                let bytes = formatted.as_bytes();
388
389                if total_written + bytes.len() > buf_len {
390                    break;
391                }
392
393                unsafe {
394                    core::ptr::copy_nonoverlapping(
395                        bytes.as_ptr(),
396                        bufp.add(total_written),
397                        bytes.len(),
398                    );
399                }
400
401                total_written += bytes.len();
402            }
403
404            // 清空剩余的日志
405            while read_log().is_some() {}
406
407            total_written as isize
408        }
409
410        // 缓冲区控制
411        SyslogAction::Clear => {
412            // 清空日志缓冲区
413            while read_log().is_some() {}
414            0
415        }
416
417        // 控制台输出控制
418        SyslogAction::ConsoleOff => {
419            // 禁用控制台输出
420            // 设置为 0,只显示 level <= 0 的消息(即只有 EMERG)
421            set_console_level(LogLevel::Emergency);
422            0
423        }
424
425        SyslogAction::ConsoleOn => {
426            // 启用控制台输出
427            // 恢复到默认级别(Warning = 4)
428            set_console_level(DEFAULT_CONSOLE_LEVEL);
429            0
430        }
431
432        SyslogAction::ConsoleLevel => {
433            // 设置控制台日志级别
434            //
435            // Linux 语义:
436            //   console_loglevel = N 表示显示 level < N 的消息
437            //   范围:1-8
438            //
439            // comix 的 log 模块语义:
440            //   console_level = N 表示显示 level <= N 的消息
441            //   范围:0-7
442            //
443            // 转换关系:
444            //   Linux len=1 -> 只显示 level < 1 (即 EMERG(0))
445            //              -> comix 的 console_level = 0 (Emergency)
446            //   Linux len=8 -> 显示 level < 8 (即 0-7 全部)
447            //              -> comix 的 console_level = 7 (Debug)
448            //
449            // 公式:console_level_u8 = len - 1
450
451            let new_level_u8 = (len - 1) as u8; // 1-8 -> 0-7
452            let new_level = LogLevel::from_u8(new_level_u8);
453
454            // 获取旧值
455            let old_level = get_console_level();
456            let old_level_u8 = old_level.to_u8();
457
458            // 设置新值
459            set_console_level(new_level);
460
461            // 返回旧值(转换回 1-8 范围)
462            (old_level_u8 + 1) as isize
463        }
464
465        // 查询操作
466        SyslogAction::SizeUnread => {
467            // 返回未读日志的精确字节数
468            use crate::log::log_unread_bytes;
469            log_unread_bytes() as isize
470        }
471
472        SyslogAction::SizeBuffer => {
473            // 返回日志缓冲区的总大小
474            use crate::log::GLOBAL_LOG_BUFFER_SIZE;
475            GLOBAL_LOG_BUFFER_SIZE as isize
476        }
477
478        // 空操作(这些操作在 Linux 中也是 NOP)
479        SyslogAction::Close | SyslogAction::Open => 0,
480    }
481}
482
483/// 获取随机字节系统调用
484/// # 参数
485/// * `buf`: 指向用户空间缓冲区的指针,用于存储随机字节
486/// * `len`: 最大需要填充的字节数
487/// * `_flags`: 标志位(当前未使用)
488/// # 返回值
489/// * **成功**:返回填充的字节数
490/// * **失败**:返回负的 errno
491pub fn getrandom(buf: *mut c_void, len: SizeT, _flags: c_uint) -> c_int {
492    let mut pool = BiogasPoll::new();
493    for i in 0..len {
494        let byte = match pool.try_fill(core::slice::from_mut(unsafe {
495            &mut *(buf as *mut u8).add(i as usize)
496        })) {
497            Ok(_) => unsafe { *(buf as *mut u8).add(i as usize) },
498            Err(_) => return -EINVAL,
499        };
500        unsafe {
501            *(buf as *mut u8).add(i as usize) = byte;
502        }
503    }
504    len as c_int
505}