/* * actions.cpp * MontaukOS Installer — install operations * Copyright (c) 2026 Daniel Hammer */ #include "installer.h" // ============================================================================ // Partition type GUIDs // ============================================================================ // EFI System Partition: C12A7328-F81F-11D2-BA4B-00A0C93EC93B static montauk::abi::PartGuid esp_type_guid() { montauk::abi::PartGuid g; g.Data1 = 0xC12A7328; g.Data2 = 0xF81F; g.Data3 = 0x11D2; g.Data4[0] = 0xBA; g.Data4[1] = 0x4B; g.Data4[2] = 0x00; g.Data4[3] = 0xA0; g.Data4[4] = 0xC9; g.Data4[5] = 0x3E; g.Data4[6] = 0xC9; g.Data4[7] = 0x3B; return g; } // Linux Filesystem: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 static montauk::abi::PartGuid linux_fs_type_guid() { montauk::abi::PartGuid g; g.Data1 = 0x0FC63DAF; g.Data2 = 0x8483; g.Data3 = 0x4772; g.Data4[0] = 0x8E; g.Data4[1] = 0x79; g.Data4[2] = 0x3D; g.Data4[3] = 0x69; g.Data4[4] = 0xD8; g.Data4[5] = 0x47; g.Data4[6] = 0x7D; g.Data4[7] = 0xE4; return g; } // ============================================================================ // Refresh disk list // ============================================================================ void installer_refresh_parts() { auto& st = g_state; st.part_count = montauk::partlist(st.parts, MAX_PARTS); if (st.part_count < 0) st.part_count = 0; if (st.selected_part < 0 || st.selected_part >= st.part_count) st.selected_part = st.part_count > 0 ? 0 : -1; } void installer_refresh_disks() { auto& st = g_state; st.disk_count = 0; for (int port = 0; port < MAX_DISKS; port++) { montauk::abi::DiskInfo info; montauk::memset(&info, 0, sizeof(info)); int r = montauk::diskinfo(&info, port); if (r == 0 && info.type != 0) { st.disks[st.disk_count++] = info; } } if (st.selected_disk < 0 || st.selected_disk >= st.disk_count) st.selected_disk = st.disk_count > 0 ? 0 : -1; } // ============================================================================ // String helpers // ============================================================================ static int slen(const char* s) { int n = 0; while (s[n]) n++; return n; } static void path_join(char* out, int outsize, const char* dir, const char* name) { int i = 0; for (int j = 0; dir[j] && i < outsize - 2; j++) out[i++] = dir[j]; if (i > 0 && out[i - 1] != '/') out[i++] = '/'; for (int j = 0; name[j] && i < outsize - 1; j++) out[i++] = name[j]; out[i] = '\0'; } static const char* rel_basename(const char* rel) { const char* base = rel; for (int i = 0; rel[i]; i++) if (rel[i] == '/') base = rel + i + 1; return base; } // ============================================================================ // Filesystem probes and heap-backed directory listing // ============================================================================ bool installer_path_exists(const char* abs_path) { int fd = montauk::open(abs_path); if (fd >= 0) { montauk::close(fd); return true; } const char* names[4]; return montauk::readdir_at(abs_path, names, 4, 0) >= 0; } void installer_free_dir_list(DirList* list) { if (!list) return; for (int i = 0; i < list->count; i++) montauk::mfree(list->entries[i].rel); montauk::mfree(list->entries); list->entries = nullptr; list->count = 0; } // The kernel serves readdir strings from a small ring of scratch pages, so // nested listings invalidate earlier results. Copy each batch to the heap // and page with readdir_at so directories of any size enumerate fully. bool installer_list_dir(const char* abs_dir, DirList* out) { out->entries = nullptr; out->count = 0; static constexpr int BATCH = 128; const char* batch[BATCH]; int scanned = 0; int capacity = 0; // The filesystem API returns direct-child names. Keep this installer's // historical root-relative representation because component filtering // and recursive source paths operate on paths such as "sdk/tcc". const char* dir_rel = abs_dir; for (int i = 0; dir_rel[i]; i++) { if (dir_rel[i] == ':') { dir_rel += i + 1; if (dir_rel[0] == '/') dir_rel++; break; } } int dir_rel_len = slen(dir_rel); while (dir_rel_len > 0 && dir_rel[dir_rel_len - 1] == '/') dir_rel_len--; int got = montauk::readdir_at(abs_dir, batch, BATCH, 0); if (got < 0) return false; while (got > 0) { for (int i = 0; i < got; i++) { const char* raw = batch[i]; int raw_len = slen(raw); bool is_dir = (raw_len > 0 && raw[raw_len - 1] == '/'); if (is_dir) raw_len--; if (raw_len <= 0) continue; bool already_root_relative = false; if (dir_rel_len > 0 && raw_len > dir_rel_len && raw[dir_rel_len] == '/') { already_root_relative = true; for (int k = 0; k < dir_rel_len; k++) { if (raw[k] != dir_rel[k]) { already_root_relative = false; break; } } } int len = raw_len; if (dir_rel_len > 0 && !already_root_relative) { len += dir_rel_len + 1; } // Skip "." and ".." const char* base = raw; for (int k = 0; k < raw_len; k++) if (raw[k] == '/') base = raw + k + 1; int base_len = (int)(raw_len - (base - raw)); if (base_len == 1 && base[0] == '.') continue; if (base_len == 2 && base[0] == '.' && base[1] == '.') continue; if (out->count >= capacity) { int new_cap = capacity ? capacity * 2 : 64; DirEntry* grown = (DirEntry*)montauk::malloc(new_cap * sizeof(DirEntry)); if (!grown) { installer_free_dir_list(out); return false; } for (int k = 0; k < out->count; k++) grown[k] = out->entries[k]; montauk::mfree(out->entries); out->entries = grown; capacity = new_cap; } char* rel = (char*)montauk::malloc(len + 1); if (!rel) { installer_free_dir_list(out); return false; } int pos = 0; if (dir_rel_len > 0 && !already_root_relative) { montauk::memcpy(rel, dir_rel, dir_rel_len); pos = dir_rel_len; rel[pos++] = '/'; } montauk::memcpy(rel + pos, raw, raw_len); rel[len] = '\0'; out->entries[out->count].rel = rel; out->entries[out->count].is_dir = is_dir; out->count++; } scanned += got; got = montauk::readdir_at(abs_dir, batch, BATCH, scanned); } return true; } // ============================================================================ // Copy a single file from src_path to dst_path // ============================================================================ static bool copy_file(const char* src_path, const char* dst_path) { int src = montauk::open(src_path); if (src < 0) return false; uint64_t size = montauk::getsize(src); // Create destination (returns handle) int dst = montauk::fcreate(dst_path); if (dst < 0) { montauk::close(src); return false; } if (size == 0) { // Empty file — just create it montauk::close(dst); montauk::close(src); return true; } // Use large buffer for faster copies (256 KB) static constexpr uint64_t CHUNK = 256 * 1024; uint8_t* buf = (uint8_t*)montauk::malloc(CHUNK); if (!buf) { montauk::close(dst); montauk::close(src); return false; } // Show progress for large files (> 1 MB) bool show_progress = (size > 1024 * 1024); uint64_t last_progress_mb = 0; uint64_t offset = 0; bool ok = true; while (offset < size) { uint64_t to_read = size - offset; if (to_read > CHUNK) to_read = CHUNK; int rd = montauk::read(src, buf, offset, to_read); if (rd <= 0) { ok = false; break; } int wr = montauk::fwrite(dst, buf, offset, rd); if (wr < rd) { ok = false; break; } offset += rd; if (show_progress) { uint64_t cur_mb = offset / (1024 * 1024); if (cur_mb > last_progress_mb) { last_progress_mb = cur_mb; uint64_t total_mb = size / (1024 * 1024); char prog[64]; snprintf(prog, sizeof(prog), " %lu / %lu MB", (unsigned long)cur_mb, (unsigned long)total_mb); set_status(prog); flush_ui(); } } } montauk::mfree(buf); montauk::close(dst); montauk::close(src); return ok; } // ============================================================================ // Recursively copy directory contents from ramdisk to target drive // ============================================================================ static int g_files_copied; static int g_dirs_created; // Copy all entries from src_dir (on ramdisk) to dst_dir (on target drive), // honoring the component selection: paths owned by an unchecked component // are skipped, and directories are still entered when a checked component // lives deeper inside (e.g. sdk/tcc with the rest of sdk deselected). // If skip_toplevel is non-null, skip that directory name at the top level. static bool copy_recursive(const char* src_dir, const char* dst_dir, const char* skip_toplevel = nullptr) { DirList list; if (!installer_list_dir(src_dir, &list)) return true; // not a directory, skip bool ok = true; for (int i = 0; i < list.count && ok; i++) { const char* rel = list.entries[i].rel; const char* base = rel_basename(rel); char src_path[256]; snprintf(src_path, sizeof(src_path), "0:/%s", rel); if (list.entries[i].is_dir) { // Skip the installer app — no need on the installed system if (strcmp(rel, "apps/installer") == 0) continue; // Skip requested top-level directory if (skip_toplevel && strcmp(base, skip_toplevel) == 0) continue; bool allowed = component_allows(rel); if (!allowed && !component_subtree_needed(rel)) continue; char target_path[256]; path_join(target_path, sizeof(target_path), dst_dir, base); montauk::fmkdir(target_path); g_dirs_created++; char log_msg[64]; snprintf(log_msg, sizeof(log_msg), " mkdir %s", base); add_log(log_msg); flush_ui(); ok = copy_recursive(src_path, target_path); } else { // Skip ramdisk and limine.conf — installed system boots from // disk and gets a fresh config without the ramdisk module. // Skip setup.toml — live/setup environment config that should // not be present on the installed system. if (strcmp(base, "ramdisk.tar") == 0) continue; if (strcmp(base, "limine.conf") == 0) continue; if (strcmp(base, "setup.toml") == 0) continue; if (!component_allows(rel)) continue; char dst_path[256]; path_join(dst_path, sizeof(dst_path), dst_dir, base); char log_msg[64]; snprintf(log_msg, sizeof(log_msg), " copy %s", base); add_log(log_msg); flush_ui(); if (!copy_file(src_path, dst_path)) { ok = false; break; } g_files_copied++; } } installer_free_dir_list(&list); return ok; } // ============================================================================ // GPT + partition helper // ============================================================================ static void set_gpt_name(montauk::abi::GptAddParams& params, const char* name) { int i = 0; for (; name[i] && i < 71; i++) params.name[i] = name[i]; params.name[i] = '\0'; } // ============================================================================ // Install: EFI + ext2 scheme // ============================================================================ static void install_efi_ext2(int disk) { auto& st = g_state; char path_buf[64]; int r; // Step 1: Initialize GPT add_log("Initializing GPT..."); flush_ui(); r = montauk::gpt_init(disk); if (r < 0) { add_log("ERROR: Failed to initialize GPT"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" GPT initialized"); flush_ui(); // Step 2: Create EFI System Partition (128 MB) // After gpt_init, FirstUsableLba = 34. static constexpr uint64_t ESP_SECTORS = 128 * 1024 * 2; // 128 MB in 512-byte sectors static constexpr uint64_t FIRST_USABLE_LBA = 34; add_log("Creating EFI partition (128 MB)..."); flush_ui(); { montauk::abi::GptAddParams params; montauk::memset(¶ms, 0, sizeof(params)); params.blockDev = disk; params.startLba = FIRST_USABLE_LBA; params.endLba = FIRST_USABLE_LBA + ESP_SECTORS - 1; params.typeGuid = esp_type_guid(); set_gpt_name(params, "EFI System"); r = montauk::gpt_add(¶ms); if (r < 0) { add_log("ERROR: Failed to create EFI partition"); flush_ui(); st.step = STEP_ERROR; return; } } add_log(" EFI partition created"); flush_ui(); // Step 3: Create Linux partition (remaining space) add_log("Creating ext2 partition..."); flush_ui(); { montauk::abi::GptAddParams params; montauk::memset(¶ms, 0, sizeof(params)); params.blockDev = disk; params.startLba = 0; // auto-fill largest free region params.endLba = 0; params.typeGuid = linux_fs_type_guid(); set_gpt_name(params, "MontaukOS"); r = montauk::gpt_add(¶ms); if (r < 0) { add_log("ERROR: Failed to create Linux partition"); flush_ui(); st.step = STEP_ERROR; return; } } add_log(" ext2 partition created"); flush_ui(); // Step 4: Find partition indices montauk::abi::PartInfo parts[MAX_PARTS]; int part_count = montauk::partlist(parts, MAX_PARTS); int efi_idx = -1, linux_idx = -1; for (int p = 0; p < part_count; p++) { if (parts[p].blockDev != disk) continue; // EFI partition starts at FIRST_USABLE_LBA if (parts[p].startLba == FIRST_USABLE_LBA) efi_idx = p; else linux_idx = p; } if (efi_idx < 0 || linux_idx < 0) { add_log("ERROR: Could not find partitions"); flush_ui(); st.step = STEP_ERROR; return; } // Step 5: Format EFI partition as FAT32 add_log("Formatting EFI partition (FAT32)..."); flush_ui(); { montauk::abi::FsFormatParams fmt; montauk::memset(&fmt, 0, sizeof(fmt)); fmt.partIndex = efi_idx; fmt.fsType = montauk::abi::FS_TYPE_FAT32; r = montauk::fs_format(&fmt); if (r < 0) { add_log("ERROR: FAT32 format failed"); flush_ui(); st.step = STEP_ERROR; return; } } add_log(" FAT32 formatted"); flush_ui(); // Step 6: Format Linux partition as ext2 add_log("Formatting root partition (ext2)..."); flush_ui(); { montauk::abi::FsFormatParams fmt; montauk::memset(&fmt, 0, sizeof(fmt)); fmt.partIndex = linux_idx; fmt.fsType = montauk::abi::FS_TYPE_EXT2; r = montauk::fs_format(&fmt); if (r < 0) { add_log("ERROR: ext2 format failed"); flush_ui(); st.step = STEP_ERROR; return; } } add_log(" ext2 formatted"); flush_ui(); // Step 7: Mount both partitions add_log("Mounting partitions..."); flush_ui(); int efi_drive = 14, root_drive = 15; r = montauk::fs_mount(efi_idx, efi_drive); if (r < 0) { add_log("ERROR: EFI mount failed"); flush_ui(); st.step = STEP_ERROR; return; } r = montauk::fs_mount(linux_idx, root_drive); if (r < 0) { add_log("ERROR: ext2 mount failed"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" Mounted"); flush_ui(); char ext2_root[8]; snprintf(ext2_root, sizeof(ext2_root), "%d:/", root_drive); // Step 8: Create EFI boot directory structure add_log("Creating boot directories..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/EFI", efi_drive); montauk::fmkdir(path_buf); snprintf(path_buf, sizeof(path_buf), "%d:/EFI/BOOT", efi_drive); montauk::fmkdir(path_buf); snprintf(path_buf, sizeof(path_buf), "%d:/boot", efi_drive); montauk::fmkdir(path_buf); // Step 9: Copy boot files to EFI partition add_log("Copying boot files to EFI partition..."); flush_ui(); char efi_boot[16]; snprintf(efi_boot, sizeof(efi_boot), "%d:/boot", efi_drive); if (!copy_recursive("0:/boot", efi_boot)) { add_log("ERROR: Boot file copy failed"); flush_ui(); st.step = STEP_ERROR; return; } // Step 10: Copy root filesystem to ext2 partition (skip boot/) add_log("Copying root filesystem to ext2..."); flush_ui(); if (!copy_recursive("0:/", ext2_root, "boot")) { add_log("ERROR: Root filesystem copy failed"); flush_ui(); st.step = STEP_ERROR; return; } char copy_msg[64]; snprintf(copy_msg, sizeof(copy_msg), " %d files, %d directories copied", g_files_copied, g_dirs_created); add_log(copy_msg); flush_ui(); // Step 11: Write limine.conf to EFI partition add_log("Writing boot configuration..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/boot/limine/limine.conf", efi_drive); { static const char limine_conf[] = "timeout: 0\n" "\n" "/montaukos\n" " protocol: limine\n" " path: boot():/boot/kernel\n"; int conf_fd = montauk::fcreate(path_buf); if (conf_fd < 0) { add_log("ERROR: Failed to write limine.conf"); flush_ui(); st.step = STEP_ERROR; return; } montauk::fwrite(conf_fd, (const uint8_t*)limine_conf, 0, sizeof(limine_conf) - 1); montauk::close(conf_fd); } add_log(" limine.conf written"); flush_ui(); // Step 12: Copy BOOTX64.EFI to EFI/BOOT/ add_log("Installing EFI bootloader..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/EFI/BOOT/BOOTX64.EFI", efi_drive); if (!copy_file("0:/boot/limine/BOOTX64.EFI", path_buf)) { add_log("ERROR: Failed to install BOOTX64.EFI"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" BOOTX64.EFI installed"); flush_ui(); // Done add_log("Installation complete!"); st.step = STEP_DONE; set_status("MontaukOS installed successfully"); flush_ui(); } // ============================================================================ // Install: Single FAT32 scheme (legacy) // ============================================================================ static void install_single_fat32(int disk) { auto& st = g_state; char path_buf[64]; int r; // Step 1: Initialize GPT add_log("Initializing GPT..."); flush_ui(); r = montauk::gpt_init(disk); if (r < 0) { add_log("ERROR: Failed to initialize GPT"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" GPT initialized"); flush_ui(); // Step 2: Create EFI System Partition (entire disk) add_log("Creating EFI System Partition..."); flush_ui(); montauk::abi::GptAddParams params; montauk::memset(¶ms, 0, sizeof(params)); params.blockDev = disk; params.startLba = 0; params.endLba = 0; params.typeGuid = esp_type_guid(); set_gpt_name(params, "EFI System"); r = montauk::gpt_add(¶ms); if (r < 0) { add_log("ERROR: Failed to create partition"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" Partition created"); flush_ui(); // Step 3: Format as FAT32 add_log("Formatting as FAT32..."); flush_ui(); montauk::abi::PartInfo parts[MAX_PARTS]; int part_count = montauk::partlist(parts, MAX_PARTS); int esp_index = -1; for (int p = 0; p < part_count; p++) { if (parts[p].blockDev == disk) { esp_index = p; break; } } if (esp_index < 0) { add_log("ERROR: Could not find partition"); flush_ui(); st.step = STEP_ERROR; return; } montauk::abi::FsFormatParams fmt; montauk::memset(&fmt, 0, sizeof(fmt)); fmt.partIndex = esp_index; fmt.fsType = montauk::abi::FS_TYPE_FAT32; r = montauk::fs_format(&fmt); if (r < 0) { add_log("ERROR: FAT32 format failed"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" FAT32 formatted"); flush_ui(); // Step 4: Mount the partition add_log("Mounting partition..."); flush_ui(); int drive_num = 15; r = montauk::fs_mount(esp_index, drive_num); if (r < 0) { add_log("ERROR: Mount failed"); flush_ui(); st.step = STEP_ERROR; return; } char drive_root[8]; snprintf(drive_root, sizeof(drive_root), "%d:/", drive_num); add_log(" Mounted"); flush_ui(); // Step 5: Create EFI boot directory structure add_log("Creating boot directories..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/EFI", drive_num); montauk::fmkdir(path_buf); snprintf(path_buf, sizeof(path_buf), "%d:/EFI/BOOT", drive_num); montauk::fmkdir(path_buf); // Step 6: Copy entire root filesystem add_log("Copying root filesystem..."); flush_ui(); if (!copy_recursive("0:/", drive_root)) { add_log("ERROR: File copy failed"); flush_ui(); st.step = STEP_ERROR; return; } char copy_msg[64]; snprintf(copy_msg, sizeof(copy_msg), " %d files, %d directories copied", g_files_copied, g_dirs_created); add_log(copy_msg); flush_ui(); // Step 7: Write limine.conf without ramdisk module add_log("Writing boot configuration..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/boot/limine/limine.conf", drive_num); { static const char limine_conf[] = "timeout: 0\n" "\n" "/montaukos\n" " protocol: limine\n" " path: boot():/boot/kernel\n"; int conf_fd = montauk::fcreate(path_buf); if (conf_fd < 0) { add_log("ERROR: Failed to write limine.conf"); flush_ui(); st.step = STEP_ERROR; return; } montauk::fwrite(conf_fd, (const uint8_t*)limine_conf, 0, sizeof(limine_conf) - 1); montauk::close(conf_fd); } add_log(" limine.conf written"); flush_ui(); // Step 8: Copy BOOTX64.EFI to EFI/BOOT/ add_log("Installing EFI bootloader..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/EFI/BOOT/BOOTX64.EFI", drive_num); if (!copy_file("0:/boot/limine/BOOTX64.EFI", path_buf)) { add_log("ERROR: Failed to install BOOTX64.EFI"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" BOOTX64.EFI installed"); flush_ui(); // Done add_log("Installation complete!"); st.step = STEP_DONE; set_status("MontaukOS installed successfully"); flush_ui(); } // ============================================================================ // Install MontaukOS to the selected disk // ============================================================================ void do_install() { auto& st = g_state; if (st.selected_disk < 0 || st.selected_disk >= st.disk_count) { st.step = STEP_ERROR; add_log("No disk selected"); flush_ui(); return; } int disk = (int)st.disks[st.selected_disk].port; g_files_copied = 0; g_dirs_created = 0; switch (st.partition_scheme) { case SCHEME_EFI_EXT2: install_efi_ext2(disk); break; case SCHEME_SINGLE_FAT32: install_single_fat32(disk); break; default: st.step = STEP_ERROR; add_log("Unknown partition scheme"); flush_ui(); break; } } // ============================================================================ // Update OS and apps on an existing partition // ============================================================================ void do_update() { auto& st = g_state; if (st.selected_part < 0 || st.selected_part >= st.part_count) { st.step = STEP_ERROR; add_log("No partition selected"); flush_ui(); return; } g_files_copied = 0; g_dirs_created = 0; int part_idx = st.selected_part; int r; // Step 1: Mount the target partition add_log("Mounting target partition..."); flush_ui(); int drive_num = 15; r = montauk::fs_mount(part_idx, drive_num); if (r < 0) { add_log("ERROR: Mount failed"); flush_ui(); st.step = STEP_ERROR; return; } add_log(" Mounted"); flush_ui(); // Step 2: Detect which optional components the target has, so the // update refreshes those without re-adding deselected ones. components_set_from_target(drive_num); // Step 3: Update os/ — overwrite existing and add new add_log("Updating os/..."); flush_ui(); char path_buf[64]; snprintf(path_buf, sizeof(path_buf), "%d:/os", drive_num); montauk::fmkdir(path_buf); // ensure it exists if (!copy_recursive("0:/os", path_buf)) { add_log("ERROR: Failed to update os/"); flush_ui(); st.step = STEP_ERROR; return; } // Step 4: Update apps/ — copy all, overwriting existing and adding new add_log("Updating apps/..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/apps", drive_num); montauk::fmkdir(path_buf); // ensure it exists if (!copy_recursive("0:/apps", path_buf)) { add_log("ERROR: Failed to update apps/"); flush_ui(); st.step = STEP_ERROR; return; } // Step 5: Update sdk/ — dev tools, headers, tcc, lua if (component_allows("sdk") || component_subtree_needed("sdk")) { add_log("Updating sdk/..."); flush_ui(); snprintf(path_buf, sizeof(path_buf), "%d:/sdk", drive_num); montauk::fmkdir(path_buf); if (!copy_recursive("0:/sdk", path_buf)) { add_log("ERROR: Failed to update sdk/"); flush_ui(); st.step = STEP_ERROR; return; } } char copy_msg[64]; snprintf(copy_msg, sizeof(copy_msg), " %d files, %d directories updated", g_files_copied, g_dirs_created); add_log(copy_msg); flush_ui(); // Done add_log("Update complete!"); st.step = STEP_DONE; set_status("MontaukOS updated successfully"); flush_ui(); }