/* DSK Main Kernel — boot entry, FAT32 firstInit check, ELF loader */ #include "../UTSM/include/utsm/dsk.h" #include "port.h" /* Embedded Logo.png RGBA data (auto-generated by png_to_rgba.py) */ #include "logo_data.c" /* Embedded ASCII bitmap font (Consolas 18px grayscale, 11x18 cell) */ #include "../firstInit/ascii_bitmaps.c" #define COM1 0x3F8 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef long long i64; typedef int (*block_read_fn)(u32 index, u64 lba, u32 count, void *buf); typedef int (*block_write_fn)(u32 index, u64 lba, u32 count, const void *buf); /* freestanding 无 stddef.h,本地提供 offsetof */ #ifndef offsetof #define offsetof(type, member) __builtin_offsetof(type, member) #endif /* ---- BUG-021 修复: kernel_api 镜像结构体 + 编译期偏移校验 ---- * DSK 独立编译不含 dkm_kernel_api 定义,为避免硬偏移脆蠕性, * 在此定义镜像结构体并用 _Static_assert 校验 block 字段偏移 * 与 dkm.h 中 dkm_kernel_api.block (0xA8) 一致。 */ typedef struct dsk_block_api_mirror { void *pad0; void *pad1; /* register_device, device_count */ block_read_fn read; block_write_fn write; } dsk_block_api_mirror; typedef struct dsk_kernel_api_mirror { u32 version; u32 size; u64 feature_bits; const void *log; const void *mem; const void *utsm; const void *irq; const void *pci; const void *dma; const void *vfs; const void *net; const void *timer; const void *drr; const void *rsdp_address; const void *fb_address; u64 fb_width; u64 fb_height; u64 fb_pitch; u16 fb_bpp; u16 _pad_bpp; const void *boot_modules_response; int (*irq_register)(u8 irq, void *handler); u64 hhdm_offset; const dsk_block_api_mirror *block; /* 必须在偏移 0xA8 */ const void *mmio; void *(*mm_map_mmio)(u64 phys, u64 size); void (*mm_unmap_mmio)(void *virt, u64 size); } dsk_kernel_api_mirror; _Static_assert(offsetof(dsk_kernel_api_mirror, block) == 0xA8, "dsk_kernel_api_mirror.block offset must be 0xA8 (matching dkm_kernel_api)"); _Static_assert(offsetof(dsk_block_api_mirror, read) == 16, "dsk_block_api_mirror.read offset must be 16 (matching dkm_block_api)"); static void sputc(char c) { for(unsigned i=0;i<100000;i++){if(inb(COM1+5)&0x20)break;} outb(COM1,(u8)c); } static void swrite(const char *s) { while(*s){if(*s=='\n')sputc('\r');sputc(*s++);} } static void logl(const char *s) { swrite(s); swrite("\n"); } static void logh(const char *p, u64 v) { static const char h[]="0123456789abcdef"; char b[19]; int i=0; b[i++]='0';b[i++]='x'; for(int j=15;j>=0;j--)b[i++]=h[(v>>(j*4))&0xf];b[i]=0; swrite(p);swrite(b);swrite("\n"); } /* ---- DSK 插桩: 轻量级 TSC 计时 (forward-declared, rdtsc_dsk defined later) ---- */ static u64 rdtsc_dsk(void); #define DSK_TS_DECL(name) static u64 name##_ts = 0 #define DSK_TS_BEGIN(name) do { name##_ts = rdtsc_dsk(); } while(0) #define DSK_TS_END(name, label) do { \ if (g_tsc_per_ms) { \ u64 _d = rdtsc_dsk() - name##_ts; \ u64 _ms = _d / g_tsc_per_ms; \ logl("[DSK:TS] " label); logh(" elapsed_ms=", _ms); \ } \ } while(0) /* ---- DSK 插桩: 操作计数器 ---- */ #define DSK_STAT_DECL(name) static u32 name##_count = 0 #define DSK_STAT_INC(name) do { name##_count++; } while(0) static void *memset_dsk(void *d, int c, u64 n) { u8 *p=(u8*)d; while(n--)*p++=(u8)c; return d; } static void *memcpy_dsk(void *d, const void *s, u64 n) { u8 *dd=(u8*)d; const u8 *ss=(const u8*)s; while(n--)*dd++=*ss++; return d; } typedef struct __attribute__((packed)) { u8 jmp[3]; char oem[8]; u16 bps; u8 spc; u16 rsvd; u8 fc; u16 root_ent; u16 ts16; u8 media; u16 spf16; u16 spt; u16 heads; u32 hidden; u32 ts32; u32 spf; u16 flags; u16 ver; u32 root_clus; u16 fsi; u16 bkboot; u8 res[12]; u8 drv; u8 ntfl; u8 sig; u32 ser; char lbl[11]; char typ[8]; u8 code[420]; u16 boot_sig; } fat32_bpb; typedef struct __attribute__((packed)) { char name[11]; u8 attr; u8 ntr; u8 ctenth; u16 ctime; u16 cdate; u16 adate; u16 chigh; u16 wtime; u16 wdate; u16 clow; u32 fsize; } fat32_de; static u32 r32(const u8 *p) { return (u32)p[0]|((u32)p[1]<<8)|((u32)p[2]<<16)|((u32)p[3]<<24); } static u16 r16(const u8 *p) { return (u16)p[0]|((u16)p[1]<<8); } static int neq11(const char *a, const char *b) { for(int i=0;i<11;i++) if(a[i]!=b[i]) return 0; return 1; } static u64 g_fb_addr, g_fb_w, g_fb_h, g_fb_p; static block_read_fn g_block_read; static block_write_fn g_block_write; static u64 g_tsc_per_ms = 0; static u8 g_disk[131072]; static u8 g_cluster[4096]; static u8 g_fdata[2097152]; /* 2MB file data buffer (与 UTSM 端一致) */ /* BUG-019 修复: FAT 按需扇区读取缓冲区(仅 512 字节) */ static u8 g_fat_sec[512]; static u8 g_milestone_buf[4096]; /* milestone write cluster buffer */ DSK_STAT_DECL(fat32_read); DSK_STAT_DECL(fat32_write); DSK_STAT_DECL(elf_load); DSK_STAT_DECL(mod_schedule); static int fat32_read_sectors(u32 lba, u32 count, u8 *out) { DSK_STAT_INC(fat32_read); return g_block_read ? g_block_read(0,lba,count,out) : -1; } static int fat32_write_sectors(u32 lba, u32 count, const u8 *buf) { DSK_STAT_INC(fat32_write); return g_block_write ? g_block_write(0,lba,count,buf) : -1; } /* BUG-019 修复: 按需读取 FAT 扇区获取下一个簇号。 * 如果 FAT 条目在预读缓冲区内直接读取; * 否则只读取包含该条目的单个 FAT 扇区(512 字节)。 */ static u32 fat32_get_next_cluster(u32 fat_byte_off, u32 clus, u32 fat_rsvd_sec) { u32 ent_off = fat_byte_off + clus * 4; /* 情况 1: 在预读缓冲区内 */ if (ent_off + 4 <= sizeof(g_disk)) { return r32(g_disk + ent_off) & 0x0FFFFFFF; } /* 情况 2: 超出预读缓冲区——按需读取单扇区 */ u32 fat_byte_in_fat = clus * 4; u32 sec_idx = fat_byte_in_fat / 512; u32 off_in_sec = fat_byte_in_fat % 512; u32 sec_lba = fat_rsvd_sec + sec_idx; if (fat32_read_sectors(sec_lba, 1, g_fat_sec) != 0) { logl("[DSK] FAT32: on-demand FAT sector read failed"); logh("[DSK] FAT32: sec_lba=", (u64)sec_lba); return 0x0FFFFFFF; } return r32(g_fat_sec + off_in_sec) & 0x0FFFFFFF; } /* ---- DSK 内嵌 INI 解析器 ---- */ typedef struct { char section[32]; char key[32]; char value[64]; } dsk_ini_entry; typedef struct { dsk_ini_entry entries[64]; u32 count; } dsk_ini_config; static int dsk_ini_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 dsk_ini_atoi(const char *s) { int neg=0, v=0; if(!s) return 0; while(*s==' '||*s=='\t') s++; if(*s=='-'){neg=1;s++;} while(*s>='0'&&*s<='9'){v=v*10+(*s-'0');s++;} return neg?-v:v; } static int dsk_ini_parse_bool(const char *s) { if(!s) return -1; if(s[0]=='1') return 1; if(s[0]=='0') return 0; if(dsk_ini_streq(s,"true")) return 1; if(dsk_ini_streq(s,"false")) return 0; return -1; } static int dsk_ini_parse(const char *text, u32 size, dsk_ini_config *cfg) { if(!text||!cfg) return -1; cfg->count = 0; char cur_sec[32]; for(int i=0;i<32;i++) cur_sec[i]=0; u32 pos = 0; while(pos < size) { while(pos=size) break; char c = text[pos]; if(c=='\n'){pos++;continue;} if(c=='#'||c==';'){while(poscount>=64) break; dsk_ini_entry *e = &cfg->entries[cfg->count]; u32 ki=0; while(poskey[ki++]=text[pos++]; e->key[ki]=0; while(pos=size||text[pos]!='='){while(posvalue[vi++]=text[pos++]; while(vi>0&&(e->value[vi-1]==' '||e->value[vi-1]=='\t')) vi--; e->value[vi]=0; for(int i=0;i<32;i++) e->section[i]=cur_sec[i]; cfg->count++; } return 0; } static const char *dsk_ini_get(const dsk_ini_config *cfg, const char *sec, const char *key) { if(!cfg||!sec||!key) return 0; for(u32 i=0;icount;i++) if(dsk_ini_streq(cfg->entries[i].section,sec)&&dsk_ini_streq(cfg->entries[i].key,key)) return cfg->entries[i].value; return 0; } __attribute__((unused)) static int dsk_ini_get_int(const dsk_ini_config *cfg, const char *sec, const char *key, int def) { const char *v=dsk_ini_get(cfg,sec,key); if(!v||v[0]==0) return def; return dsk_ini_atoi(v); } static int dsk_ini_get_bool(const dsk_ini_config *cfg, const char *sec, const char *key, int def) { const char *v=dsk_ini_get(cfg,sec,key); if(!v||v[0]==0) return def; int b=dsk_ini_parse_bool(v); return (b>=0)?b:def; } /* ---- DSK FAT32 子目录遍历 ---- */ /* 在指定起始 cluster 的目录中查找 name11。 * is_dir=1 只匹配子目录,is_dir=0 只匹配文件。 * 注意:需先调用 fat32_read_sectors(0,256,g_disk) 确保 BPB 缓冲可用。 */ static int fat32_find_in_dir(u32 start_clus, const char *name11, int is_dir, u32 *out_clus, u32 *out_size) { const fat32_bpb *bpb = (const fat32_bpb *)g_disk; if(bpb->boot_sig!=0xAA55||bpb->bps!=512) return -2; u32 data_lba = bpb->rsvd + (u32)bpb->fc * bpb->spf; u32 fat_byte_off = bpb->rsvd * 512; u32 spc = bpb->spc; u32 clus = start_clus; while(clus>=2 && clus<0x0FFFFFF8) { u32 lba = data_lba + (clus-2)*spc; const u8 *cb; if((u64)lba*512+(u64)spc*512<=256ULL*512) cb = g_disk + (u64)lba*512; else { if(fat32_read_sectors(lba,8,g_cluster)!=0) return -3; cb = g_cluster; } const fat32_de *dir = (const fat32_de *)cb; for(u32 e=0; e*32rsvd); } return -4; } /* 按 '/' 分隔的 8.3 路径读取文件(如 "SYSTEM /DESHAB64 /FUCK ")。 * 需先调用 fat32_read_sectors(0,256,g_disk) 确保 BPB 可用。 */ static int fat32_read_path(const char *path, u8 **out_data, u32 *out_size) { DSK_TS_DECL(fat32_path_read); DSK_TS_BEGIN(fat32_path_read); const fat32_bpb *bpb = (const fat32_bpb *)g_disk; if(bpb->boot_sig!=0xAA55||bpb->bps!=512) { logl("[DSK] fat32_read_path: bad BPB"); return -2; } u32 fat_byte_off = bpb->rsvd*512; u32 data_lba = bpb->rsvd + (u32)bpb->fc*bpb->spf; u32 spc = bpb->spc; u32 pos=0, path_len=0; while(path[path_len]) path_len++; u32 cur_clus = bpb->root_clus; while(pos=path_len); if(is_last) { u32 found_clus=0, found_size=0; if(fat32_find_in_dir(cur_clus,comp,0,&found_clus,&found_size)!=0) { logl("[DSK] fat32_read_path: file not found: "); swrite(path); swrite("\n"); return -4; } if(found_size>sizeof(g_fdata)) { logh("[DSK] fat32_read_path: file too large size=", (u64)found_size); return -5; } u8 *dst=g_fdata; u32 remaining=found_size; u32 fc=found_clus; while(fc>=2&&fc<0x0FFFFFF8&&remaining>0) { u32 fc_lba=data_lba+(fc-2)*spc; u32 fc_bytes=spc*512; if(fc_bytes>remaining) fc_bytes=remaining; const u8 *fb; if((u64)fc_lba*512+(u64)spc*512<=256ULL*512) fb=g_disk+(u64)fc_lba*512; else { if(fat32_read_sectors(fc_lba,8,g_cluster)!=0) { logh("[DSK] fat32_read_path: data cluster read failed lba=", (u64)fc_lba); return -6; } fb=g_cluster; } for(u32 b=0;brsvd); } *out_data=g_fdata; *out_size=found_size; DSK_TS_END(fat32_path_read, "fat32_read_path"); return 0; } else { u32 sub_clus=0, sub_size=0; if(fat32_find_in_dir(cur_clus,comp,1,&sub_clus,&sub_size)!=0) { logl("[DSK] fat32_read_path: dir not found in path: "); swrite(path); swrite("\n"); return -7; } cur_clus=sub_clus; } } DSK_TS_END(fat32_path_read, "fat32_read_path (failed)"); return -8; } /* Navigate a '/'-separated 8.3 path to find a directory cluster. * Returns the cluster of the final directory, or 0 on failure. * Requires g_disk to contain a valid BPB. */ static u32 fat32_find_dir_cluster(const char *path) { const fat32_bpb *bpb = (const fat32_bpb *)g_disk; if (bpb->boot_sig != 0xAA55 || bpb->bps != 512) return 0; u32 pos = 0, path_len = 0; while (path[path_len]) path_len++; u32 cur_clus = bpb->root_clus; while (pos < path_len) { char comp[12]; u32 ci = 0; while (pos < path_len && path[pos] != '/' && ci < 11) comp[ci++] = path[pos++]; while (ci < 11) comp[ci++] = ' '; comp[11] = 0; if (pos < path_len && path[pos] == '/') pos++; u32 sub_clus = 0, sub_size = 0; if (fat32_find_in_dir(cur_clus, comp, 1, &sub_clus, &sub_size) != 0) return 0; cur_clus = sub_clus; } return cur_clus; } #define EI_MAG0 0x7f #define ELFCLASS64 2 #define ELFDATA2LSB 1 #define EM_X86_64 62 #define PT_LOAD 1 #define PT_DYNAMIC 2 #define DT_RELA 7 #define DT_RELASZ 8 #define DT_RELAENT 9 #define R_X86_64_RELATIVE 8 typedef struct { u8 ident[16]; u16 type,machine; u32 ver; u64 entry,phoff,shoff; u32 flags; u16 ehsize,phentsize,phnum,shentsize,shnum,shstrndx; } elf64_ehdr; typedef struct { u32 type,flags; u64 offset,vaddr,paddr,filesz,memsz,align; } elf64_phdr; typedef struct { i64 tag; u64 val; } elf64_dyn; typedef struct { u64 offset; u64 info; i64 addend; } elf64_rela; #define BG_TOP 0xFFC8E0F0u #define BG_BOTTOM 0xFF49306Fu #define BG_MID 0xFF8888B0u /* ---- TSC-based timing ---- */ static u64 rdtsc_dsk(void) { u32 lo, hi; __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi)); return ((u64)hi << 32) | lo; } static void tsc_calibrate_dsk(void) { outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */ outb(0x40, 0x7c); /* 11932 low = ~10ms */ outb(0x40, 0x2e); /* 11932 high */ u64 tsc_start = rdtsc_dsk(); u16 prev = 0; u64 loops = 0; for (;;) { outb(0x43, 0x00); u16 cur = (u16)inb(0x40) | ((u16)inb(0x40) << 8); if (cur > prev && loops > 10) break; prev = cur; loops++; } u64 tsc_end = rdtsc_dsk(); g_tsc_per_ms = (tsc_end - tsc_start) / 10; logh("[DSK] tsc_per_ms=", g_tsc_per_ms); } static u32 blend_color(u32 c1, u32 c2, u32 a) { u32 na = 256 - a; u32 r = ((c1 & 0xFF) * na + (c2 & 0xFF) * a) >> 8; u32 g = (((c1 >> 8) & 0xFF) * na + ((c2 >> 8) & 0xFF) * a) >> 8; u32 b = (((c1 >> 16) & 0xFF) * na + ((c2 >> 16) & 0xFF) * a) >> 8; return 0xFF000000 | (b << 16) | (g << 8) | r; } static u32 dsk_bg_at_y(i64 y) { if (g_fb_h <= 1) return BG_TOP; if (y < 0) y = 0; if ((u64)y >= g_fb_h) y = (i64)g_fb_h - 1; return blend_color(BG_TOP, BG_BOTTOM, (u32)(((u64)y * 255ULL) / (g_fb_h - 1))); } static void dsk_fill_gradient_rect(u32 *fb, i64 x, i64 y, i64 w, i64 h) { for (i64 r = 0; r < h; r++) { i64 yy = y + r; if (yy < 0 || (u64)yy >= g_fb_h) continue; u32 color = dsk_bg_at_y(yy); u32 *line = (u32 *)((u8 *)fb + (u64)yy * g_fb_p); for (i64 c = 0; c < w; c++) { i64 xx = x + c; if (xx < 0 || (u64)xx >= g_fb_w) continue; line[(u64)xx] = color; } } } /* ---- Spinner animation (removed — replaced by static Logo.png display) ---- */ /* ---- Logo rendering: center RGBA image with alpha blending on gradient bg ---- * g_logo_rgba / g_logo_w / g_logo_h are from logo_data.c (included above). * Source pixel format: RGBA8888 (R at byte 0, G byte 1, B byte 2, A byte 3). * Framebuffer format: UEFI BGRX — u32 = 0xAARRGGBB * bits 0-7 = B, bits 8-15 = G, bits 16-23 = R, bits 24-31 = A/X */ static void dsk_draw_logo(u32 *fb) { /* Center the logo on screen */ i64 ox = ((i64)g_fb_w - g_logo_w) / 2; i64 oy = ((i64)g_fb_h - g_logo_h) / 2; for (int ly = 0; ly < g_logo_h; ly++) { i64 fy = oy + ly; if (fy < 0 || (u64)fy >= g_fb_h) continue; u32 *line = (u32 *)((u8 *)fb + (u64)fy * g_fb_p); for (int lx = 0; lx < g_logo_w; lx++) { i64 fx = ox + lx; if (fx < 0 || (u64)fx >= g_fb_w) continue; /* Read RGBA pixel from embedded data */ int idx = (ly * g_logo_w + lx) * 4; u8 r = g_logo_rgba[idx + 0]; u8 g = g_logo_rgba[idx + 1]; u8 b = g_logo_rgba[idx + 2]; u8 a = g_logo_rgba[idx + 3]; if (a == 0) continue; /* fully transparent: skip */ if (a == 255) { /* fully opaque: BGRX = 0xFF000000 | (R<<16) | (G<<8) | B */ line[(u64)fx] = 0xFF000000u | ((u32)r << 16) | ((u32)g << 8) | b; } else { /* alpha blend with background (BGRX channel order) */ u32 bg = line[(u64)fx]; u32 na = 256 - a; u32 ob = (((bg & 0xFF) * na + (u32)b * a) >> 8) & 0xFF; u32 og = ((((bg >> 8) & 0xFF) * na + (u32)g * a) >> 8) & 0xFF; u32 or = ((((bg >> 16)& 0xFF) * na + (u32)r * a) >> 8) & 0xFF; line[(u64)fx] = 0xFF000000u | (or << 16) | (og << 8) | ob; } } } } /* ---- Text rendering: ASCII bitmap font on framebuffer ---- * Uses g_ascii[95][11*18] from ascii_bitmaps.c (Consolas 18px). * Framebuffer format: BGRX — u32 = 0xAARRGGBB. */ static void dsk_draw_char(u32 *fb, char ch, i64 x, i64 y, u32 fg) { u32 idx = (u32)(ch - ' '); if (idx > 94) idx = 0; const u8 *glyph = g_ascii[idx]; for (int r = 0; r < g_ascii_h; r++) { i64 yy = y + r; if (yy < 0 || (u64)yy >= g_fb_h) continue; u32 *line = (u32 *)((u8 *)fb + (u64)yy * g_fb_p); for (int c = 0; c < g_ascii_w; c++) { u8 a = glyph[r * g_ascii_w + c]; if (a == 0) continue; i64 xx = x + c; if (xx < 0 || (u64)xx >= g_fb_w) continue; if (a == 255) { line[(u64)xx] = fg; } else { /* alpha blend with background */ u32 bg = line[(u64)xx]; u32 na = 256 - a; u32 ob = (((bg & 0xFF) * na + ((fg & 0xFF) ) * a) >> 8) & 0xFF; u32 og = ((((bg >> 8) & 0xFF) * na + (((fg >> 8) & 0xFF)) * a) >> 8) & 0xFF; u32 or = ((((bg >> 16)& 0xFF) * na + (((fg >> 16)& 0xFF)) * a) >> 8) & 0xFF; line[(u64)xx] = 0xFF000000u | (or << 16) | (og << 8) | ob; } } } } static void dsk_draw_string(u32 *fb, const char *s, i64 x, i64 y, u32 fg, int spacing) { i64 cx = x; while (*s) { dsk_draw_char(fb, *s, cx, y, fg); cx += spacing; s++; } } static int fat32_find_entry(const u8 *clus, u32 clus_sectors, const char *target, u32 *out_clus, u32 *out_size) { const fat32_de *dir = (const fat32_de *)clus; for (u32 e=0; e*32 < clus_sectors*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 (neq11(dir[e].name, target)) { *out_clus = r16((const u8*)&dir[e].clow) | ((u32)r16((const u8*)&dir[e].chigh) << 16); *out_size = dir[e].fsize; return 0; } } return -1; } /* find a single file in root directory by 11-char 8.3 name (avoids PIE pointer reloc) */ static int fat32_read_root_file(const char *name11, u8 **out_data, u32 *out_size) { u8 *disk = g_disk; DSK_TS_DECL(fat32_root_read); DSK_TS_BEGIN(fat32_root_read); logl("[DSK] fat32 reading 256 sectors from LBA 0"); int st = fat32_read_sectors(0, 256, disk); logh("[DSK] fat32 read_sectors rc=", (u64)(i64)st); if (st != 0) { logl("[DSK] fat32_read_root_file: BPB read failed"); return -1; } const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bps != 512) { logl("[DSK] fat32_read_root_file: bad BPB sig/bps"); return -2; } if (bpb->spf == 0 || bpb->root_clus < 2) { logh("[DSK] fat32_read_root_file: bad spf/root_clus spf=", (u64)bpb->spf); return -3; } u32 data_lba = bpb->rsvd + (u32)bpb->fc * bpb->spf; u32 fat_byte_off = bpb->rsvd * 512; u32 spc = bpb->spc; logh("[DSK] fat32 data_lba=", data_lba); /* walk root directory cluster chain */ u32 clus = bpb->root_clus; u32 found_clus = 0, found_size = 0; int found = 0; while (clus >= 2 && clus < 0x0FFFFFF8 && !found) { u32 lba = data_lba + (clus - 2) * spc; const u8 *cb; if ((u64)lba * 512 + (u64)spc * 512 <= 256ULL * 512) cb = disk + (u64)lba * 512; else { if (fat32_read_sectors(lba, 8, g_cluster) != 0) { logh("[DSK] fat32_read_root_file: dir cluster read failed lba=", (u64)lba); return -4; } cb = g_cluster; } if (fat32_find_entry(cb, spc, name11, &found_clus, &found_size) == 0) { found = 1; break; } /* BUG-019: 使用按需 FAT 读取 */ clus = fat32_get_next_cluster(fat_byte_off, clus, bpb->rsvd); } if (!found) { logl("[DSK] fat32 entry not found: "); swrite(name11); swrite("\n"); return -5; } logh("[DSK] fat32 found_clus=", found_clus); logh("[DSK] fat32 found_size=", found_size); if (found_size > sizeof(g_fdata)) { logh("[DSK] fat32_read_root_file: file too large size=", (u64)found_size); return -6; } u8 *dst = g_fdata; u32 remaining = found_size; u32 fc = found_clus; while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) { u32 fc_lba = data_lba + (fc - 2) * spc; u32 fc_bytes = spc * 512; if (fc_bytes > remaining) fc_bytes = remaining; const u8 *fb; if ((u64)fc_lba * 512 + (u64)spc * 512 <= 256ULL * 512) fb = disk + (u64)fc_lba * 512; else { if (fat32_read_sectors(fc_lba, 8, g_cluster) != 0) { logh("[DSK] fat32_read_root_file: data cluster read failed lba=", (u64)fc_lba); return -7; } fb = g_cluster; } for (u32 b = 0; b < fc_bytes; b++) dst[b] = fb[b]; dst += fc_bytes; remaining -= fc_bytes; /* BUG-019: 使用按需 FAT 读取 */ fc = fat32_get_next_cluster(fat_byte_off, fc, bpb->rsvd); } *out_data = g_fdata; *out_size = found_size; DSK_TS_END(fat32_root_read, "fat32_read_root_file"); logl("[DSK] fat32 file read done"); return 0; } /* Write a file to the FAT32 root directory by 11-char 8.3 name. * If the file exists, its content is replaced. If not, a new entry is created. * Uses g_disk (256-sector buffer) which must already contain the BPB+FAT+root. * Returns 0 on success. */ static int fat32_write_root_file(const char *name11, const u8 *data, u32 size) { u8 *disk = g_disk; const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bps != 512) return -1; u32 spc = bpb->spc; u32 fat_lba = bpb->rsvd; u32 fat_sectors = bpb->spf; u32 data_lba = bpb->rsvd + (u32)bpb->fc * bpb->spf; u32 fat_byte_off = bpb->rsvd * 512; u32 root_clus = bpb->root_clus; u32 cluster_bytes = spc * 512; /* 1. Re-read BPB+FAT to ensure g_disk is fresh */ if (fat32_read_sectors(0, 256, disk) != 0) return -2; /* 2. Find file entry in root directory — scan ALL clusters in FAT chain */ u32 cur_clus = root_clus; int free_entry = -1; u32 free_clus = 0; /* cluster number where free entry was found */ u32 existing_clus = 0; int found = 0; u32 found_clus = 0; /* cluster number where existing file was found */ while (cur_clus >= 2 && cur_clus < 0x0FFFFFF8) { u32 clus_lba = data_lba + (cur_clus - 2) * spc; int in_buf = ((u64)clus_lba * 512 + cluster_bytes <= 256ULL * 512); u8 *buf; if (in_buf) { buf = disk + (u64)clus_lba * 512; } else { if (fat32_read_sectors(clus_lba, spc, g_milestone_buf) != 0) { logl("[DSK] fat32 write: root dir cluster read failed"); break; } buf = g_milestone_buf; } u32 me = cluster_bytes / 32; fat32_de *d = (fat32_de *)buf; int cluster_done = 0; for (u32 e = 0; e < me; e++) { if (d[e].name[0] == 0) { if (free_entry < 0) { free_entry = (int)e; free_clus = cur_clus; } cluster_done = 1; break; } if ((u8)d[e].name[0] == 0xE5) { if (free_entry < 0) { free_entry = (int)e; free_clus = cur_clus; } continue; } if (d[e].attr == 0x0F) continue; if (d[e].attr & 0x08) continue; if (neq11(d[e].name, name11)) { existing_clus = r16((const u8*)&d[e].clow) | ((u32)r16((const u8*)&d[e].chigh) << 16); found = 1; found_clus = cur_clus; cluster_done = 1; break; } } if (cluster_done) break; cur_clus = fat32_get_next_cluster(fat_byte_off, cur_clus, bpb->rsvd); } /* Re-read the active cluster (the one we'll modify) into root_buf */ u32 active_clus = found ? found_clus : free_clus; u32 root_lba; int root_in_buffer; u8 *root_buf; fat32_de *dir; u32 max_entries = cluster_bytes / 32; if (active_clus >= 2) { root_lba = data_lba + (active_clus - 2) * spc; root_in_buffer = ((u64)root_lba * 512 + cluster_bytes <= 256ULL * 512); if (root_in_buffer) { root_buf = disk + (u64)root_lba * 512; } else { if (fat32_read_sectors(root_lba, spc, g_milestone_buf) != 0) { logl("[DSK] fat32 write: root dir re-read failed"); return -10; } root_buf = g_milestone_buf; } dir = (fat32_de *)root_buf; } else { root_lba = 0; root_in_buffer = 0; root_buf = 0; dir = 0; } /* 3. Allocate or reuse clusters */ u32 bytes_needed = size > 0 ? size : 1; u32 clusters_needed = (bytes_needed + cluster_bytes - 1) / cluster_bytes; u32 first_clus = 0; u32 prev_clus = 0; if (found && existing_clus >= 2) { /* Reuse existing chain, extend or shrink as needed */ first_clus = existing_clus; u32 cur = existing_clus; u32 count = 0; while (cur >= 2 && cur < 0x0FFFFFF8 && count < clusters_needed) { prev_clus = cur; u32 fo = fat_byte_off + cur * 4; if (fo + 4 > sizeof(g_disk)) break; cur = r32(disk + fo) & 0x0FFFFFFF; count++; } /* If we need more clusters, allocate them */ while (count < clusters_needed) { /* Find a free cluster in FAT */ u32 newc = 0; for (u32 c = 2; c < (fat_sectors * 512) / 4; c++) { u32 fo = fat_byte_off + c * 4; if (fo + 4 > sizeof(g_disk)) break; if ((r32(disk + fo) & 0x0FFFFFFF) == 0) { newc = c; break; } } if (newc == 0) { logl("[DSK] fat32 write: no free clusters"); return -3; } /* BUG-20260730: Mark newly allocated cluster as EOC immediately to prevent re-allocation */ { u32 nfo = fat_byte_off + newc * 4; if (nfo + 4 <= sizeof(g_disk)) { disk[nfo] = 0xF8; disk[nfo+1] = 0xFF; disk[nfo+2] = 0xFF; disk[nfo+3] = (disk[nfo+3] & 0xF0) | 0x0F; } } /* Link previous cluster to new */ u32 pfo = fat_byte_off + prev_clus * 4; if (pfo + 4 <= sizeof(g_disk)) { disk[pfo] = (u8)(newc & 0xFF); disk[pfo+1] = (u8)((newc >> 8) & 0xFF); disk[pfo+2] = (u8)((newc >> 16) & 0xFF); disk[pfo+3] = (disk[pfo+3] & 0xF0) | (u8)((newc >> 24) & 0x0F); } prev_clus = newc; count++; } /* BUG-20260730: Terminate the chain, saving original next pointer before overwriting with EOC */ if (prev_clus >= 2) { u32 fo = fat_byte_off + prev_clus * 4; u32 original_next = 0; if (fo + 4 <= sizeof(g_disk)) { original_next = r32(disk + fo) & 0x0FFFFFFF; disk[fo] = 0xF8; disk[fo+1] = 0xFF; disk[fo+2] = 0xFF; disk[fo+3] = (disk[fo+3] & 0xF0) | 0x0F; } /* Free excess clusters from the old chain using saved pointer */ u32 next = original_next; while (next >= 2 && next < 0x0FFFFFF8) { u32 nfo = fat_byte_off + next * 4; u32 nn = 0; if (nfo + 4 <= sizeof(g_disk)) nn = r32(disk + nfo) & 0x0FFFFFFF; if (nfo + 4 <= sizeof(g_disk)) { disk[nfo] = 0; disk[nfo+1] = 0; disk[nfo+2] = 0; disk[nfo+3] = disk[nfo+3] & 0xF0; } next = nn; } } } else { /* Allocate new clusters */ if (free_entry < 0) { logl("[DSK] fat32 write: no free dir entry"); return -4; } for (u32 i = 0; i < clusters_needed; i++) { u32 newc = 0; for (u32 c = 2; c < (fat_sectors * 512) / 4; c++) { u32 fo = fat_byte_off + c * 4; if (fo + 4 > sizeof(g_disk)) break; if ((r32(disk + fo) & 0x0FFFFFFF) == 0) { newc = c; break; } } if (newc == 0) { logl("[DSK] fat32 write: no free clusters"); return -3; } /* BUG-20260730: Mark newly allocated cluster as EOC immediately to prevent re-allocation */ { u32 nfo = fat_byte_off + newc * 4; if (nfo + 4 <= sizeof(g_disk)) { disk[nfo] = 0xF8; disk[nfo+1] = 0xFF; disk[nfo+2] = 0xFF; disk[nfo+3] = (disk[nfo+3] & 0xF0) | 0x0F; } } if (i == 0) first_clus = newc; if (prev_clus >= 2) { u32 pfo = fat_byte_off + prev_clus * 4; if (pfo + 4 <= sizeof(g_disk)) { disk[pfo] = (u8)(newc & 0xFF); disk[pfo+1] = (u8)((newc >> 8) & 0xFF); disk[pfo+2] = (u8)((newc >> 16) & 0xFF); disk[pfo+3] = (disk[pfo+3] & 0xF0) | (u8)((newc >> 24) & 0x0F); } } prev_clus = newc; } /* Terminate chain */ /* BUG-20260730: Terminate chain preserving high 4 bits */ if (prev_clus >= 2) { u32 fo = fat_byte_off + prev_clus * 4; if (fo + 4 <= sizeof(g_disk)) { disk[fo] = 0xF8; disk[fo+1] = 0xFF; disk[fo+2] = 0xFF; disk[fo+3] = (disk[fo+3] & 0xF0) | 0x0F; } } } /* 4. Write data to clusters */ u32 remaining = size; const u8 *src = data; u32 cur = first_clus; u32 ci = 0; while (cur >= 2 && cur < 0x0FFFFFF8 && ci < clusters_needed) { u32 clba = data_lba + (cur - 2) * spc; u32 chunk = remaining < cluster_bytes ? remaining : cluster_bytes; /* Read cluster into g_cluster, overlay data, write back */ if ((u64)clba * 512 + cluster_bytes <= 256ULL * 512) { /* In g_disk buffer — copy data directly */ u8 *dst = disk + (u64)clba * 512; for (u32 b = 0; b < chunk; b++) dst[b] = src[b]; for (u32 b = chunk; b < cluster_bytes; b++) dst[b] = 0; } else { /* Out of buffer — use sector write */ if (fat32_read_sectors(clba, spc, g_cluster) != 0) return -5; for (u32 b = 0; b < chunk; b++) g_cluster[b] = src[b]; for (u32 b = chunk; b < cluster_bytes; b++) g_cluster[b] = 0; if (fat32_write_sectors(clba, spc, g_cluster) != 0) return -6; } src += chunk; remaining -= chunk; ci++; u32 fo = fat_byte_off + cur * 4; if (fo + 4 > sizeof(g_disk)) break; cur = r32(disk + fo) & 0x0FFFFFFF; } /* 5. Update directory entry */ if (!found) { fat32_de *e = &dir[free_entry]; for (int i = 0; i < 11; i++) e->name[i] = name11[i]; e->attr = 0x20; /* archive */ e->ntr = 0; e->ctenth = 0; e->ctime = 0; e->cdate = 0; e->adate = 0; e->chigh = (u16)((first_clus >> 16) & 0xFFFF); e->wtime = 0; e->wdate = 0; e->clow = (u16)(first_clus & 0xFFFF); e->fsize = size; } else { /* 文件已存在:只更新匹配到的条目(不触碰 free_entry!) */ for (u32 e2 = 0; e2 < max_entries; e2++) { if (neq11(dir[e2].name, name11)) { dir[e2].chigh = (u16)((first_clus >> 16) & 0xFFFF); dir[e2].clow = (u16)(first_clus & 0xFFFF); dir[e2].fsize = size; break; } } } /* 6. Write FAT + root directory + data sectors back to disk */ /* BUG-20260730: Only write back FAT sectors within g_disk buffer bounds */ { u32 max_fat_sectors_in_buffer = (256 - fat_lba) / fat_sectors; if (max_fat_sectors_in_buffer > bpb->fc) max_fat_sectors_in_buffer = bpb->fc; for (u32 f = 0; f < max_fat_sectors_in_buffer; f++) { u32 flba = fat_lba + f * fat_sectors; u32 sectors_to_write = fat_sectors; if (flba + sectors_to_write > 256) sectors_to_write = 256 - flba; if (sectors_to_write > 0 && flba < 256) { if (fat32_write_sectors(flba, sectors_to_write, disk + (u64)flba * 512) != 0) return -7; } } } /* Write root directory cluster that was modified */ { if (root_in_buffer) { if (fat32_write_sectors(root_lba, spc, disk + (u64)root_lba * 512) != 0) return -8; } else { if (fat32_write_sectors(root_lba, spc, g_milestone_buf) != 0) { logl("[DSK] fat32 write: root dir write failed (bounce buffer)"); return -8; } } } /* Write data clusters that were in the g_disk buffer */ cur = first_clus; ci = 0; while (cur >= 2 && cur < 0x0FFFFFF8 && ci < clusters_needed) { u32 clba = data_lba + (cur - 2) * spc; if ((u64)clba * 512 + cluster_bytes <= 256ULL * 512) { if (fat32_write_sectors(clba, spc, disk + (u64)clba * 512) != 0) return -9; } u32 fo = fat_byte_off + cur * 4; if (fo + 4 > sizeof(g_disk)) break; cur = r32(disk + fo) & 0x0FFFFFFF; ci++; } logl("[DSK] fat32 write: success"); return 0; } /* Write a file into a directory identified by dir_clus, by 11-char 8.3 name. * If the file exists, its content is replaced. If not, a new entry is created. * Content must fit in one cluster (optimized for small marker files). * Uses g_disk (BPB+FAT) and g_cluster (dir) and g_milestone_buf (data). * Returns 0 on success. */ static int fat32_write_file_in_dir(u32 dir_clus, const char *name11, const u8 *data, u32 size) { u8 *disk = g_disk; const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bps != 512) return -1; u32 spc = bpb->spc; u32 fat_lba = bpb->rsvd; u32 fat_sectors = bpb->spf; u32 data_lba = bpb->rsvd + (u32)bpb->fc * bpb->spf; u32 fat_byte_off = bpb->rsvd * 512; u32 cluster_bytes = spc * 512; if (size > cluster_bytes) return -1; /* content must fit in one cluster */ /* 1. Re-read BPB+FAT to ensure g_disk is fresh */ if (fat32_read_sectors(0, 256, disk) != 0) return -2; /* 2. Read directory cluster */ u32 dir_lba = data_lba + (dir_clus - 2) * spc; if (fat32_read_sectors(dir_lba, spc, g_cluster) != 0) return -3; /* 3. Find existing entry or free slot */ u32 max_entries = cluster_bytes / 32; fat32_de *dir = (fat32_de *)g_cluster; int free_entry = -1; u32 existing_clus = 0; int found = 0; for (u32 e = 0; e < max_entries; e++) { if (dir[e].name[0] == 0) { if (free_entry < 0) free_entry = (int)e; break; } if ((u8)dir[e].name[0] == 0xE5) { if (free_entry < 0) free_entry = (int)e; continue; } if (dir[e].attr == 0x0F) continue; if (dir[e].attr & 0x08) continue; if (neq11(dir[e].name, name11)) { existing_clus = r16((const u8*)&dir[e].clow) | ((u32)r16((const u8*)&dir[e].chigh) << 16); found = 1; break; } } if (!found && free_entry < 0) return -4; /* 4. Allocate or reuse data cluster */ u32 file_clus = 0; if (found && existing_clus >= 2) { file_clus = existing_clus; } else { /* Find free cluster in FAT */ for (u32 c = 2; c < (fat_sectors * 512) / 4; c++) { u32 fo = fat_byte_off + c * 4; if (fo + 4 > sizeof(g_disk)) break; if ((r32(disk + fo) & 0x0FFFFFFF) == 0) { file_clus = c; break; } } if (file_clus == 0) return -5; /* BUG-20260730: Mark as end-of-chain in FAT, preserving high 4 bits */ u32 fo = fat_byte_off + file_clus * 4; if (fo + 4 <= sizeof(g_disk)) { disk[fo] = 0xF8; disk[fo+1] = 0xFF; disk[fo+2] = 0xFF; disk[fo+3] = (disk[fo+3] & 0xF0) | 0x0F; } } /* 5. Write file data to cluster */ u32 file_lba = data_lba + (file_clus - 2) * spc; for (u32 b = 0; b < size; b++) g_milestone_buf[b] = data[b]; for (u32 b = size; b < cluster_bytes; b++) g_milestone_buf[b] = 0; if (fat32_write_sectors(file_lba, spc, g_milestone_buf) != 0) return -6; /* 6. Update directory entry */ if (found) { for (u32 e = 0; e < max_entries; e++) { if (neq11(dir[e].name, name11)) { dir[e].chigh = (u16)((file_clus >> 16) & 0xFFFF); dir[e].clow = (u16)(file_clus & 0xFFFF); dir[e].fsize = size; break; } } } else { fat32_de *e = &dir[free_entry]; for (int i = 0; i < 11; i++) e->name[i] = name11[i]; e->attr = 0x20; /* archive */ e->ntr = 0; e->ctenth = 0; e->ctime = 0; e->cdate = 0; e->adate = 0; e->chigh = (u16)((file_clus >> 16) & 0xFFFF); e->wtime = 0; e->wdate = 0; e->clow = (u16)(file_clus & 0xFFFF); e->fsize = size; } /* 7. Write directory cluster back */ if (fat32_write_sectors(dir_lba, spc, g_cluster) != 0) return -7; /* BUG-20260730: Only write back FAT sectors within g_disk buffer bounds */ { u32 max_fat_sectors_in_buffer = (256 - fat_lba) / fat_sectors; if (max_fat_sectors_in_buffer > bpb->fc) max_fat_sectors_in_buffer = bpb->fc; for (u32 f = 0; f < max_fat_sectors_in_buffer; f++) { u32 flba = fat_lba + f * fat_sectors; u32 sectors_to_write = fat_sectors; if (flba + sectors_to_write > 256) sectors_to_write = 256 - flba; if (sectors_to_write > 0 && flba < 256) { if (fat32_write_sectors(flba, sectors_to_write, disk + (u64)flba * 512) != 0) return -8; } } } logl("[DSK] fat32 write_in_dir: success"); return 0; } /* ---- DSK 启动链里程碑标记系统 ---- * 实机测试崩溃定位:每个启动阶段成功后写标记文件到 FAT32。 * 命名:BOOT01.TXT ~ BOOT07.TXT(8.3 短名)。 * 目标目录:DESHAB64/DEV/(不存在时回退根目录)。 * 写入失败静默忽略,不影响启动流程。 * * 阶段定义: * BOOT_01: FAT32 文件系统就绪 * BOOT_02: block_read/block_write API 就绪 * BOOT_03: FUCK 配置加载完成 * BOOT_04: firstInit 检查完成 * BOOT_05: dev_mode shell 加载完成 * BOOT_06: desktop.elf 加载完成 * BOOT_07: 网络管理器加载完成 */ static void milestone_write(int num, const char *desc) { if (!g_block_write) return; if (num < 1 || num > 9) return; /* 构造 8.3 短名: "BOOTnn TXT" (FAT 8.3 format, 11 chars) */ char name11[12]; name11[0]='B'; name11[1]='O'; name11[2]='O'; name11[3]='T'; name11[4]=(char)('0' + (num / 10)); name11[5]=(char)('0' + (num % 10)); name11[6]=' '; name11[7]=' '; name11[8]='T'; name11[9]='X'; name11[10]='T'; /* 构造内容: "OK\n" + desc + "\n" */ /* BUG-20260730: Enlarge buffer — "OK\n" + stage desc + " tsc=0x" + 16-hex + " ms=" + digits + "\n" can exceed 64 */ u8 buf[160]; u32 len = 0; buf[len++]='O'; buf[len++]='K'; buf[len++]='\n'; while (*desc && len < 150) buf[len++] = (u8)*desc++; buf[len++] = '\n'; /* 确保 BPB 在 g_disk 中可用 */ if (fat32_read_sectors(0, 256, g_disk) != 0) return; /* 尝试写入 DESHAB64/DEV/ 目录,不存在则回退根目录 */ u32 dev_clus = fat32_find_dir_cluster("SYSTEM /DESHAB64 /DEV "); int rc; if (dev_clus >= 2) { rc = fat32_write_file_in_dir(dev_clus, name11, buf, len); } else { rc = fat32_write_root_file(name11, buf, len); } if (rc == 0) { swrite("[DSK] milestone BOOT_0"); sputc('0' + num); logl(dev_clus >= 2 ? " written (DEV)" : " written (root)"); } } static int dsk_check_firstinit(int *is_first, int *dev_mode) { DSK_TS_DECL(firstinit_check); DSK_TS_BEGIN(firstinit_check); char name[12]; /* "FIRSTINTXT" on stack — no PIE reloc */ name[0]='F';name[1]='I';name[2]='R';name[3]='S';name[4]='T'; name[5]='I';name[6]='N';name[7]='T';name[8]='X';name[9]='T';name[10]=0; u8 *data = 0; u32 size = 0; *dev_mode = 0; logl("[DSK] fat32_read_path start"); int rc = fat32_read_root_file(name, &data, &size); logh("[DSK] fat32_read_path rc=", (u64)(i64)rc); if (rc != 0) { logl("[DSK] firstInit.txt not found, assuming first boot"); *is_first = 1; DSK_TS_END(firstinit_check, "dsk_check_firstinit (not found)"); return 0; } if (data[0] == '0') { logl("[DSK] firstInit=0"); *is_first = 1; } else { logl("[DSK] firstInit != 0"); *is_first = 0; } /* 解析第二行 dev_mode 标志(firstInit.txt 格式: "0|1\n0|1") */ u32 i = 0; while (i < size && data[i] != '\n') i++; if (i < size) { i++; /* 跳过换行 */ if (i < size && data[i] == '1') { *dev_mode = 1; logl("[DSK] dev_mode=1 (developer auto-test)"); } } DSK_TS_END(firstinit_check, "dsk_check_firstinit"); return 0; } static int dsk_load_elf(u8 *data, u32 size, void **entry_out) { DSK_TS_DECL(elf_load); DSK_TS_BEGIN(elf_load); DSK_STAT_INC(elf_load); const elf64_ehdr *eh = (const elf64_ehdr *)data; if (size < sizeof(elf64_ehdr)) { logl("[DSK] ELF: data too small"); return -1; } if (eh->ident[0] != EI_MAG0 || eh->ident[4] != ELFCLASS64) { logl("[DSK] ELF: bad magic/class"); return -1; } if (eh->machine != EM_X86_64) { logl("[DSK] ELF: wrong machine"); return -2; } /* P0 修复: 验证程序头在数据范围内 */ if (eh->phoff == 0 || eh->phnum == 0) { logl("[DSK] ELF: no program headers"); return -3; } if ((u64)eh->phoff + (u64)eh->phnum * (u64)eh->phentsize > (u64)size) { logl("[DSK] ELF: program headers beyond data bounds"); return -4; } u64 min_vaddr = ~0ULL, max_vaddr = 0; u32 lc = 0; for (u16 i = 0; i < eh->phnum; i++) { const elf64_phdr *ph = (const elf64_phdr *)(data + eh->phoff + (u64)i * eh->phentsize); if (ph->type != PT_LOAD) continue; if (ph->filesz > ph->memsz) { logl("[DSK] ELF: filesz > memsz"); return -5; } /* P0 修复: 验证 PT_LOAD 段在数据范围内 */ if ((u64)ph->offset + (u64)ph->filesz > (u64)size) { logl("[DSK] ELF: PT_LOAD beyond data bounds"); logh("[DSK] ELF: offset=", ph->offset); logh("[DSK] ELF: filesz=", ph->filesz); return -6; } if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr; if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz; lc++; } if (!lc || min_vaddr == ~0ULL) { logl("[DSK] ELF: no PT_LOAD segments"); return -7; } u64 isize = max_vaddr - min_vaddr; isize = (isize + 0xFFF) & ~0xFFFULL; logh("[DSK] elf total image size=", isize); /* 加载缓冲:需容纳 desktop.elf(~1.67MB memsz span,含 Linux 窗口槽+16KB 缓冲 BSS)。2MB 留余量。 */ static u8 ibuf[8388608]; /* 8MB — cmd.elf 含 4MB PE 文件缓冲 BSS */ u8 *image = ibuf; if (isize > 8388608) { logl("[DSK] ELF: image too large for 8MB ibuf"); logh("[DSK] ELF isize=", isize); return -8; } memset_dsk(image, 0, isize); for (u16 i = 0; i < eh->phnum; i++) { const elf64_phdr *ph = (const elf64_phdr *)(data + eh->phoff + (u64)i * eh->phentsize); if (ph->type != PT_LOAD) continue; u64 off = ph->vaddr - min_vaddr; logh("[DSK] PT_LOAD vaddr=", ph->vaddr); logh("[DSK] PT_LOAD filesz=", ph->filesz); logh("[DSK] PT_LOAD memsz=", ph->memsz); /* off + filesz 不会越界,已在上面的循环中验证 */ memcpy_dsk(image + off, data + ph->offset, ph->filesz); } /* P0 修复: 验证 entry 在映像范围内 */ if (eh->entry < min_vaddr || eh->entry >= max_vaddr) { logl("[DSK] ELF: entry point out of bounds"); logh("[DSK] ELF: entry=", eh->entry); logh("[DSK] ELF: min_vaddr=", min_vaddr); logh("[DSK] ELF: max_vaddr=", max_vaddr); return -9; } *entry_out = image + (eh->entry - min_vaddr); /* apply R_X86_64_RELATIVE relocations from PT_DYNAMIC (PIE) */ u64 load_bias = (u64)image - min_vaddr; for (u16 i = 0; i < eh->phnum; i++) { const elf64_phdr *ph = (const elf64_phdr *)(data + eh->phoff + (u64)i * eh->phentsize); if (ph->type != PT_DYNAMIC) continue; /* P0 修复: 验证 PT_DYNAMIC vaddr 在映像范围内 */ if (ph->vaddr < min_vaddr || ph->vaddr + ph->filesz > max_vaddr) { logl("[DSK] ELF: PT_DYNAMIC out of image bounds"); continue; } const elf64_dyn *dyn = (const elf64_dyn *)(image + (ph->vaddr - min_vaddr)); u64 rela_off = 0, rela_sz = 0, rela_ent = 24; for (; dyn->tag != 0; dyn++) { if (dyn->tag == DT_RELA) rela_off = dyn->val; else if (dyn->tag == DT_RELASZ) rela_sz = dyn->val; else if (dyn->tag == DT_RELAENT) rela_ent = dyn->val; } if (rela_off && rela_sz) { /* P0 修复: 边界检查 rela_off 和 rela_off+rela_sz 必须在 [min_vaddr, min_vaddr+isize) 内 */ if (rela_off < min_vaddr || rela_off >= min_vaddr + isize) { logl("[DSK] ELF: rela_off out of bounds, skipping reloc"); logh("[DSK] ELF: rela_off=", rela_off); logh("[DSK] ELF: min_vaddr=", min_vaddr); logh("[DSK] ELF: isize=", isize); continue; } if (rela_off + rela_sz > min_vaddr + isize) { logl("[DSK] ELF: rela table extends beyond image, clamping"); rela_sz = (min_vaddr + isize - rela_off) / rela_ent * rela_ent; } u64 n = rela_sz / rela_ent; logh("[DSK] elf relocs=", n); for (u64 r = 0; r < n; r++) { const elf64_rela *rel = (const elf64_rela *)(image + (rela_off - min_vaddr) + r * rela_ent); u32 rtype = (u32)(rel->info & 0xFFFFFFFF); if (rtype == R_X86_64_RELATIVE) { /* P0 修复: 验证 rel->offset 在映像范围内,防止无符号下溢 */ if (rel->offset < min_vaddr || rel->offset >= min_vaddr + isize) continue; u64 *slot = (u64 *)(image + (rel->offset - min_vaddr)); *slot = load_bias + (u64)rel->addend; } } } } logh("[DSK] elf image base=", (u64)image); logh("[DSK] elf entry=", (u64)*entry_out); DSK_TS_END(elf_load, "dsk_load_elf"); return 0; } /* Load an ELF module from the FAT32 root by 11-char 8.3 name, parse it into * the shared image buffer, and jump to its entry with the boot context. * Returns 0 if the module ran and returned, non-zero on load failure. */ static int dsk_load_and_run(const char name11[12], const dsk_boot_context *ctx) { DSK_TS_DECL(mod_run); DSK_TS_BEGIN(mod_run); DSK_STAT_INC(mod_schedule); u8 *data=0; u32 size=0; void *entry=0; logl("[DSK] load_and_run: "); swrite(name11); swrite("\n"); if (fat32_read_root_file(name11, &data, &size) != 0) { logl("[DSK] load_and_run: fat32 read failed for "); swrite(name11); swrite("\n"); return -1; } if (dsk_load_elf(data, size, &entry) != 0) { logl("[DSK] load_and_run: elf load failed for "); swrite(name11); swrite("\n"); return -2; } void(*fn)(const dsk_boot_context*)=(void(*)(const dsk_boot_context*))entry; fn(ctx); DSK_TS_END(mod_run, "dsk_load_and_run"); return 0; } /* Load desktop.elf and jump to it. Never returns on success. */ static void dsk_run_desktop(const dsk_boot_context *ctx) { char dn[12]; /* DESKTOP ELF */ dn[0]='D';dn[1]='E';dn[2]='S';dn[3]='K';dn[4]='T';dn[5]='O';dn[6]='P';dn[7]=' ';dn[8]='E';dn[9]='L';dn[10]='F'; if (dsk_load_and_run(dn, ctx) != 0) logl("[DSK] desktop load failed"); for(;;)__asm__("hlt"); } /* After FirstInit returns, persist the encrypted user.conf buffer (left in * ctx->reserved[0/1]) to the FAT32 root as USER.CONF, then flip firstInit.txt * from '0' to '1' so subsequent boots skip the wizard and go to login. */ static void dsk_persist_userconf(const dsk_boot_context *ctx) { dsk_boot_context *ctx_mut = (dsk_boot_context *)ctx; u64 conf_ptr = ctx_mut->reserved[0]; u64 conf_sz = ctx_mut->reserved[1]; if (!conf_ptr || !conf_sz) { logl("[DSK] no conf buffer from FirstInit, skipping persist"); return; } if (!g_block_write) { logl("[DSK] no block_write, cannot persist user.conf"); return; } const u8 *conf = (const u8 *)conf_ptr; /* 1. Write USER.CONF (encrypted buffer as-is; login decrypts with password) */ char cn[12]; /* USER CON */ cn[0]='U';cn[1]='S';cn[2]='E';cn[3]='R';cn[4]=' ';cn[5]=' ';cn[6]=' ';cn[7]=' ';cn[8]='C';cn[9]='O';cn[10]='N'; logl("[DSK] writing USER.CONF"); int wrc = fat32_write_root_file(cn, conf, (u32)conf_sz); logh("[DSK] USER.CONF write rc=", (u64)(i64)wrc); /* 2. Flip firstInit.txt: '0' -> '1',保留第二行 dev_mode 标志 */ char fn[12]; /* FIRSTINTXT */ fn[0]='F';fn[1]='I';fn[2]='R';fn[3]='S';fn[4]='T';fn[5]='I';fn[6]='N';fn[7]='T';fn[8]='X';fn[9]='T';fn[10]=0; /* 读取当前 firstInit.txt 以保留 dev_mode(第二行),格式 "0|1\n0|1" */ u8 dev_mode_byte = '0'; u8 *fi_data = 0; u32 fi_size = 0; if (fat32_read_root_file(fn, &fi_data, &fi_size) == 0) { u32 i = 0; while (i < fi_size && fi_data[i] != '\n') i++; if (i < fi_size) { i++; if (i < fi_size) dev_mode_byte = fi_data[i]; } } u8 fi_buf[3]; fi_buf[0] = '1'; fi_buf[1] = '\n'; fi_buf[2] = dev_mode_byte; int frc = fat32_write_root_file(fn, fi_buf, 3); logh("[DSK] firstInit.txt flip rc=", (u64)(i64)frc); /* Clear reserved so login path doesn't see stale pointer */ ctx_mut->reserved[0] = 0; ctx_mut->reserved[1] = 0; } /* Draw the spinning loader (comet-tail arc) on the gradient background, * then run the firstInit check and dispatch system component loading. * FUCK config controls: show_logo, skip_login, mouse_init, netman, dev_mode. */ static void dsk_spinner_and_check(const void *boot_ctx_ptr) { const dsk_boot_context *ctx = (const dsk_boot_context *)boot_ctx_ptr; { u64 api_addr = ctx->dkm_kernel_api; logh("[DSK] kernel_api addr=", api_addr); if (!api_addr) { logl("[DSK] FATAL: kernel_api is NULL"); for(;;)__asm__("hlt"); } const dsk_kernel_api_mirror *api = (const dsk_kernel_api_mirror *)api_addr; const dsk_block_api_mirror *blk = api->block; logh("[DSK] block_api addr=", (u64)(u64)blk); g_block_read = blk ? blk->read : 0; g_block_write = blk ? blk->write : 0; logh("[DSK] block_read fn=", (u64)g_block_read); logh("[DSK] block_write fn=", (u64)g_block_write); } milestone_write(2, "block API ready"); g_fb_addr=ctx->framebuffer_address; g_fb_w=ctx->framebuffer_width; g_fb_h=ctx->framebuffer_height; g_fb_p=ctx->framebuffer_pitch; if (!g_fb_addr) { logl("[DSK] FATAL: framebuffer address is NULL"); for(;;)__asm__("hlt"); } u32 *sfb=(u32*)(u64)g_fb_addr; logh("[DSK] block_read ptr=", (u64)g_block_read); tsc_calibrate_dsk(); /* === 读取 FUCK 配置 === */ DSK_TS_DECL(fuck_config); DSK_TS_BEGIN(fuck_config); dsk_ini_config dsk_cfg; int dsk_cfg_ok = 0; if (g_block_read) { logl("[DSK] reading BPB for FUCK config"); int bpb_rc = fat32_read_sectors(0, 256, g_disk); if (bpb_rc == 0) { milestone_write(1, "FAT32 ready"); u8 *fuck_data=0; u32 fuck_size=0; int rc = fat32_read_path("SYSTEM /DESHAB64 /FUCK ", &fuck_data, &fuck_size); logh("[DSK] fat32_read_path FUCK rc=", (u64)(i64)rc); if (rc != 0) { /* 扁平布局回退:SATA 测试盘等场景下 FUCK 直接放根目录 */ rc = fat32_read_path("FUCK ", &fuck_data, &fuck_size); logh("[DSK] fat32_read_path root FUCK rc=", (u64)(i64)rc); } if (rc == 0 && fuck_size > 0) { if (dsk_ini_parse((const char *)fuck_data, fuck_size, &dsk_cfg) == 0) { dsk_cfg_ok = 1; logl("[DSK] FUCK config loaded"); } else { logl("[DSK] FUCK INI parse failed"); } } else { logl("[DSK] FUCK file not found or empty"); } } else { logl("[DSK] BPB read failed, cannot load FUCK"); } } DSK_TS_END(fuck_config, "FUCK config load"); /* === 应用 DSK 配置 === */ int show_logo = dsk_cfg_ok ? dsk_ini_get_bool(&dsk_cfg, "dsk", "show_logo", 1) : 1; int skip_login = dsk_cfg_ok ? dsk_ini_get_bool(&dsk_cfg, "dsk", "skip_login", 0) : 0; int load_mouse = dsk_cfg_ok ? dsk_ini_get_bool(&dsk_cfg, "dsk", "mouse_init", 1) : 1; int load_netman = dsk_cfg_ok ? dsk_ini_get_bool(&dsk_cfg, "dsk", "netman", 1) : 1; int dev_mode = dsk_cfg_ok ? dsk_ini_get_bool(&dsk_cfg, "boot", "dev_mode", 0) : 0; milestone_write(3, "FUCK config loaded"); /* Gradient background + centered Logo.png (5 seconds) */ dsk_fill_gradient_rect(sfb, 0, 0, (i64)g_fb_w, (i64)g_fb_h); if (show_logo) { /* Draw Logo.png centered with alpha blending on gradient background */ dsk_draw_logo(sfb); /* Draw "DESHAB P01" text centered below the logo */ { i64 logo_cx = (i64)g_fb_w / 2; i64 logo_cy = ((i64)g_fb_h - g_logo_h) / 2; const char *ver_str = "DESHAB P01"; int len = 10; /* strlen("DESHAB P01") */ int spacing = g_ascii_w + 1; /* 11+1 = 12px per char */ i64 text_w = (i64)len * spacing; i64 text_x = logo_cx - text_w / 2; i64 text_y = logo_cy + g_logo_h + 12; /* 12px below logo */ /* White text: BGRX = 0xFF_RR_GG_BB = 0xFF_FFFFFF */ u32 fg = 0xFFFFFFFFu; dsk_draw_string(sfb, ver_str, text_x, text_y, fg, spacing); } logh("[DSK] Logo.png displayed (", (u64)g_logo_w); logh("[DSK] x", (u64)g_logo_h); /* Hold Logo for 5 seconds */ u64 logo_start = rdtsc_dsk(); u64 logo_budget = g_tsc_per_ms * 5000; /* 5000 ms = 5 seconds */ while (rdtsc_dsk() - logo_start < logo_budget) __asm__("pause"); logl("[DSK] Logo 5s done, proceeding"); } else { logl("[DSK] logo skipped by FUCK config"); } if (!g_block_read) { logl("[DSK] no block device, halting"); for(;;)__asm__("hlt"); } logl("[DSK] checking firstInit..."); DSK_TS_DECL(firstinit_phase); DSK_TS_BEGIN(firstinit_phase); int is_first = 0, firstinit_dev_mode = 0; if (dsk_check_firstinit(&is_first, &firstinit_dev_mode) != 0) { logl("[DSK] firstInit check failed, halting"); for(;;)__asm__("hlt"); } DSK_TS_END(firstinit_phase, "firstInit check phase"); milestone_write(4, "firstInit check done"); /* 合并 FUCK dev_mode 和 firstInit.txt dev_mode */ if (firstinit_dev_mode) dev_mode = 1; /* 开发者模式:加载 shell.elf 自动测试命令序列(cp/mv/echo/ls/cat/rm) */ if (dev_mode) { logl("[DSK:SCHED] decision: dev_mode -> shell.elf"); char sn[12]; /* SHELL ELF */ sn[0]='S';sn[1]='H';sn[2]='E';sn[3]='L';sn[4]='L';sn[5]=' ';sn[6]=' ';sn[7]=' ';sn[8]='E';sn[9]='L';sn[10]='F'; dsk_boot_context *ctx_mut = (dsk_boot_context *)ctx; ctx_mut->reserved[3] = 1; /* dev mode flag for shell */ if (dsk_load_and_run(sn, ctx) == 0) logl("[DSK] shell auto-test returned"); else logl("[DSK] shell.elf not found, skipping dev test"); ctx_mut->reserved[3] = 0; milestone_write(5, "dev shell loaded"); } if (!is_first) { logl("[DSK:SCHED] decision: is_first=0 -> login then desktop"); /* login — 可通过 skip_login=1 跳过 */ if (skip_login) { logl("[DSK:SCHED] login skipped by FUCK config"); } else { DSK_TS_DECL(login_phase); DSK_TS_BEGIN(login_phase); logl("[DSK:SCHED] scheduling login.elf"); char ln[12]; /* LOGIN ELF */ ln[0]='L';ln[1]='O';ln[2]='G';ln[3]='I';ln[4]='N';ln[5]=' ';ln[6]=' ';ln[7]=' ';ln[8]='E';ln[9]='L';ln[10]='F'; u8 *ld=0; u32 ls=0; void *le=0; int login_ok = 0; if (fat32_read_root_file(ln, &ld, &ls) == 0) { if (dsk_load_elf(ld, ls, &le) == 0) { char cn[12]; /* USER CON */ cn[0]='U';cn[1]='S';cn[2]='E';cn[3]='R';cn[4]=' ';cn[5]=' ';cn[6]=' ';cn[7]=' ';cn[8]='C';cn[9]='O';cn[10]='N'; u8 *conf_data=0; u32 conf_size=0; if (fat32_read_root_file(cn, &conf_data, &conf_size) == 0) { logl("[DSK] USER.CONF found, passing to login"); dsk_boot_context *ctx_mut = (dsk_boot_context *)ctx; ctx_mut->reserved[0] = (u64)conf_data; ctx_mut->reserved[1] = (u64)conf_size; ctx_mut->reserved[2] = 0; /* login success flag */ logl("[DSK] jumping to login"); void(*lentry)(const dsk_boot_context*)=(void(*)(const dsk_boot_context*))le; lentry(ctx); logl("[DSK] login returned"); if (ctx_mut->reserved[2] == 1) { logl("[DSK] login success"); login_ok = 1; } else { logl("[DSK] login skipped or failed"); } } else { logl("[DSK] USER.CONF not found, skipping login"); } } else { logl("[DSK] login.elf load failed, skipping login"); } } else { logl("[DSK] login.elf not found, skipping login"); } (void)login_ok; DSK_TS_END(login_phase, "login phase"); } /* default_shell=cmd → 直接进 CMD.ELF(PE/EXE 兼容层前端), * cmd 退出后回落桌面。 */ const char *def_shell = dsk_cfg_ok ? dsk_ini_get(&dsk_cfg, "dsk", "default_shell") : 0; if (def_shell && dsk_ini_streq(def_shell, "cmd")) { logl("[DSK:SCHED] default_shell=cmd -> cmd.elf"); char cn[12]; /* CMD ELF */ cn[0]='C';cn[1]='M';cn[2]='D';cn[3]=' ';cn[4]=' ';cn[5]=' ';cn[6]=' ';cn[7]=' ';cn[8]='E';cn[9]='L';cn[10]='F'; if (dsk_load_and_run(cn, ctx) == 0) logl("[DSK] cmd.elf returned, falling back to desktop"); else logl("[DSK] cmd.elf load failed, falling back to desktop"); } logl("[DSK:SCHED] loading desktop"); logh("[DSK:STAT] fat32_read_count=", (u64)fat32_read_count); logh("[DSK:STAT] fat32_write_count=", (u64)fat32_write_count); logh("[DSK:STAT] elf_load_count=", (u64)elf_load_count); logh("[DSK:STAT] mod_schedule_count=", (u64)mod_schedule_count); milestone_write(6, "desktop loading"); dsk_run_desktop(ctx); return; } /* First boot: run system initializers, then FirstInit, then desktop */ logl("[DSK:SCHED] decision: is_first=1 -> mouseInit -> netman -> FirstInit -> desktop"); /* mouseInit.elf — 可通过 FUCK mouse_init=0 跳过 */ if (load_mouse) { logl("[DSK:SCHED] scheduling mouseInit.elf"); char mn[12]; /* MOUSE ELF */ mn[0]='M';mn[1]='O';mn[2]='U';mn[3]='S';mn[4]='E';mn[5]=' ';mn[6]=' ';mn[7]=' ';mn[8]='E';mn[9]='L';mn[10]='F'; logl("[DSK] loading mouseInit"); if (dsk_load_and_run(mn, ctx) == 0) logl("[DSK] mouseInit returned"); else logl("[DSK] mouseInit not found"); } else { logl("[DSK] mouseInit skipped by FUCK config"); } /* netman.elf — 可通过 FUCK netman=0 跳过 */ if (load_netman) { logl("[DSK:SCHED] scheduling netman.elf"); char nn[12]; /* NETMAN ELF */ nn[0]='N';nn[1]='E';nn[2]='T';nn[3]='M';nn[4]='A';nn[5]='N';nn[6]=' ';nn[7]=' ';nn[8]='E';nn[9]='L';nn[10]='F'; logl("[DSK] loading netman"); if (dsk_load_and_run(nn, ctx) == 0) logl("[DSK] netman returned"); else logl("[DSK] netman not found"); } else { logl("[DSK] netman skipped by FUCK config"); } milestone_write(7, "netman loaded"); /* FirstInit.elf — user setup wizard; returns to DSK when done */ { logl("[DSK:SCHED] scheduling FirstInit.elf"); char en[12]; /* FIRSTINIT */ en[0]='F';en[1]='I';en[2]='R';en[3]='S';en[4]='T'; en[5]='I';en[6]='N';en[7]='I';en[8]='T';en[9]=' ';en[10]=0; logl("[DSK] loading FirstInit"); if (dsk_load_and_run(en, ctx) != 0) { logl("[DSK] FirstInit not found, loading desktop directly"); milestone_write(6, "desktop loading"); dsk_run_desktop(ctx); return; } logl("[DSK] FirstInit returned, persisting user.conf"); dsk_persist_userconf(ctx); logh("[DSK:STAT] fat32_read_count=", (u64)fat32_read_count); logh("[DSK:STAT] fat32_write_count=", (u64)fat32_write_count); logh("[DSK:STAT] elf_load_count=", (u64)elf_load_count); logh("[DSK:STAT] mod_schedule_count=", (u64)mod_schedule_count); logl("[DSK] loading desktop"); milestone_write(6, "desktop loading"); dsk_run_desktop(ctx); } } __attribute__((noreturn, visibility("default"))) void dsk_entry(const dsk_boot_context *ctx) { __asm__ volatile("cli"); /* disable IRQs — ps2kbd/IRQ1 & mouse/IRQ12 handlers crash during boot */ logl("[DSK] boot"); if(!ctx||ctx->magic!=DSK_BOOT_MAGIC){logl("[DSK] bad context");for(;;)__asm__("hlt");} logl("[DSK] context ok"); dsk_spinner_and_check(ctx); logl("[DSK] SELFTEST PASS"); for(;;)__asm__("hlt"); }