Skip to content

Commit 3c0a64e

Browse files
committed
feat: implement NtDisplayString
Signed-off-by: Theo Paris <theo@theoparis.com>
1 parent f84d38b commit 3c0a64e

File tree

3 files changed

+300
-51
lines changed

3 files changed

+300
-51
lines changed

kernel/kernel.rs

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub mod virtio_blk;
2727
pub mod zram;
2828

2929
use core::{arch::asm, panic::PanicInfo};
30+
use alloc::string::ToString;
31+
use alloc::vec::Vec;
3032
use limine::{
3133
request::{
3234
EntryPointRequest, HhdmRequest, MemoryMapRequest, RequestsEndMarker, RequestsStartMarker,
@@ -203,6 +205,31 @@ fn install_uefi_root_device(
203205
}
204206
}
205207

208+
fn prepare_init_task(task_id: usize) -> Option<process::Task> {
209+
let requested = cmdline::resolved_init_path();
210+
let mut candidates = Vec::new();
211+
if requested.eq_ignore_ascii_case("\\SystemRoot\\System32\\init.exe") {
212+
candidates.push("\\SystemRoot\\System32\\autochk.exe".to_string());
213+
}
214+
candidates.push(requested.clone());
215+
216+
for init_path in candidates {
217+
match user::create_init_task(task_id, &init_path) {
218+
Ok(task) => {
219+
println!("NT KERNEL: native init {} task prepared", init_path);
220+
return Some(task);
221+
}
222+
Err(init_err) => {
223+
println!(
224+
"NT KERNEL: native init {} prepare failed: {:#x}",
225+
init_path, init_err
226+
);
227+
}
228+
}
229+
}
230+
None
231+
}
232+
206233
#[unsafe(no_mangle)]
207234
pub extern "C" fn kernel_main() -> ! {
208235
unsafe {
@@ -267,19 +294,7 @@ pub extern "C" fn kernel_main() -> ! {
267294
match vfs::mount_uefi_root() {
268295
Ok(()) => {
269296
println!("NT KERNEL: mounted root via UEFI BlockIO");
270-
let init_path = cmdline::resolved_init_path();
271-
match user::create_init_task(3, &init_path) {
272-
Ok(task) => {
273-
println!("NT KERNEL: native init {} task prepared", init_path);
274-
init_task = Some(task);
275-
}
276-
Err(init_err) => {
277-
println!(
278-
"NT KERNEL: native init {} prepare failed: {:#x}",
279-
init_path, init_err
280-
);
281-
}
282-
}
297+
init_task = prepare_init_task(3);
283298
}
284299
Err(mount_err) => {
285300
println!("NT KERNEL: UEFI root mount failed: {:?}", mount_err);
@@ -296,19 +311,7 @@ pub extern "C" fn kernel_main() -> ! {
296311
match vfs::mount_root(dev) {
297312
Ok(()) => {
298313
println!("NT KERNEL: crabfs root mounted");
299-
let init_path = cmdline::resolved_init_path();
300-
match user::create_init_task(3, &init_path) {
301-
Ok(task) => {
302-
println!("NT KERNEL: native init {} task prepared", init_path);
303-
init_task = Some(task);
304-
}
305-
Err(err) => {
306-
println!(
307-
"NT KERNEL: native init {} prepare failed: {:#x}",
308-
init_path, err
309-
);
310-
}
311-
}
314+
init_task = prepare_init_task(3);
312315
}
313316
Err(_) => {
314317
println!("NT KERNEL: crabfs mount failed");
@@ -324,19 +327,7 @@ pub extern "C" fn kernel_main() -> ! {
324327
(_, _, Err(err)) => match vfs::mount_uefi_root() {
325328
Ok(()) => {
326329
println!("NT KERNEL: mounted root via UEFI BlockIO");
327-
let init_path = cmdline::resolved_init_path();
328-
match user::create_init_task(3, &init_path) {
329-
Ok(task) => {
330-
println!("NT KERNEL: native init {} task prepared", init_path);
331-
init_task = Some(task);
332-
}
333-
Err(init_err) => {
334-
println!(
335-
"NT KERNEL: native init {} prepare failed: {:#x}",
336-
init_path, init_err
337-
);
338-
}
339-
}
330+
init_task = prepare_init_task(3);
340331
}
341332
Err(mount_err) => {
342333
println!(

kernel/syscall.rs

Lines changed: 170 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
extern crate alloc;
22

3-
use crate::{gdt, nt, user};
3+
use crate::{gdt, nt, println, user};
4+
use core::sync::atomic::{AtomicUsize, Ordering};
45
use x86_64::instructions::segmentation::Segment;
56
use x86_64::registers::model_specific::{
67
Efer, EferFlags, GsBase, KernelGsBase, LStar, SFMask, Star,
@@ -32,6 +33,8 @@ static mut SYSCALL_CPU_LOCALS: [SyscallCpuLocal; MAX_CPUS] = [const {
3233

3334
static mut SYSCALL_STACKS: [SyscallStack; MAX_CPUS] =
3435
[const { SyscallStack([0; SYSCALL_STACK_SIZE]) }; MAX_CPUS];
36+
static UNKNOWN_SYSCALL_LOG_COUNT: AtomicUsize = AtomicUsize::new(0);
37+
static FAILED_SYSCALL_LOG_COUNT: AtomicUsize = AtomicUsize::new(0);
3538

3639
#[repr(C)]
3740
pub struct SyscallFrame {
@@ -168,23 +171,154 @@ extern "sysv64" fn syscall_dispatch(frame: *mut SyscallFrame) -> usize {
168171
}
169172
let frame = unsafe { &*frame };
170173
let result = match frame.nr {
174+
// Windows x64 native syscall compatibility for real ntdll stubs.
175+
4 => user::wait_for_single_object(frame.r10, frame.rdx != 0, frame.r8 as *const i64) as usize,
176+
6 => user::read_file(
177+
frame.r10,
178+
stack_arg(frame, 0) as *mut nt::IoStatusBlock,
179+
stack_arg(frame, 1) as *mut u8,
180+
stack_arg(frame, 2),
181+
) as usize,
182+
7 => user::device_io_control_file(
183+
frame.r10,
184+
frame.rdx,
185+
frame.r8 as *mut (),
186+
frame.r9 as *mut (),
187+
stack_arg(frame, 0) as *mut nt::IoStatusBlock,
188+
stack_arg(frame, 1) as u32,
189+
stack_arg(frame, 2) as *const u8,
190+
stack_arg(frame, 3) as u32,
191+
stack_arg(frame, 4) as *mut u8,
192+
stack_arg(frame, 5) as u32,
193+
) as usize,
194+
8 => user::write_file(
195+
frame.r10,
196+
stack_arg(frame, 0) as *mut nt::IoStatusBlock,
197+
stack_arg(frame, 1) as *const u8,
198+
stack_arg(frame, 2),
199+
) as usize,
200+
14 => user::set_event(frame.r10, frame.rdx as *mut i32) as usize,
201+
15 => user::close_handle(frame.r10) as usize,
202+
17 => user::query_information_file(
203+
frame.r10,
204+
frame.rdx as *mut nt::IoStatusBlock,
205+
frame.r8 as *mut u8,
206+
frame.r9 as u32,
207+
stack_arg(frame, 0) as u32,
208+
) as usize,
209+
24 if frame.rdx != 0 && frame.r9 != 0 => user::allocate_virtual_memory(
210+
frame.r10,
211+
frame.rdx as *mut usize,
212+
frame.r9 as *mut usize,
213+
stack_arg(frame, 1) as u32,
214+
) as usize,
215+
25 => user::query_information_process(
216+
frame.r10,
217+
frame.rdx as u32,
218+
frame.r8 as *mut u8,
219+
frame.r9 as u32,
220+
stack_arg(frame, 0) as *mut u32,
221+
) as usize,
222+
30 => user::free_virtual_memory(
223+
frame.r10,
224+
frame.rdx as *mut usize,
225+
frame.r8 as *mut usize,
226+
) as usize,
227+
35 => user::query_virtual_memory(
228+
frame.r10,
229+
frame.rdx,
230+
frame.r8 as u32,
231+
frame.r9 as *mut u8,
232+
stack_arg(frame, 0),
233+
stack_arg(frame, 1) as *mut usize,
234+
) as usize,
235+
39 => user::query_information_file(
236+
frame.r10,
237+
frame.rdx as *mut nt::IoStatusBlock,
238+
frame.r8 as *mut u8,
239+
frame.r9 as u32,
240+
stack_arg(frame, 0) as u32,
241+
) as usize,
242+
40 => user::map_view_of_section(
243+
frame.r10,
244+
frame.rdx,
245+
frame.r8 as *mut usize,
246+
stack_arg(frame, 3) as *mut usize,
247+
stack_arg(frame, 6) as u32,
248+
) as usize,
249+
42 => user::unmap_view_of_section(frame.r10, frame.rdx) as usize,
250+
// Windows native syscall number for NtTerminateProcess on recent x64 builds.
251+
44 => user::terminate_process(frame.r10, frame.rdx as i32) as usize,
252+
51 => user::create_file(
253+
frame.r10 as *mut usize,
254+
frame.rdx as u32,
255+
frame.r8 as *const nt::ObjectAttributes,
256+
frame.r9 as *mut nt::IoStatusBlock,
257+
) as usize,
258+
52 => user::delay_execution(frame.r10 != 0, frame.rdx as *const i64) as usize,
171259
// Windows native syscall number for NtQuerySystemInformation on recent x64 builds.
172260
54 => user::query_system_information(
173261
frame.r10 as u32,
174262
frame.rdx as *mut u8,
175263
frame.r8 as u32,
176264
frame.r9 as *mut u32,
177265
) as usize,
178-
// Windows native syscall number for NtAllocateVirtualMemory on recent x64 builds.
179-
// Args: (ProcessHandle, BaseAddress*, ZeroBits, RegionSize*, AllocationType, Protect)
180-
24 if frame.rdx != 0 && frame.r9 != 0 => user::allocate_virtual_memory(
266+
55 => user::open_section(
267+
frame.r10 as *mut usize,
268+
frame.rdx as u32,
269+
frame.r8 as *const nt::ObjectAttributes,
270+
) as usize,
271+
57 => user::device_io_control_file(
181272
frame.r10,
182-
frame.rdx as *mut usize,
183-
frame.r9 as *mut usize,
273+
frame.rdx,
274+
frame.r8 as *mut (),
275+
frame.r9 as *mut (),
276+
stack_arg(frame, 0) as *mut nt::IoStatusBlock,
184277
stack_arg(frame, 1) as u32,
278+
stack_arg(frame, 2) as *const u8,
279+
stack_arg(frame, 3) as u32,
280+
stack_arg(frame, 4) as *mut u8,
281+
stack_arg(frame, 5) as u32,
185282
) as usize,
186-
// Windows native syscall number for NtTerminateProcess on recent x64 builds.
187-
44 => user::terminate_process(frame.r10, frame.rdx as i32) as usize,
283+
62 => user::clear_event(frame.r10) as usize,
284+
70 => user::yield_execution() as usize,
285+
72 => user::create_event(
286+
frame.r10 as *mut usize,
287+
frame.r9 as u32,
288+
stack_arg(frame, 0) != 0,
289+
) as usize,
290+
73 => user::query_information_file(
291+
frame.r10,
292+
frame.rdx as *mut nt::IoStatusBlock,
293+
frame.r8 as *mut u8,
294+
frame.r9 as u32,
295+
stack_arg(frame, 0) as u32,
296+
) as usize,
297+
74 => user::create_section(
298+
frame.r10 as *mut usize,
299+
frame.rdx as u32,
300+
frame.r8 as *const nt::ObjectAttributes,
301+
frame.r9 as *const i64,
302+
stack_arg(frame, 0) as u32,
303+
stack_arg(frame, 1) as u32,
304+
stack_arg(frame, 2),
305+
) as usize,
306+
80 => user::protect_virtual_memory(
307+
frame.r10,
308+
frame.rdx as *mut usize,
309+
frame.r8 as *mut usize,
310+
frame.r9 as u32,
311+
stack_arg(frame, 0) as *mut u32,
312+
) as usize,
313+
83 => user::terminate_thread(frame.r10, frame.rdx as i32) as usize,
314+
85 => user::create_file(
315+
frame.r10 as *mut usize,
316+
frame.rdx as u32,
317+
frame.r8 as *const nt::ObjectAttributes,
318+
frame.r9 as *mut nt::IoStatusBlock,
319+
) as usize,
320+
91 => user::query_system_time(frame.r10 as *mut i64) as usize,
321+
228 => user::display_string(frame.r10 as *const nt::UnicodeString) as usize,
188322
nt::SYSCALL_NT_CLOSE => user::close_handle(frame.a0) as usize,
189323
nt::SYSCALL_NT_QUERY_INFORMATION_PROCESS => user::query_information_process(
190324
frame.a0,
@@ -323,7 +457,34 @@ extern "sysv64" fn syscall_dispatch(frame: *mut SyscallFrame) -> usize {
323457
stack_arg(frame, 3) as usize,
324458
stack_arg(frame, 4) as *const (),
325459
) as usize,
326-
_ => nt::STATUS_NOT_IMPLEMENTED as usize,
460+
_ => {
461+
let seen = UNKNOWN_SYSCALL_LOG_COUNT.fetch_add(1, Ordering::Relaxed);
462+
if seen < 128 {
463+
println!(
464+
"NT KERNEL: unknown syscall nr={} rcx={:#x} r10={:#x} rdx={:#x} r8={:#x} r9={:#x}",
465+
frame.nr,
466+
frame.rcx,
467+
frame.r10,
468+
frame.rdx,
469+
frame.r8,
470+
frame.r9
471+
);
472+
}
473+
nt::STATUS_NOT_IMPLEMENTED as usize
474+
}
327475
};
476+
if result != nt::STATUS_SUCCESS as usize
477+
&& result != nt::STATUS_TIMEOUT as usize
478+
&& result != nt::STATUS_END_OF_FILE as usize
479+
&& result != nt::STATUS_INVALID_DEVICE_REQUEST as usize
480+
{
481+
let seen = FAILED_SYSCALL_LOG_COUNT.fetch_add(1, Ordering::Relaxed);
482+
if seen < 256 {
483+
println!(
484+
"NT KERNEL: syscall failure nr={} status={:#x} rcx={:#x} r10={:#x}",
485+
frame.nr, result as u32, frame.rcx, frame.r10
486+
);
487+
}
488+
}
328489
result
329490
}

0 commit comments

Comments
 (0)