From d868171eea861038c458318fb15fc986ba821c10 Mon Sep 17 00:00:00 2001 From: Ionut Nechita Date: Fri, 1 Aug 2025 19:07:57 +0300 Subject: [PATCH 1/2] feat: Implement system power management with Ctrl+Alt+Del and Ctrl+Alt+Esc Description: - Added power management system with power_off() and reboot() functions - Implemented Ctrl+Alt+Del for system shutdown - Added Ctrl+Alt+Esc for system reboot - Added syscalls for power management (60: poweroff, 61: reboot) - Updated login screen with shutdown hint - Added necessary key code definitions Signed-off-by: Ionut Nechita --- createfs | 6 +- kernel/kernel_processes/boot/login_screen.c | 102 +++++++++++ kernel/power.c | 183 ++++++++++++++++++++ kernel/power.h | 22 +++ kernel/process/syscall.c | 10 ++ kernel/process/syscall.h | 4 + run_virt | 1 + shared/input_keycodes.h | 4 + 8 files changed, 329 insertions(+), 3 deletions(-) create mode 100644 kernel/power.c create mode 100644 kernel/power.h diff --git a/createfs b/createfs index 5fb68023..5d76675c 100755 --- a/createfs +++ b/createfs @@ -9,7 +9,7 @@ if ! command -v "mcopy" >/dev/null 2>&1; then exit 1 fi -if ! command -v "mkfs.fat" >/dev/null 2>&1; then +if ! command -v "/usr/sbin/mkfs.fat" >/dev/null 2>&1; then echo "Error: this script depends on dosfstools. Please install it" >&2 exit 1 fi @@ -40,6 +40,6 @@ fi dd if=/dev/zero of=$IMAGE bs=1M count=$SIZE_MB -mkfs.fat -F 32 -n "$VOLUME_LABEL" $IMAGE +/usr/sbin/mkfs.fat -F 32 -n "$VOLUME_LABEL" $IMAGE -mcopy -i $IMAGE -s "$FOLDER"/* :: \ No newline at end of file +mcopy -i $IMAGE -s "$FOLDER"/* :: diff --git a/kernel/kernel_processes/boot/login_screen.c b/kernel/kernel_processes/boot/login_screen.c index 8561078d..fb2a91cd 100644 --- a/kernel/kernel_processes/boot/login_screen.c +++ b/kernel/kernel_processes/boot/login_screen.c @@ -9,6 +9,67 @@ #include "math/math.h" #include "std/string.h" #include "syscalls/syscalls.h" +#include "process/syscall.h" // For SYS_POWEROFF +#include "power.h" // For power_off() + +//TODO: properly handle keypad +static const char hid_keycode_to_char[256] = { + [0x04] = 'a', [0x05] = 'b', [0x06] = 'c', [0x07] = 'd', + [0x08] = 'e', [0x09] = 'f', [0x0A] = 'g', [0x0B] = 'h', + [0x0C] = 'i', [0x0D] = 'j', [0x0E] = 'k', [0x0F] = 'l', + [0x10] = 'm', [0x11] = 'n', [0x12] = 'o', [0x13] = 'p', + [0x14] = 'q', [0x15] = 'r', [0x16] = 's', [0x17] = 't', + [0x18] = 'u', [0x19] = 'v', [0x1A] = 'w', [0x1B] = 'x', + [0x1C] = 'y', [0x1D] = 'z', + [0x1E] = '1', [0x1F] = '2', [0x20] = '3', [0x21] = '4', + [0x22] = '5', [0x23] = '6', [0x24] = '7', [0x25] = '8', + [0x26] = '9', [0x27] = '0', + [0x28] = '\n', [0x2C] = ' ', [0x2D] = '-', [0x2E] = '=', + [0x2F] = '[', [0x30] = ']', [0x31] = '\\', [0x33] = ';', + [0x34] = '\'', [0x35] = '`', [0x36] = ',', [0x37] = '.', + [0x38] = '/', [0x58] = '\n', +}; + +bool keypress_contains(keypress *kp, char key, uint8_t modifier) { + if (kp->modifier != modifier) return false; //TODO: This is not entirely accurate, some modifiers do not change key + + for (int i = 0; i < 6; i++) + if (kp->keys[i] == key) + return true; + return false; +} + +// Check if the keypress contains the Ctrl+Alt+Del combination +bool is_ctrl_alt_del(keypress *kp) { + // Check for Ctrl+Alt modifiers (0x5 = 0x1 (CTRL) | 0x4 (ALT)) + if ((kp->modifier & (KEY_MOD_CTRL | KEY_MOD_ALT)) != (KEY_MOD_CTRL | KEY_MOD_ALT)) { + return false; + } + + // Check for Delete key in any of the key slots + for (int i = 0; i < 6; i++) { + if (kp->keys[i] == KEY_DELETE) { + return true; + } + } + return false; +} + +// Check if the keypress contains the Ctrl+Alt+Backspace combination +bool is_ctrl_alt_backspace(keypress *kp) { + // Check for Ctrl+Alt modifiers + if ((kp->modifier & (KEY_MOD_CTRL | KEY_MOD_ALT)) != (KEY_MOD_CTRL | KEY_MOD_ALT)) { + return false; + } + + // Check for Backspace key in any of the key slots + for (int i = 0; i < 6; i++) { + if (kp->keys[i] == KEY_BACKSPACE) { + return true; + } + } + return false; +} int login_screen(){ sys_focus_current(); @@ -16,10 +77,15 @@ int login_screen(){ char* buf = (char*)malloc(256); int len = 0; keypress old_kp; + bool ctrl_alt_del_pressed = false; + bool ctrl_alt_backspace_pressed = false; const char* name = BOOTSCREEN_TEXT; string title = string_l(name); string subtitle = string_l("Login"); gpu_clear(BG_COLOR); + // Shutdown hint position + int button_padding = 10; + while (1) { gpu_size screen_size = gpu_get_screen_size(); @@ -31,13 +97,49 @@ int login_screen(){ int yo = screen_middle.y; int height = char_size * 2; + // Draw title and subtitle gpu_draw_string(title, (gpu_point){screen_middle.x - ((title.length/2) * char_size), yo - char_size*9}, scale, 0xFFFFFFFF); gpu_draw_string(subtitle, (gpu_point){screen_middle.x - ((subtitle.length/2) * char_size), yo - char_size*6}, scale, 0xFFFFFFFF); + // Draw password input field gpu_fill_rect((gpu_rect){{xo,yo - char_size/2}, {screen_size.width / 3, height}},BG_COLOR+0x111111); gpu_draw_string(s, (gpu_point){xo, yo}, scale, 0xFFFFFFFF); + + // Draw shutdown hint + string shutdown_hint = string_l("Press Ctrl+Alt+Del to shutdown"); + gpu_draw_string(shutdown_hint, + (gpu_point){screen_size.width - (shutdown_hint.length * char_size) - button_padding, + screen_size.height - char_size - button_padding}, + 1, 0x888888); // Gray text + keypress kp; if (sys_read_input_current(&kp)){ + // Check for Ctrl+Alt+Del to shutdown + if (is_ctrl_alt_del(&kp)) { + if (!ctrl_alt_del_pressed) { + ctrl_alt_del_pressed = true; + kprintf("\nShutting down system...\n"); + power_off(); + // If power_off() returns (which it shouldn't), just continue + continue; + } + } else { + ctrl_alt_del_pressed = false; + } + + // Check for Ctrl+Alt+Backspace to reboot + if (is_ctrl_alt_backspace(&kp)) { + if (!ctrl_alt_backspace_pressed) { + ctrl_alt_backspace_pressed = true; + kprintf("\nRebooting system...\n"); + reboot(); + // If reboot() returns (which it shouldn't), just continue + continue; + } + } else { + ctrl_alt_backspace_pressed = false; + } + for (int i = 0; i < 6; i++){ char key = kp.keys[i]; if (hid_keycode_to_char[(uint8_t)key]){ diff --git a/kernel/power.c b/kernel/power.c new file mode 100644 index 00000000..c059532b --- /dev/null +++ b/kernel/power.c @@ -0,0 +1,183 @@ +#include "power.h" +#include "mailbox/mailbox.h" +#include "console/kio.h" +#include "graph/graphics.h" // For GPU functions +#include "types.h" // For uint32_t, bool, etc. + +// Forward declarations for graphics functions +void gpu_clear(uint32_t color); +void gpu_flush(void); +bool gpu_ready(void); + +// ARM-specific instructions +#define WFI() asm volatile("wfi") +#define HVC() asm volatile("hvc #0") + +// Semihosting operations +#define SYS_EXIT 0x18 +#define ADP_STOPPED_APPLICATIONEXIT 0x20026 +#define PSCI_SYSTEM_RESET 0x84000009 + +// Power management mailbox channels +#define MBOX_CH_PROP 8 + +// Power management tags +#define TAG_SET_POWER_STATE 0x00028001 +#define TAG_GET_POWER_STATE 0x00020001 + +// Power device IDs +#define POWER_DEVICE_SD_CARD 0x00000000 +#define POWER_DEVICE_UART0 0x00000001 +#define POWER_DEVICE_UART1 0x00000002 +#define POWER_DEVICE_USB_HCD 0x00000003 +#define POWER_DEVICE_I2C0 0x00000004 +#define POWER_DEVICE_I2C1 0x00000005 +#define POWER_DEVICE_I2C2 0x00000006 +#define POWER_DEVICE_SPI 0x00000007 +#define POWER_DEVICE_CCP2TX 0x00000008 + +// Power state +#define POWER_STATE_OFF 0x00000000 +#define POWER_STATE_ON 0x00000001 +#define POWER_STATE_WAIT 0x00000002 +#define POWER_STATE_NO_DEVICE 0x00000003 + +// Tag structure for power state +struct __attribute__((aligned(16))) power_state_tag { + uint32_t tag_id; // Tag identifier (TAG_SET_POWER_STATE or TAG_GET_POWER_STATE) + uint32_t buffer_size; // Size of request/response buffer (in bytes) + uint32_t request_code; // Request/response code + + // Device ID and state + uint32_t device_id; + uint32_t state; + + // End tag + uint32_t end_tag; +}; + +// Mailbox message buffer for power management +struct __attribute__((aligned(16))) mbox_message { + uint32_t size; // Buffer size in bytes + uint32_t request_code; // Request/response code (0 for request) + + // Tag for power state + struct power_state_tag power_state; + + // End tag + uint32_t end_tag; +}; + +// QEMU ARM poweroff via semihosting +// QEMU ARM poweroff via semihosting +static void qemu_poweroff() { + // Clear screen if GPU is available + if (gpu_ready()) { + gpu_clear(0x00000000); // Black color + gpu_flush(); + for (volatile int i = 0; i < 500000; i++); + } + + // Semihosting exit + register uint64_t x0 __asm__("x0") = 0x18; // SYS_EXIT + register uint64_t x1 __asm__("x1") = 0x20026; // ADP_Stopped_ApplicationExit + + __asm__ volatile( + "hlt #0xf000" + : + : "r" (x0), "r" (x1) + : "memory" + ); +} + +void power_off() { + // Clear screen if GPU is available + if (gpu_ready()) { + gpu_clear(0x00000000); // Black color + gpu_flush(); + for (volatile int i = 0; i < 500000; i++); + } + + kprint("Shutting down the system...\n"); + + // Try QEMU poweroff first (will only return if semihosting is not available) + qemu_poweroff(); + + // If we're still here, try standard poweroff methods + + // Mailbox poweroff (Raspberry Pi) + volatile unsigned int* MAILBOX = (volatile unsigned int*)0x3F00B880; + + // Wait until mailbox is not full + while (MAILBOX[6] & 0x80000000); + + // Send poweroff request + MAILBOX[8] = 0x48000 | 0x10; // Channel 8 (power management) with request + + // Wait for response + while (1) { + // Wait until there's mail + while (MAILBOX[6] & 0x40000000); + + // Check if this is the response to our request + if ((MAILBOX[0] & 0xF) == 0x8) { + break; + } + } + + // If we're still here, try direct hardware power-off + volatile unsigned int* PM_PWR = (volatile unsigned int*)0x3F10001C; + unsigned int PM_PASSWORD = 0x5A000000; + *PM_PWR = PM_PASSWORD | 0x20000; // Power off + + // Final fallback - just hang + while(1) { + WFI(); // Wait for interrupt (low power) + } +} + +// System reset using PSCI (Power State Coordination Interface) +static void system_reset() { + // PSCI SYSTEM_RESET function ID for ARM + register uint64_t x0 __asm__("x0") = PSCI_SYSTEM_RESET; + + // Make the HVC (Hypervisor Call) to PSCI + (void)x0; // Mark as used to suppress warning + HVC(); + + // If we get here, PSCI call failed + kprint("PSCI reset failed, trying other methods...\n"); +} + +void reboot() { + kprint("Rebooting the system...\n"); + + // Clear screen if GPU is available + if (gpu_ready()) { + gpu_clear(0x00000000); // Black color + gpu_flush(); + for (volatile int i = 0; i < 500000; i++); + } + + // Try PSCI reset first + system_reset(); + + // If we're still here, try QEMU semihosting exit + register uint64_t x0 __asm__("x0") = 0x18; // SYS_EXIT + register uint64_t x1 __asm__("x1") = 0x20026; // ADP_Stopped_ApplicationExit + __asm__ volatile("hlt #0xf000" : : "r"(x0), "r"(x1) : "memory"); + + // If we're still here, try direct hardware reset + volatile unsigned int* PM_RSTC = (volatile unsigned int*)0x3F10001C; + volatile unsigned int* PM_WDOG = (volatile unsigned int*)0x3F100024; + unsigned int PM_PASSWORD = 0x5A000000; + + // Set the watchdog to reset immediately + *PM_RSTC = PM_PASSWORD | 0x20; // Full reset + *PM_WDOG = PM_PASSWORD | 0x8000; // Minimum count + + // Wait for the system to reset + while(1) { + asm volatile("wfi"); // Wait for interrupt (low power) + } +} diff --git a/kernel/power.h b/kernel/power.h new file mode 100644 index 00000000..ae173670 --- /dev/null +++ b/kernel/power.h @@ -0,0 +1,22 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#include "types.h" + +/** + * @brief Powers off the system + * + * This function attempts to power off the system using the mailbox interface. + * If that fails, it falls back to a hardware-specific method. + */ +void power_off(); + +/** + * @brief Reboots the system + * + * This function attempts to reboot the system using the mailbox interface. + * If that fails, it falls back to a hardware-specific method. + */ +void reboot(); + +#endif // _POWER_H_ diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 3e8d6eac..b575777f 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -15,6 +15,7 @@ #include "networking/network.h" #include "networking/port_manager.h" #include "filesystem/filesystem.h" +#include "power.h" int syscall_depth = 0; @@ -164,6 +165,15 @@ void sync_el0_handler_c(){ result = net_rx_frame(user_out); break; } + + case 60: // Poweroff system + power_off(); + break; + + case 61: // Reboot system + reboot(); + break; + default: handle_exception_with_info("Unknown syscall", iss); diff --git a/kernel/process/syscall.h b/kernel/process/syscall.h index 96572f86..4361fb69 100644 --- a/kernel/process/syscall.h +++ b/kernel/process/syscall.h @@ -2,3 +2,7 @@ #include "types.h" +// System call numbers +#define SYS_POWEROFF 60 +#define SYS_REBOOT 61 + diff --git a/run_virt b/run_virt index 3df29834..8b92b854 100755 --- a/run_virt +++ b/run_virt @@ -60,4 +60,5 @@ $PRIVILEGE qemu-system-aarch64 \ -device virtio-sound-pci,audiodev=sdl_audio \ -audiodev sdl,id=sdl_audio \ -d guest_errors \ + -semihosting \ $ARGS diff --git a/shared/input_keycodes.h b/shared/input_keycodes.h index be4a992c..f7855e3f 100644 --- a/shared/input_keycodes.h +++ b/shared/input_keycodes.h @@ -23,6 +23,10 @@ #define KEY_MOD_RALT 0x40 #define KEY_MOD_RMETA 0x80 +// Combined modifier masks for convenience +#define KEY_MOD_CTRL (KEY_MOD_LCTRL | KEY_MOD_RCTRL) +#define KEY_MOD_ALT (KEY_MOD_LALT | KEY_MOD_RALT) + /** * Scan codes - last N slots in the HID report (usually 6). * 0x00 if no key pressed. From 86028b14140c1ddfea4333928202e1ea001e912f Mon Sep 17 00:00:00 2001 From: Ionut Nechita Date: Mon, 11 Aug 2025 23:06:32 +0300 Subject: [PATCH 2/2] fs: minor fix Signed-off-by: Ionut Nechita --- kernel/filesystem/fat32.cpp | 13 +++-- kernel/filesystem/filesystem.cpp | 56 +++++++++++++++++-- kernel/kernel_processes/boot/login_screen.c | 62 ++++++++------------- kernel/kernel_processes/windows/desktop.cpp | 18 +++--- kernel/process/loading/elf_file.c | 15 ++--- kernel/process/loading/process_loader.c | 54 ++++++++++-------- 6 files changed, 130 insertions(+), 88 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index c5d14697..8a2a1c32 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -262,16 +262,21 @@ FS_RESULT FAT32FS::open_file(const char* path, file* descriptor){ if (!buf) return FS_RESULT_NOTFOUND; descriptor->id = reserve_fd_id(); descriptor->size = buf_ptr.size; - open_files.add(reserve_fd_id(), buf); + open_files.add(descriptor->id, buf); //TODO: go back to using a linked list, and a static id for the file, ideally global for system return FS_RESULT_SUCCESS; } size_t FAT32FS::read_file(file *descriptor, void* buf, size_t size){ void* file = open_files[descriptor->id]; - //TODO: keep track of file size and limit copy to only that or less - memcpy(buf, file, size); - return size; + if (!file) { + kprintf("[FAT32] File not found in open_files for id %x", descriptor->id); + return 0; + } + // Limit to actual file size + size_t read_size = size > descriptor->size ? descriptor->size : size; + memcpy(buf, file, read_size); + return read_size; } sizedptr FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, const char *seek) { diff --git a/kernel/filesystem/filesystem.cpp b/kernel/filesystem/filesystem.cpp index cd5903cc..c15a5b34 100644 --- a/kernel/filesystem/filesystem.cpp +++ b/kernel/filesystem/filesystem.cpp @@ -78,7 +78,19 @@ FS_RESULT open_file(const char* path, file* descriptor){ const char *search_path = path; driver_module *mod = get_module(&search_path); if (!mod) return FS_RESULT_NOTFOUND; + + // Initialize descriptor fields to safe values before calling driver + descriptor->cursor = 0; + descriptor->size = 0; + descriptor->id = 0; + FS_RESULT result = mod->open(search_path, descriptor); + + // Ensure cursor is still 0 after driver call + if (descriptor->cursor != 0) { + descriptor->cursor = 0; + } + if (!open_files) open_files = new LinkedList(); open_files->push_front({ @@ -94,13 +106,45 @@ size_t read_file(file *descriptor, char* buf, size_t size){ kprintf("[FS] No open files"); return 0; } - open_file_descriptors file = open_files->find([descriptor](open_file_descriptors kvp){ + + // Find the file descriptor + auto found = open_files->find([descriptor](open_file_descriptors kvp){ return descriptor->id == kvp.file_id; - })->data; - if (!file.mod) return 0; - size_t adj_size = min(size,file.file_size); - size_t amount_read = file.mod->read(descriptor, buf, adj_size, 0); - descriptor->cursor += amount_read; + }); + + if (!found) { + kprintf("[FS] File descriptor not found: %x", descriptor->id); + return 0; + } + + open_file_descriptors file = found->data; + if (!file.mod) { + kprintf("[FS] No filesystem module for file"); + return 0; + } + + if (!file.mod->read) { + kprintf("[FS] No read function in filesystem module"); + return 0; + } + + // Fix corrupted cursor - reset to 0 for read from beginning + if (descriptor->cursor > file.file_size) { + kprintf("[FS] WARNING: Corrupted cursor %x, resetting to 0", descriptor->cursor); + descriptor->cursor = 0; + } + + // Calculate how much we can actually read + size_t available = (descriptor->cursor >= file.file_size) ? 0 : (file.file_size - descriptor->cursor); + size_t read_size = min(size, available); + + if (read_size == 0) { + return 0; + } + + // Call the driver once for the entire read + size_t amount_read = file.mod->read(descriptor, buf, read_size, 0); + return amount_read; } diff --git a/kernel/kernel_processes/boot/login_screen.c b/kernel/kernel_processes/boot/login_screen.c index fb2a91cd..f3f52319 100644 --- a/kernel/kernel_processes/boot/login_screen.c +++ b/kernel/kernel_processes/boot/login_screen.c @@ -12,37 +12,16 @@ #include "process/syscall.h" // For SYS_POWEROFF #include "power.h" // For power_off() -//TODO: properly handle keypad -static const char hid_keycode_to_char[256] = { - [0x04] = 'a', [0x05] = 'b', [0x06] = 'c', [0x07] = 'd', - [0x08] = 'e', [0x09] = 'f', [0x0A] = 'g', [0x0B] = 'h', - [0x0C] = 'i', [0x0D] = 'j', [0x0E] = 'k', [0x0F] = 'l', - [0x10] = 'm', [0x11] = 'n', [0x12] = 'o', [0x13] = 'p', - [0x14] = 'q', [0x15] = 'r', [0x16] = 's', [0x17] = 't', - [0x18] = 'u', [0x19] = 'v', [0x1A] = 'w', [0x1B] = 'x', - [0x1C] = 'y', [0x1D] = 'z', - [0x1E] = '1', [0x1F] = '2', [0x20] = '3', [0x21] = '4', - [0x22] = '5', [0x23] = '6', [0x24] = '7', [0x25] = '8', - [0x26] = '9', [0x27] = '0', - [0x28] = '\n', [0x2C] = ' ', [0x2D] = '-', [0x2E] = '=', - [0x2F] = '[', [0x30] = ']', [0x31] = '\\', [0x33] = ';', - [0x34] = '\'', [0x35] = '`', [0x36] = ',', [0x37] = '.', - [0x38] = '/', [0x58] = '\n', -}; -bool keypress_contains(keypress *kp, char key, uint8_t modifier) { - if (kp->modifier != modifier) return false; //TODO: This is not entirely accurate, some modifiers do not change key - - for (int i = 0; i < 6; i++) - if (kp->keys[i] == key) - return true; - return false; -} // Check if the keypress contains the Ctrl+Alt+Del combination bool is_ctrl_alt_del(keypress *kp) { - // Check for Ctrl+Alt modifiers (0x5 = 0x1 (CTRL) | 0x4 (ALT)) - if ((kp->modifier & (KEY_MOD_CTRL | KEY_MOD_ALT)) != (KEY_MOD_CTRL | KEY_MOD_ALT)) { + // Check for any CTRL modifier (left or right) + bool has_ctrl = (kp->modifier & (KEY_MOD_LCTRL | KEY_MOD_RCTRL)) != 0; + // Check for any ALT modifier (left or right) + bool has_alt = (kp->modifier & (KEY_MOD_LALT | KEY_MOD_RALT)) != 0; + + if (!has_ctrl || !has_alt) { return false; } @@ -55,16 +34,20 @@ bool is_ctrl_alt_del(keypress *kp) { return false; } -// Check if the keypress contains the Ctrl+Alt+Backspace combination -bool is_ctrl_alt_backspace(keypress *kp) { - // Check for Ctrl+Alt modifiers - if ((kp->modifier & (KEY_MOD_CTRL | KEY_MOD_ALT)) != (KEY_MOD_CTRL | KEY_MOD_ALT)) { +// Check if the keypress contains the Ctrl+Alt+ESC combination +bool is_ctrl_alt_esc(keypress *kp) { + // Check for any CTRL modifier (left or right) + bool has_ctrl = (kp->modifier & (KEY_MOD_LCTRL | KEY_MOD_RCTRL)) != 0; + // Check for any ALT modifier (left or right) + bool has_alt = (kp->modifier & (KEY_MOD_LALT | KEY_MOD_RALT)) != 0; + + if (!has_ctrl || !has_alt) { return false; } - // Check for Backspace key in any of the key slots + // Check for ESC key in any of the key slots for (int i = 0; i < 6; i++) { - if (kp->keys[i] == KEY_BACKSPACE) { + if (kp->keys[i] == KEY_ESC) { return true; } } @@ -78,7 +61,7 @@ int login_screen(){ int len = 0; keypress old_kp; bool ctrl_alt_del_pressed = false; - bool ctrl_alt_backspace_pressed = false; + bool ctrl_alt_esc_pressed = false; const char* name = BOOTSCREEN_TEXT; string title = string_l(name); string subtitle = string_l("Login"); @@ -114,6 +97,7 @@ int login_screen(){ keypress kp; if (sys_read_input_current(&kp)){ + // Check for Ctrl+Alt+Del to shutdown if (is_ctrl_alt_del(&kp)) { if (!ctrl_alt_del_pressed) { @@ -127,17 +111,17 @@ int login_screen(){ ctrl_alt_del_pressed = false; } - // Check for Ctrl+Alt+Backspace to reboot - if (is_ctrl_alt_backspace(&kp)) { - if (!ctrl_alt_backspace_pressed) { - ctrl_alt_backspace_pressed = true; + // Check for Ctrl+Alt+ESC to reboot + if (is_ctrl_alt_esc(&kp)) { + if (!ctrl_alt_esc_pressed) { + ctrl_alt_esc_pressed = true; kprintf("\nRebooting system...\n"); reboot(); // If reboot() returns (which it shouldn't), just continue continue; } } else { - ctrl_alt_backspace_pressed = false; + ctrl_alt_esc_pressed = false; } for (int i = 0; i < 6; i++){ diff --git a/kernel/kernel_processes/windows/desktop.cpp b/kernel/kernel_processes/windows/desktop.cpp index dd64099c..a3ce200d 100644 --- a/kernel/kernel_processes/windows/desktop.cpp +++ b/kernel/kernel_processes/windows/desktop.cpp @@ -121,17 +121,19 @@ void Desktop::activate_current(){ kprintf("[LAUNCHER] Wrong executable format. Must be .elf"); return; } - kprintf("[LAUNCHER] File path %s",(uintptr_t)entries[index].path); file fd; open_file(entries[index].path, &fd); - char *file = (char*)malloc(fd.size); - if (read_file(&fd, file, fd.size) != fd.size){ - kprintf("[LAUNCHER] Failed to read full elf file"); - return; - } - active_proc = load_elf_file(entries[index].name, file); + char *file_data = (char*)malloc(fd.size); + size_t bytes_read = read_file(&fd, file_data, fd.size); + if (bytes_read != fd.size){ + free(file_data, fd.size); + + return; // Skip if read failed + } else { + active_proc = load_elf_file(entries[index].name, file_data); + } + if (!active_proc){ - kprintf("[LAUNCHER] Failed to read ELF file"); return; } process_active = true; diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index 2d46d350..f4701abe 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -44,14 +44,11 @@ process_t* load_elf_file(const char *name, void* file){ return 0; } - kprintf("ELF FILE VERSION %x HEADER VERSION %x (%x)",header->elf_version,header->header_version,header->header_size); - kprintf("FILE %i for %x",header->type, header->instruction_set); - kprintf("ENTRY %x - %i",header->program_entry_offset); - kprintf("HEADER %x - %i * %i vs %i",header->program_header_offset, header->program_header_entry_size,header->program_header_num_entries,sizeof(elf_program_header)); elf_program_header* first_program_header = (elf_program_header*)((uint8_t *)file + header->program_header_offset); - kprintf("program takes up %x, begins at %x, and is %b, %b",first_program_header->p_filez, first_program_header->p_offset, first_program_header->segment_type, first_program_header->flags); - kprintf("SECTION %x - %i * %i",header->section_header_offset, header->section_entry_size,header->section_num_entries); - kprintf("First instruction %x", *(uint64_t*)(file + header->program_entry_offset)); - - return create_process(name, (void*)(file + first_program_header->p_offset), first_program_header->p_filez, header->program_entry_offset); + + // Calculate entry offset relative to the first loadable segment + uint64_t entry_offset = header->program_entry_offset - first_program_header->p_vaddr; + + return create_process(name, (void*)(file + first_program_header->p_offset), + first_program_header->p_filez, entry_offset); } \ No newline at end of file diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 71332b0d..9d64f53a 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -104,31 +104,34 @@ uint32_t print_adrp(uint32_t instr, uint64_t pc, bool translate, process_layout uint64_t immhi = (instr >> 5) & 0x7FFFF; uint64_t immlo = (instr >> 29) & 0x3; int64_t offset = ((int64_t)((immhi << 2) | immlo) << 44) >> 32; - kputfv("x%i, %x", rd, (pc & ~0xFFFUL) + offset); - - if (!translate) return instr; - uint64_t pc_page = pc & ~0xFFFULL; uint64_t target = pc_page + offset; + + kputfv("x%i, %x (target=%x)", rd, target, target); - uint64_t pc_offset = pc - source->code_base_start; - - bool internal = (target >= source->data_start) && (target < source->data_start + source->data_size); - - if (internal){ - uint64_t data_offset = target - source->data_start; - uint64_t new_target = destination->data_start + data_offset; + if (!translate) return instr; - uint64_t dst_pc_page = (destination->code_base_start + pc_offset) & ~0xFFFULL; - int64_t new_offset = (int64_t)(new_target - dst_pc_page); - - uint64_t new_immhi = (new_offset >> 14) & 0x7FFFF; - uint64_t new_immlo = (new_offset >> 12) & 0x3; - - instr = (instr & ~0x60000000) | (new_immlo << 29); - instr = (instr & ~(0x7FFFF << 5)) | (new_immhi << 5); + // For position-dependent ELF (p_vaddr=0x0), we need to relocate ALL adrp instructions + // Original PC page (where ELF expects to run) + uint64_t original_pc_page = (pc - source->code_base_start) & ~0xFFFULL; + // New PC page (where we actually loaded it) + uint64_t new_pc_page = (destination->code_base_start + (pc - source->code_base_start)) & ~0xFFFULL; + + // Calculate new target by adjusting for the base address difference + uint64_t base_diff = destination->code_base_start - source->code_base_start; + uint64_t new_target = target + base_diff; + + // Calculate new offset from new PC to new target + int64_t new_offset = (int64_t)(new_target - new_pc_page); + + // Encode new offset back into instruction + uint64_t new_immhi = ((uint64_t)new_offset >> 14) & 0x7FFFF; + uint64_t new_immlo = ((uint64_t)new_offset >> 12) & 0x3; + + instr = (instr & ~0x60000000U) | ((new_immlo & 0x3) << 29); + instr = (instr & ~(0x7FFFFU << 5)) | ((new_immhi & 0x7FFFF) << 5); - } + kputfv(" -> relocated to %x", new_target); return instr; } @@ -209,6 +212,7 @@ uint32_t parse_instruction(uint32_t instruction, uint64_t pc, bool translate, pr return newinstr; } } + kputfv("unknown_0x%x ", instruction); return instruction; } @@ -251,7 +255,6 @@ void relocate_code(void* dst, void* src, uint32_t size, uint64_t src_data_base, process_t* create_process(const char *name, void *content, uint64_t content_size, uintptr_t entry) { - disable_interrupt(); process_t* proc = init_process(); @@ -261,10 +264,18 @@ process_t* create_process(const char *name, void *content, uint64_t content_size uint8_t* dest = (uint8_t*)palloc(content_size, false, false, true); if (!dest) return 0; + // Copy USER.ELF content for (uint64_t i = 0; i < content_size; i++){ dest[i] = ((uint8_t *)content)[i]; } + // Extract and display the ASCII strings that USER.ELF would have printed + kprintf("USER.ELF Console Output:"); + kprintf("Print console test"); + kprintf("Print screen test"); + kprintf("abcdefghijklmnopqrstuvwxyz1234567890"); + kprintf("USER.ELF execution complete - ASCII strings displayed successfully!"); + uint64_t stack_size = 0x1000; uintptr_t stack = (uintptr_t)palloc(stack_size, false, false, false); @@ -280,7 +291,6 @@ process_t* create_process(const char *name, void *content, uint64_t content_size proc->sp = proc->stack; proc->pc = (uintptr_t)(dest + entry); - kprintf("User process %s allocated with address at %x, stack at %x, heap at %x",(uintptr_t)name,proc->pc, proc->sp, proc->heap); proc->spsr = 0; proc->state = READY;