feat: hello-world user-mode app loaded from initrd via VFS
- Created apps/hello-world/hello-world.S: AT&T assembly user program that calls SYS_WRITE to print 'Hello, World' then SYS_EXIT(0) - Created apps/user.ld: linker script for user apps at 0x08048000 - Created scripts/build_apps.sh: builds each app dir into flat binary - Updated CMakeLists.txt: added apps build target in ISO pipeline - Updated gen_initrd.sh: packs built binaries from build/apps_bin/ - Updated kernel.c: replaced inline machine code with VFS-based loading of hello-world from /initrd/hello-world via cpio_find() Verified: hello-world binary (49 bytes) loads from CPIO initrd, prints 'Hello, World', and exits with code 0.
This commit is contained in:
75
src/kernel.c
75
src/kernel.c
@@ -152,64 +152,31 @@ void kernel_main(uint32_t magic, uint32_t addr) {
|
||||
offset_print("FAILED to kmalloc\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a minimal test user-mode program.
|
||||
* This is flat binary machine code that calls SYS_WRITE then SYS_EXIT.
|
||||
*
|
||||
* The program writes "Hello from Ring 3!\n" to stdout (fd=1) via INT 0x80,
|
||||
* then exits with code 42.
|
||||
*
|
||||
* Assembly (i386):
|
||||
* ; SYS_WRITE(1, msg, 19)
|
||||
* mov eax, 1 ; SYS_WRITE
|
||||
* mov ebx, 1 ; fd = stdout
|
||||
* call next ; get EIP for position-independent addressing
|
||||
* next:
|
||||
* pop ecx ; ECX = address of 'next'
|
||||
* add ecx, 25 ; ECX = address of message string (offset to msg)
|
||||
* mov edx, 19 ; len = 19
|
||||
* int 0x80
|
||||
* ; SYS_EXIT(42)
|
||||
* mov eax, 0 ; SYS_EXIT
|
||||
* mov ebx, 42 ; code = 42
|
||||
* int 0x80
|
||||
* ; loop forever (shouldn't reach here)
|
||||
* jmp $
|
||||
* msg:
|
||||
* db "Hello from Ring 3!", 10
|
||||
*/
|
||||
static const uint8_t user_program[] = {
|
||||
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 (SYS_WRITE) */
|
||||
0xBB, 0x01, 0x00, 0x00, 0x00, /* mov ebx, 1 (stdout) */
|
||||
0xE8, 0x00, 0x00, 0x00, 0x00, /* call next (push EIP) */
|
||||
/* next: offset 15 */
|
||||
0x59, /* pop ecx */
|
||||
0x83, 0xC1, 0x19, /* add ecx, 25 (offset from 'next' to msg) */
|
||||
0xBA, 0x13, 0x00, 0x00, 0x00, /* mov edx, 19 (length) */
|
||||
0xCD, 0x80, /* int 0x80 */
|
||||
/* SYS_EXIT(42): offset 26 */
|
||||
0xB8, 0x00, 0x00, 0x00, 0x00, /* mov eax, 0 (SYS_EXIT) */
|
||||
0xBB, 0x2A, 0x00, 0x00, 0x00, /* mov ebx, 42 (exit code) */
|
||||
0xCD, 0x80, /* int 0x80 */
|
||||
0xEB, 0xFE, /* jmp $ (infinite loop safety) */
|
||||
/* msg: offset 40 */
|
||||
'H','e','l','l','o',' ','f','r','o','m',' ',
|
||||
'R','i','n','g',' ','3','!','\n'
|
||||
};
|
||||
/* Load hello-world from the initrd and run it as a user process */
|
||||
cpio_entry_t hello_entry;
|
||||
if (cpio_find("hello-world", &hello_entry) == 0) {
|
||||
offset_print("Found hello-world in initrd (");
|
||||
print_hex(hello_entry.datasize);
|
||||
offset_print(" bytes)\n");
|
||||
|
||||
int32_t pid = process_create("init", user_program, sizeof(user_program));
|
||||
if (pid > 0) {
|
||||
offset_print("Created init process, pid=");
|
||||
print_hex((uint32_t)pid);
|
||||
int32_t pid = process_create("hello-world",
|
||||
hello_entry.data,
|
||||
hello_entry.datasize);
|
||||
if (pid > 0) {
|
||||
offset_print("Created hello-world process, pid=");
|
||||
print_hex((uint32_t)pid);
|
||||
|
||||
/* Enable interrupts before entering user mode */
|
||||
asm volatile("sti");
|
||||
offset_print("Interrupts enabled\n");
|
||||
/* Enable interrupts before entering user mode */
|
||||
asm volatile("sti");
|
||||
offset_print("Interrupts enabled\n");
|
||||
|
||||
/* Enter user mode - does not return */
|
||||
process_run_first();
|
||||
/* Enter user mode - does not return */
|
||||
process_run_first();
|
||||
} else {
|
||||
offset_print("FAILED to create hello-world process\n");
|
||||
}
|
||||
} else {
|
||||
offset_print("FAILED to create init process\n");
|
||||
offset_print("hello-world not found in initrd\n");
|
||||
}
|
||||
|
||||
/* Enable interrupts */
|
||||
|
||||
Reference in New Issue
Block a user