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:
AI
2026-02-23 12:30:36 +00:00
parent 0c5aa72fd3
commit a6e6e3d8ca
6 changed files with 141 additions and 63 deletions

View File

@@ -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 */