#include #include #include #include #include #include #include #include #include "../arch/x86_64/limine.h" #define DSK_PATH "/system/deshab64/deshab.elf" #define DSK_CMDLINE "dsk:main" #define ELF_MAGIC0 0x7f #define ELF_MAGIC1 'E' #define ELF_MAGIC2 'L' #define ELF_MAGIC3 'F' #define ELFCLASS64 2 #define ELFDATA2LSB 1 #define ET_DYN 3 #define ET_EXEC 2 #define EM_X86_64 62 #define PT_LOAD 1 #define PT_DYNAMIC 2 /* ELF Dynamic section tags */ #define DT_NULL 0 #define DT_RELA 7 #define DT_RELASZ 8 #define DT_RELAENT 9 /* ELF Relocation types */ #define R_X86_64_RELATIVE 8 typedef struct elf64_dyn { i64 tag; u64 val; } elf64_dyn; typedef struct elf64_rela { u64 offset; u64 info; i64 addend; } elf64_rela; void *memset(void *dst, int value, usize len); void *memcpy(void *dst, const void *src, usize len); extern volatile struct limine_module_request g_module_request; extern volatile struct limine_rsdp_request g_rsdp_request; extern volatile struct limine_framebuffer_request g_fb_request; extern volatile struct limine_hhdm_request g_hhdm_request; typedef struct elf64_ehdr { u8 ident[16]; u16 type; u16 machine; u32 version; u64 entry; u64 phoff; u64 shoff; u32 flags; u16 ehsize; u16 phentsize; u16 phnum; u16 shentsize; u16 shnum; u16 shstrndx; } elf64_ehdr; typedef struct elf64_phdr { u32 type; u32 flags; u64 offset; u64 vaddr; u64 paddr; u64 filesz; u64 memsz; u64 align; } elf64_phdr; /* ---- minimal FAT32 parser ---- */ typedef struct __attribute__((packed)) { u8 jmp[3]; char oem[8]; u16 bytes_per_sector; u8 sectors_per_cluster; u16 reserved_sector_count; u8 fat_count; u16 root_entry_count; u16 total_sectors_16; u8 media; u16 sectors_per_fat_16; u16 sectors_per_track; u16 heads; u32 hidden_sectors; u32 total_sectors_32; u32 sectors_per_fat; u16 flags; u16 version; u32 root_cluster; u16 fsinfo_sector; u16 backup_boot; u8 reserved[12]; u8 drive; u8 nt_flags; u8 signature; u32 serial; char label[11]; char type[8]; u8 code[420]; u16 boot_sig; } fat32_bpb; typedef struct __attribute__((packed)) { char name[11]; u8 attr; u8 nt_reserved; u8 creation_tenth; u16 creation_time; u16 creation_date; u16 access_date; u16 cluster_high; u16 write_time; u16 write_date; u16 cluster_low; u32 file_size; } fat32_dir_entry; static u32 fat32_read_u32(const u8 *p) { return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24); } static u16 fat32_read_u16(const u8 *p) { return (u16)p[0] | ((u16)p[1] << 8); } static int fat32_name11_eq(const char *n, const char *s) { for (int i = 0; i < 11; i++) { if (n[i] != s[i]) return 0; } return 1; } /* core helpers reused from earlier loader */ static int streq(const char *a, const char *b) { if (!a || !b) return 0; while (*a && *b) { if (*a != *b) return 0; a++; b++; } return *a == *b; } static int range_ok(u64 offset, u64 length, u64 size) { if (offset > size) return 0; if (length > size - offset) return 0; return 1; } static struct limine_file *dsk_find_module(void) { struct limine_module_response *rsp = g_module_request.response; if (!rsp) return 0; for (u64 i = 0; i < rsp->module_count; i++) { struct limine_file *file = rsp->modules[i]; if (!file) continue; if (streq(file->path, DSK_PATH) || streq(file->cmdline, DSK_CMDLINE)) { return file; } } return 0; } /* ---- FAT32 block-provider file reader ---- */ static u8 g_dsk_fat32_disk[131072]; /* 256-sector BPB+FAT+root dir buffer (与 DSK 端一致) */ static u8 g_dsk_fat32_cluster[4096]; /* 8-sector cluster buffer */ /* 实机要求: 文件缓冲区足够大容纳 deshab.elf (~1.5MB) */ static u8 g_dsk_fat32_filedata[2097152]; /* 2MB file data buffer */ /* BUG-019 修复: FAT 按需扇区读取缓冲区(仅 512 字节), * 当 FAT 条目偏移超出 g_dsk_fat32_disk (128KB) 时使用。 */ static u8 g_dsk_fat32_fat_sec[512]; /* BUG-019 修复: 按需读取 FAT 扇区获取下一个簇号。 * 如果目标 FAT 条目在预读缓冲区内,直接读取; * 否则只读取包含该条目的单个 FAT 扇区(512 字节)。 * fat_start: FAT 在预读缓冲区中的字节偏移(reserved_sectors * 512)。 * clus: 当前簇号。 * bpb: BPB 指针(用于计算 FAT 扇区 LBA)。 * disk: 预读缓冲区基址。 * 返回: 下一个簇号,失败返回 0x0FFFFFFF(链终止)。 */ static u32 fat32_get_next_cluster(u32 fat_start_byte, u32 clus, const fat32_bpb *bpb, const u8 *disk) { u32 fat_ent_off = fat_start_byte + clus * 4; /* 情况 1: FAT 条目在预读缓冲区内(小分区) */ if (fat_ent_off + 4 <= sizeof(g_dsk_fat32_disk)) { return fat32_read_u32(disk + fat_ent_off) & 0x0FFFFFFF; } /* 情况 2: FAT 条目超出预读缓冲区(实机大分区)——按需读取单个 FAT 扇区 */ const dkm_kernel_api *api = dkm_get_kernel_api(); if (!api || !api->block) return 0x0FFFFFFF; /* FAT 条目在 FAT 表中的字节偏移(相对于 FAT 起始) */ u32 fat_byte_off_in_fat = clus * 4; /* 该条目所在的 FAT 扇区号(相对于 FAT 起始) */ u32 fat_sec_index = fat_byte_off_in_fat / 512; /* 条目在扇区内的字节偏移 */ u32 ent_off_in_sec = fat_byte_off_in_fat % 512; /* FAT 扇区的绝对 LBA */ u32 fat_sec_lba = bpb->reserved_sector_count + fat_sec_index; int st = api->block->read(0, fat_sec_lba, 1, g_dsk_fat32_fat_sec); if (st != 0) { log_error("[UTSM] FAT32: on-demand FAT sector read failed"); log_hex64("[UTSM] FAT32: fat_sec_lba=", fat_sec_lba); log_hex64("[UTSM] FAT32: clus=", clus); return 0x0FFFFFFF; } return fat32_read_u32(g_dsk_fat32_fat_sec + ent_off_in_sec) & 0x0FFFFFFF; } static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { const dkm_kernel_api *api = dkm_get_kernel_api(); if (!api || !api->block || !api->block->device_count) { log_error("[UTSM] FAT32: no block api available"); return -1; } u32 count = api->block->device_count(); if (count == 0 || api->block->sector_size(0) != 512) { log_error("[UTSM] FAT32: no block device or wrong sector size"); log_hex64("[UTSM] FAT32: device_count=", count); return -1; } /* Read first 256 sectors: BPB + FAT + root dir */ u8 *disk = g_dsk_fat32_disk; int st = api->block->read(0, 0, 256, disk); if (st != 0) { log_error("[UTSM] FAT32: BPB read failed"); log_hex64("[UTSM] FAT32: read status=", (u64)(i64)st); return -1; } const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) { log_error("[UTSM] FAT32: invalid BPB signature or sector size"); log_hex64("[UTSM] FAT32: boot_sig=", bpb->boot_sig); log_hex64("[UTSM] FAT32: bps=", bpb->bytes_per_sector); return -1; } u32 fat_start = bpb->reserved_sector_count * 512; u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat; log_hex64("[UTSM] FAT32: fat_start_off=", fat_start); log_hex64("[UTSM] FAT32: data_start_sec=", data_start_sec); log_hex64("[UTSM] FAT32: spc=", bpb->sectors_per_cluster); log_hex64("[UTSM] FAT32: root_clus=", bpb->root_cluster); u32 clus = bpb->root_cluster; u32 found_clus = 0; u32 found_size = 0; const char *target = "DESHAB ELF"; while (clus >= 2 && clus < 0x0FFFFFF8) { u32 clus_lba = data_start_sec + (clus - 2) * bpb->sectors_per_cluster; u32 cls_sec = bpb->sectors_per_cluster; u8 *cb = g_dsk_fat32_cluster; st = api->block->read(0, clus_lba, cls_sec, cb); if (st != 0) { log_error("[UTSM] FAT32: dir cluster read failed"); log_hex64("[UTSM] FAT32: clus=", clus); log_hex64("[UTSM] FAT32: lba=", clus_lba); return -1; } const fat32_dir_entry *dir = (const fat32_dir_entry *)cb; for (u32 e = 0; e * 32 < cls_sec * 512; e++) { if (dir[e].name[0] == 0) break; if ((u8)dir[e].name[0] == 0xE5) continue; if (dir[e].attr == 0x0F) continue; if (dir[e].attr & 0x08) continue; if (fat32_name11_eq(dir[e].name, target)) { found_size = dir[e].file_size; found_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low) | ((u32)fat32_read_u16((const u8 *)&dir[e].cluster_high) << 16); break; } } if (found_clus) break; /* BUG-019: 使用按需 FAT 读取,不再受 128KB 缓冲区限制 */ clus = fat32_get_next_cluster(fat_start, clus, bpb, disk); } if (!found_clus || found_size == 0) { log_error("[UTSM] FAT32: DESHAB.ELF not found in root dir"); return -1; } log_hex64("[UTSM] FAT32: found_clus=", found_clus); log_hex64("[UTSM] FAT32: found_size=", found_size); if (found_size > sizeof(g_dsk_fat32_filedata)) { log_error("[UTSM] FAT32: file exceeds 2MB buffer"); return -1; } u8 *dst = g_dsk_fat32_filedata; u32 remaining = found_size; u32 fc = found_clus; while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) { u32 fc_lba = data_start_sec + (fc - 2) * bpb->sectors_per_cluster; u32 fc_sec = bpb->sectors_per_cluster; u32 fc_bytes = fc_sec * 512; if (fc_bytes > remaining) fc_bytes = remaining; u8 *chunk = g_dsk_fat32_cluster; st = api->block->read(0, fc_lba, fc_sec, chunk); if (st != 0) { log_error("[UTSM] FAT32: data cluster read failed"); log_hex64("[UTSM] FAT32: fc=", fc); log_hex64("[UTSM] FAT32: lba=", fc_lba); return -1; } for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b]; dst += fc_bytes; remaining -= fc_bytes; /* BUG-019: 使用按需 FAT 读取 */ fc = fat32_get_next_cluster(fat_start, fc, bpb, disk); } /* Copy to arena for ELF loader */ u8 *file_buf = (u8 *)kmem_alloc_aligned(found_size, 16); if (!file_buf) { log_error("[UTSM] FAT32: arena alloc failed"); log_hex64("[UTSM] FAT32: size=", found_size); return -1; } for (u32 i = 0; i < found_size; i++) file_buf[i] = g_dsk_fat32_filedata[i]; *out_addr = file_buf; *out_size = found_size; log_hex64("[UTSM] FAT32 file size=", found_size); return 0; } /* ---- FAT32 subdirectory traversal ---- */ /* 在指定起始 cluster 的目录项中查找 name11。 * is_dir=1 时只匹配子目录(attr & 0x10),is_dir=0 时只匹配文件。 * 返回 0 成功,out_clus/out_size 返回匹配项的起始 cluster 和大小。 */ static int fat32_find_in_dir(u32 start_clus, const char *name11, int is_dir, u32 *out_clus, u32 *out_size) { const dkm_kernel_api *api = dkm_get_kernel_api(); if (!api || !api->block || !api->block->device_count) return -1; u8 *disk = g_dsk_fat32_disk; const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -2; u32 fat_start = bpb->reserved_sector_count * 512; u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat; u32 spc = bpb->sectors_per_cluster; u32 clus = start_clus; while (clus >= 2 && clus < 0x0FFFFFF8) { u32 clus_lba = data_start_sec + (clus - 2) * spc; u8 *cb = g_dsk_fat32_cluster; int st = api->block->read(0, clus_lba, spc, cb); if (st != 0) return -3; const fat32_dir_entry *dir = (const fat32_dir_entry *)cb; for (u32 e = 0; e * 32 < spc * 512; e++) { if (dir[e].name[0] == 0) break; if ((u8)dir[e].name[0] == 0xE5) continue; if (dir[e].attr == 0x0F) continue; if (dir[e].attr & 0x08) continue; if (!fat32_name11_eq(dir[e].name, name11)) continue; /* 名称匹配,检查类型 */ int entry_is_dir = (dir[e].attr & 0x10) ? 1 : 0; if (entry_is_dir != is_dir) continue; *out_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low) | ((u32)fat32_read_u16((const u8 *)&dir[e].cluster_high) << 16); *out_size = dir[e].file_size; return 0; } /* 跟随 FAT 链 — BUG-019: 使用按需 FAT 读取 */ clus = fat32_get_next_cluster(fat_start, clus, bpb, disk); } return -4; /* 未找到 */ } /* 按路径查找文件并读取内容。 * path: '/' 分隔的 8.3 格式路径(如 "SYSTEM /DESHAB64 /FUCK ")。 * out_data: 返回在 g_dsk_fat32_filedata 中的文件数据指针。 * out_size: 返回文件大小。 * 返回 0 成功。 */ int fat32_read_path(const char *path, u8 **out_data, u32 *out_size) { const dkm_kernel_api *api = dkm_get_kernel_api(); if (!api || !api->block || !api->block->device_count) return -1; u8 *disk = g_dsk_fat32_disk; /* 确保 BPB 缓冲区是新鲜的 */ if (api->block->read(0, 0, 256, disk) != 0) return -2; const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -3; u32 fat_start = bpb->reserved_sector_count * 512; u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat; u32 spc = bpb->sectors_per_cluster; /* 解析路径组件 */ u32 pos = 0; u32 path_len = 0; while (path[path_len]) path_len++; u32 cur_clus = bpb->root_cluster; /* 从根目录开始 */ while (pos < path_len) { /* 提取一个路径组件(到下一个 '/' 或结尾) */ char comp[12]; /* 11 字符 8.3 名 + \0 */ u32 ci = 0; while (pos < path_len && path[pos] != '/' && ci < 11) { comp[ci++] = path[pos++]; } /* 不足 11 字符则补空格 */ while (ci < 11) comp[ci++] = ' '; comp[11] = 0; /* 跳过 '/' */ if (pos < path_len && path[pos] == '/') pos++; /* 判断是否为最后一个组件 */ int is_last = (pos >= path_len); if (is_last) { /* 最后一级:查找文件 */ u32 found_clus = 0, found_size = 0; int rc = fat32_find_in_dir(cur_clus, comp, 0, &found_clus, &found_size); if (rc != 0) return -4; if (found_size > sizeof(g_dsk_fat32_filedata)) return -5; /* 读取文件数据 */ u8 *dst = g_dsk_fat32_filedata; u32 remaining = found_size; u32 fc = found_clus; while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) { u32 fc_lba = data_start_sec + (fc - 2) * spc; u32 fc_bytes = spc * 512; if (fc_bytes > remaining) fc_bytes = remaining; u8 *chunk = g_dsk_fat32_cluster; if (api->block->read(0, fc_lba, spc, chunk) != 0) return -6; for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b]; dst += fc_bytes; remaining -= fc_bytes; /* BUG-019: 使用按需 FAT 读取 */ fc = fat32_get_next_cluster(fat_start, fc, bpb, disk); } *out_data = g_dsk_fat32_filedata; *out_size = found_size; return 0; } else { /* 中间级:查找子目录 */ u32 sub_clus = 0, sub_size = 0; int rc = fat32_find_in_dir(cur_clus, comp, 1, &sub_clus, &sub_size); if (rc != 0) return -7; cur_clus = sub_clus; } } return -8; /* 路径为空或无效 */ } /* ---- ELF checks ---- */ static int dsk_check_elf(const void *address, u64 size) { if (!address || size < sizeof(elf64_ehdr)) return -1; const elf64_ehdr *eh = (const elf64_ehdr *)address; if (eh->ident[0] != ELF_MAGIC0 || eh->ident[1] != ELF_MAGIC1 || eh->ident[2] != ELF_MAGIC2 || eh->ident[3] != ELF_MAGIC3) return -2; if (eh->ident[4] != ELFCLASS64 || eh->ident[5] != ELFDATA2LSB) return -3; if (eh->machine != EM_X86_64) return -4; if (eh->type != ET_DYN && eh->type != ET_EXEC) return -5; if (eh->phoff == 0 || eh->phnum == 0 || eh->phentsize < sizeof(elf64_phdr)) return -6; if (!range_ok(eh->phoff, (u64)eh->phnum * eh->phentsize, size)) return -7; return 0; } static int dsk_load_elf_image(const void *address, u64 size, dsk_entry_fn *entry_out) { const elf64_ehdr *eh = (const elf64_ehdr *)address; const u8 *base = (const u8 *)address; u64 min_vaddr = ~0ULL; u64 max_vaddr = 0; u64 max_align = 0x1000; u32 load_count = 0; /* PT_DYNAMIC 的位置(PIE 重定位用) */ u64 dyn_off = 0; u64 dyn_filesz = 0; int has_dyn = 0; for (u16 i = 0; i < eh->phnum; i++) { const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize); if (ph->type == PT_LOAD) { if (ph->filesz > ph->memsz) return -1; if (!range_ok(ph->offset, ph->filesz, size)) return -2; if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr; if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz; if (ph->align > max_align) max_align = ph->align; load_count++; } else if (ph->type == PT_DYNAMIC) { if (!range_ok(ph->offset, ph->filesz, size)) return -2; dyn_off = ph->offset; dyn_filesz = ph->filesz; has_dyn = 1; } } if (load_count == 0 || min_vaddr == ~0ULL || max_vaddr <= min_vaddr) return -3; if (eh->entry < min_vaddr || eh->entry >= max_vaddr) return -4; u64 image_size = utsm_align_up_u64(max_vaddr - min_vaddr, 0x1000); u8 *image = (u8 *)kmem_alloc_aligned(image_size, max_align); if (!image) return -5; memset(image, 0, image_size); for (u16 i = 0; i < eh->phnum; i++) { const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize); if (ph->type != PT_LOAD) continue; u64 dst_off = ph->vaddr - min_vaddr; if (dst_off + ph->memsz > image_size) return -6; memcpy(image + dst_off, base + ph->offset, ph->filesz); } /* PIE 重定位: 处理 PT_DYNAMIC → DT_RELA → R_X86_64_RELATIVE * load_bias = image 实际加载地址 - ELF 预期最小 vaddr * 对每个 R_X86_64_RELATIVE: slot = load_bias + addend */ if (has_dyn && eh->type == ET_DYN) { u64 load_bias = (u64)image - min_vaddr; const elf64_dyn *dyn = (const elf64_dyn *)(base + dyn_off); u64 dyn_count = dyn_filesz / sizeof(elf64_dyn); u64 rela_off = 0, rela_sz = 0, rela_ent = sizeof(elf64_rela); for (u64 d = 0; d < dyn_count; d++) { if (dyn[d].tag == DT_NULL) break; if (dyn[d].tag == DT_RELA) rela_off = dyn[d].val; if (dyn[d].tag == DT_RELASZ) rela_sz = dyn[d].val; if (dyn[d].tag == DT_RELAENT) rela_ent = dyn[d].val; } if (rela_off != 0 && rela_sz != 0 && rela_ent != 0) { /* rela_off 是相对于文件开头的 vaddr,需转换为 image 内偏移 */ if (rela_off >= min_vaddr && rela_off < min_vaddr + image_size) { u64 rela_count = rela_sz / rela_ent; for (u64 r = 0; r < rela_count; r++) { const elf64_rela *rel = (const elf64_rela *)( image + (rela_off - min_vaddr) + r * rela_ent); u32 rtype = (u32)rel->info; if (rtype == R_X86_64_RELATIVE) { if (rel->offset < min_vaddr || rel->offset >= min_vaddr + image_size) continue; u64 *slot = (u64 *)(image + (rel->offset - min_vaddr)); *slot = load_bias + (u64)rel->addend; } } } log_info("[UTSM] PIE reloc applied"); log_hex64("[UTSM] load_bias=", load_bias); log_hex64("[UTSM] rela_count=", rela_sz / rela_ent); } } *entry_out = (dsk_entry_fn)(image + (eh->entry - min_vaddr)); log_hex64("[UTSM] DSK image base=", (u64)image); log_hex64("[UTSM] DSK image size=", image_size); log_hex64("[UTSM] DSK entry=", (u64)*entry_out); return 0; } static void dsk_fill_boot_context(dsk_boot_context *ctx) { memset(ctx, 0, sizeof(*ctx)); ctx->magic = DSK_BOOT_MAGIC; ctx->abi_version = DSK_BOOT_ABI_VERSION; ctx->size = sizeof(*ctx); ctx->flags = DSK_BOOT_FLAG_FROM_UTSM | DSK_BOOT_FLAG_DKM_READY | DSK_BOOT_FLAG_FAT32_PATH; if (g_hhdm_request.response) { ctx->hhdm_offset = g_hhdm_request.response->offset; } if (g_rsdp_request.response) { ctx->rsdp_address = (u64)g_rsdp_request.response->address; } if (g_fb_request.response && g_fb_request.response->framebuffer_count > 0) { struct limine_framebuffer *fb = g_fb_request.response->framebuffers[0]; ctx->framebuffer_address = (u64)fb->address; ctx->framebuffer_width = fb->width; ctx->framebuffer_height = fb->height; ctx->framebuffer_pitch = fb->pitch; ctx->framebuffer_bpp = fb->bpp; } ctx->boot_modules_response = (u64)g_module_request.response; ctx->dkm_kernel_api = (u64)dkm_get_kernel_api(); /* PE 兼容层服务(PE32+ 原生 + PE32 解释器) */ const pe_service *pe = pe_get_service(); if (pe && pe->magic == PE_SERVICE_MAGIC) { ctx->reserved[4] = (u64)pe; } /* Linux 兼容层服务(依赖双内核 park-and-resume + IPC) */ const linux_compat_service *lxc = linux_compat_get_service(); if (lxc && lxc->magic == LINUX_COMPAT_MAGIC) { ctx->reserved[5] = (u64)lxc; } /* Probe 探测缓冲信息(供 shell $probe 命令读取) */ if (g_instr_enabled) { probe_info *pi = (probe_info *)kmem_alloc_aligned(sizeof(probe_info), 8); if (pi) { pi->magic = PROBE_INFO_MAGIC; pi->version = 1; pi->probe_buf_addr = (u64)probe_buf_address(); pi->probe_cap = probe_capacity(); pi->probe_head = probe_head_value(); pi->probe_count = probe_count(); pi->probe_dropped = probe_dropped_count(); pi->instr_enabled = g_instr_enabled; pi->instr_probe_enable = g_instr_probe_enable; ctx->reserved[6] = (u64)pi; ctx->flags |= DSK_BOOT_FLAG_PROBE_INFO; } } u64 rsp; __asm__ volatile ("movq %%rsp, %0" : "=r"(rsp)); ctx->kernel_stack_top = rsp; } int dsk_load_and_jump(void) { log_info("[UTSM] loading DSK"); log_info(DSK_PATH); const void *data = 0; u64 data_size = 0; /* 1) try FAT32 block provider */ int fat32_ok = dsk_load_from_block_fat32(&data, &data_size); if (fat32_ok == 0) { log_info("[UTSM] DSK loaded from FAT32 block provider"); } else { /* 2) fallback: Limine boot module */ log_info("[UTSM] FAT32 block path unavailable; trying Limine module"); struct limine_file *file = dsk_find_module(); if (!file) { log_error("[UTSM] DSK module not found (neither FAT32 nor Limine)"); return -1; } data = file->address; data_size = file->size; log_hex64("[UTSM] DSK module size=", data_size); } int status = dsk_check_elf(data, data_size); if (status != 0) { log_error("[UTSM] DSK ELF rejected"); log_hex64("[UTSM] DSK ELF status=", (u64)(i64)status); return status; } dsk_entry_fn entry = 0; status = dsk_load_elf_image(data, data_size, &entry); if (status != 0) { log_error("[UTSM] DSK load failed"); log_hex64("[UTSM] DSK load status=", (u64)(i64)status); return status; } dsk_boot_context *ctx = (dsk_boot_context *)kmem_alloc_aligned(sizeof(dsk_boot_context), 16); if (!ctx) { log_error("[UTSM] DSK context allocation failed"); return -1; } dsk_fill_boot_context(ctx); /* 实机安全: 跳转前 cli → mask PIC → 重置 IDT → NMI off。 * DSK 加载的 ELF 映像可能覆盖 UTSM 的驱动代码段, * 如果 UTSM 注册的 IRQ handler 所在内存被覆盖, * 中断触发时跳转到无效地址 → 三重故障重启。 * * P0 修复: 1) 先 cli 禁用中断,消除 PIC mask 两步操作之间的中断竞争窗口 * 2) mask PIC 确保不会有硬件中断到达 * 3) 设置 LAPIC TPR=0xFF 屏蔽所有通过 IOAPIC 路由的中断 * 4) 将 IDT 所有条目替换为安全 halt stub,防止 DSK 运行时 * 过期的 UTSM handler 被异常/spurious IRQ 触发 * 5) 禁用 NMI */ { extern void outb(u16 port, u8 value); extern u8 inb(u16 port); /* 1) 先禁用中断——关键修复!原来缺少此步, * outb(0xA1,0xFF) 和 outb(0x21,0xFF) 之间有中断窗口 */ __asm__ volatile("cli"); /* 2) mask PIC — 此时 IF=0,安全操作 */ outb(0xA1, 0xFF); /* PIC2: mask IRQ8-15 */ outb(0x21, 0xFF); /* PIC1: mask IRQ0-7 */ /* 3) BUG-020 修复: 设置 LAPIC TPR=0xFF 屏蔽所有 IOAPIC 路由中断。 * 实机多核平台中断通常经 IOAPIC 而非 PIC,PIC mask 不影响 * IOAPIC redirection entry。通过 IA32_APIC_BASE MSR 读取 LAPIC * 基地址,写入 TPR(偏移 0x80)=0xFF 可在 LAPIC 层面屏蔽所有 * 可屏蔽中断(低于 0xFF 优先级),确保 DSK 运行期间不会有 * IOAPIC 路由的 IRQ 到达。HHDM 映射后 LAPIC MMIO 可访问。 */ { u32 msr_lo, msr_hi; __asm__ volatile("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(0x1B)); u64 lapic_phys = ((u64)msr_hi << 32) | (msr_lo & 0xFFFFF000ULL); if (lapic_phys && (msr_lo & (1 << 11))) { /* LAPIC 全局启用时(bit 11)才操作 TPR */ extern volatile struct limine_hhdm_request g_hhdm_request; u64 hhdm_off = g_hhdm_request.response ? g_hhdm_request.response->offset : 0; if (hhdm_off) { u64 lapic_vaddr = lapic_phys + hhdm_off; *(volatile u32 *)(lapic_vaddr + 0x80) = 0xFF; } } } /* 4) BUG-20260801-005: 换装 DSK 诊断 IDT(替代原静默 halt_all)。 * vector 0-31 → UTSM isr_stub(idt_handler 打完整异常现场后 * 安全停机),vector 32-255 保持 halt stub 防御 spurious IRQ7/15。 * SAS-R0 下 UTSM .text 常驻内存,DSK 阶段异常投递路径已验证 * 可用(BUG-20260729-013 登记行为);原 halt_all 把 #PF/#GP * 无声吞掉,DSK 阶段零诊断。 */ extern void idt_install_dsk_diag(void); idt_install_dsk_diag(); /* 5) NMI off */ outb(0x70, inb(0x70) | 0x80); } log_hex64("[UTSM] DSK context magic=", ctx->magic); log_hex64("[UTSM] DSK context api=", ctx->dkm_kernel_api); log_hex64("[UTSM] DSK context fb=", ctx->framebuffer_address); log_info("[UTSM] jumping to DSK"); entry(ctx); log_error("[UTSM] DSK returned unexpectedly"); return -1; }