feat: FS-E strict filesystem mode - ext4 rw driver, FAT32 big-disk fix, forced re-login

- CODE/dsk/ext4.c: minimal full ext4 read/write (GPT probe, feature gate,
  extent depth 0/1 rw, block/inode alloc-free, dir insert, write-verify);
  boot selftest PASS on p2. Unsupported features panic (FS-E2x), zero fallback.
- DSK fat32 write: on-demand FAT entry RMW + chunked free-cluster scan
  (fixes "no free clusters" on 5.3G ESP); rec_len shrink offset (+4) and
  chunk alignment fixes. USER.CONF write-verify ok, firstInit flip ok.
- First-boot: wizard -> persist -> forced login (FS-E06 if skipped/failed)
  -> desktop. login.elf loaded via system/user/use fallback.
- FirstInit network page: Connect now panics NET-E01 (no wlan stack);
  Save (config only) is the only path forward.
- FirstInit/DSK fatal: ohMyLogo lotus fatal screen (NET-E01 / FS-E series).
- Boot screen: Logo.png image removed, "DESHAB P01" text centered only;
  dcp/xj logos regenerated from TEXTURES/.
- run_qemu.bat: main GPT image on SATA ide.0 (AHCI provider must see ext4).
This commit is contained in:
Linehu
2026-10-02 23:49:05 +08:00
parent c4a5295a81
commit 38ff3cf93c
28 changed files with 2816 additions and 1458 deletions
+236 -156
View File
@@ -5,18 +5,20 @@
#include "port.h"
#include "../tools/fat32_lfn.h"
#include "../tools/fat32_part.h"
/* Embedded Logo.png RGBA data (auto-generated by png_to_rgba.py) */
#include "logo_data.c"
#include "ext4.h"
/* Embedded dcplogo.png / xjlogo.png RGBA data (auto-generated by
* png_to_rgba_prefixed.py; must stay file-local like logo_data.c) */
* png_to_rgba_prefixed.py from TEXTURES directory; must stay file-local like
* other embedded art) */
#include "dcp_logo_data.c"
#include "xj_logo_data.c"
/* Embedded ASCII bitmap font (Consolas 18px grayscale, 11x18 cell) */
#include "../firstInit/ascii_bitmaps.c"
/* Embedded ohMyLogo.png RGBA data(莲花 panic 界面用,与 login.elf 同源) */
#include "../login/ohmylogo_data.c"
#define COM1 0x3F8
typedef unsigned char u8;
@@ -550,10 +552,6 @@ static void dsk_draw_rgba(u32 *fb, const u8 *pix, int w, int h) {
}
}
static void dsk_draw_logo(u32 *fb) {
dsk_draw_rgba(fb, g_logo_rgba, g_logo_w, g_logo_h);
}
/* Splash sequence entry: one image + hold for the given milliseconds.
* Redraws the gradient background first so successive images replace
* each other cleanly. */
@@ -634,6 +632,64 @@ static void dsk_draw_string(u32 *fb, const char *s, i64 x, i64 y, u32 fg, int sp
}
}
/* ===================================================================
* 严格错误策略插桩:FS/调度层任何错误(含未实现路径)不再降级、
* 不再静默跳过,必须整屏 fatal 显示错误码后停机。
* 错误码体系:FS-E<nn>(文件系统层)。
* =================================================================== */
static u64 dsk_fat_strlen(const char *s) { u64 n = 0; while (s[n]) n++; return n; }
/* 莲花 panic 界面:深蓝底 + ohMyLogo 莲花居中 + 错误码 + 停机落款。
* 与 login.elf / UTSM F1 panic 同一视觉体系。 */
static void dsk_fatal_lotus(u32 *fb, const char *sym) {
/* 深蓝底 */
for (u64 y = 0; y < g_fb_h; y++) {
u32 *line = (u32 *)((u8 *)fb + y * g_fb_p);
for (u64 x = 0; x < g_fb_w; x++) line[x] = 0xFF020F22u;
}
/* 莲花居中(偏上,给错误码留空间) */
i64 lx = ((i64)g_fb_w - g_panic_logo_w) / 2;
i64 ly = ((i64)g_fb_h - g_panic_logo_h) / 2 - 60;
if (ly < 0) ly = 0;
for (i64 r = 0; r < g_panic_logo_h; r++) {
for (i64 c = 0; c < g_panic_logo_w; c++) {
const unsigned char *px4 =
g_panic_logo_rgba + ((u64)r * g_panic_logo_w + (u64)c) * 4;
u32 a = px4[3];
if (a < 8) continue;
u32 col = 0xFF000000u | ((u32)px4[0] << 16) | ((u32)px4[1] << 8) | px4[2];
if (a < 250) {
u32 bg = 0xFF020F22u;
u32 na = 256 - a;
u32 rr = (((bg >> 16) & 0xFF) * na + ((col >> 16) & 0xFF) * a) >> 8;
u32 gg = (((bg >> 8) & 0xFF) * na + ((col >> 8) & 0xFF) * a) >> 8;
u32 bb = ((bg & 0xFF) * na + (col & 0xFF) * a) >> 8;
col = 0xFF000000u | (rr << 16) | (gg << 8) | bb;
}
i64 xx = lx + c, yy = ly + r;
if (xx < 0 || (u64)xx >= g_fb_w || yy < 0 || (u64)yy >= g_fb_h) continue;
*(u32 *)((u8 *)fb + (u64)yy * g_fb_p + (u64)xx * 4) = col;
}
}
/* 错误码 + 停机落款(莲花下方) */
i64 ty = ly + g_panic_logo_h + 24;
i64 spacing = g_ascii_w + 1;
dsk_draw_string(fb, sym,
((i64)g_fb_w - (i64)dsk_fat_strlen(sym) * spacing) / 2, ty,
0xFFF2D8D8u, (int)spacing);
dsk_draw_string(fb, "DESHAB FS FATAL - SYSTEM HALTED",
((i64)g_fb_w - 31 * spacing) / 2, ty + g_ascii_h + 16,
0xFFB08890u, (int)spacing);
}
static void dsk_fatal(const char *sym) {
logl(sym);
if (g_fb_addr) {
dsk_fatal_lotus((u32 *)(u64)g_fb_addr, sym);
}
for (;;) __asm__("cli; hlt");
}
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++) {
@@ -722,6 +778,51 @@ static int fat32_read_root_file(const char *name11, u8 **out_data, u32 *out_size
* 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. */
/* BUG-20261002 修复: 按需 FAT 表项读写(支持 FAT 超出 g_disk 256 扇区的大容量 ESP)。
* 缓冲内直接改写(随后由步骤 6 回写),缓冲外读单扇区到 g_fat_sec 改写后立即落盘。 */
static u32 fat32_fat_read_entry(u32 fat_byte_off, u32 c) {
u32 fo = fat_byte_off + c * 4;
if (fo + 4 <= sizeof(g_disk)) return r32(g_disk + fo) & 0x0FFFFFFF;
u32 sec = fo / 512, off = fo % 512;
if (fat32_read_sectors(sec, 1, g_fat_sec) != 0) return 0x0FFFFFF7; /* 读失败视作坏簇 */
return r32(g_fat_sec + off) & 0x0FFFFFFF;
}
static int fat32_fat_write_entry(u32 fat_byte_off, u32 c, u32 val) {
u32 fo = fat_byte_off + c * 4;
if (fo + 4 <= sizeof(g_disk)) {
g_disk[fo] = (u8)(val & 0xFF);
g_disk[fo+1] = (u8)((val >> 8) & 0xFF);
g_disk[fo+2] = (u8)((val >> 16) & 0xFF);
g_disk[fo+3] = (u8)((g_disk[fo+3] & 0xF0) | ((val >> 24) & 0x0F));
return fat32_write_sectors(fo / 512, 1, g_disk + (u64)(fo / 512) * 512);
}
u32 sec = fo / 512, off = fo % 512;
if (fat32_read_sectors(sec, 1, g_fat_sec) != 0) return -1;
g_fat_sec[off] = (u8)(val & 0xFF);
g_fat_sec[off+1] = (u8)((val >> 8) & 0xFF);
g_fat_sec[off+2] = (u8)((val >> 16) & 0xFF);
g_fat_sec[off+3] = (u8)((g_fat_sec[off+3] & 0xF0) | ((val >> 24) & 0x0F));
return fat32_write_sectors(sec, 1, g_fat_sec);
}
/* 块状空闲簇扫描:每次读 8 扇区(1024 表项),fat_byte_off 必须扇区对齐。
* chunk k 覆盖表项 [k*1024, (k+1)*1024)。 */
static u8 g_fatscan[4096];
static u32 fat32_find_free_cluster(u32 fat_byte_off, u32 max_c) {
for (u32 k = 0; k * 1024 < max_c; k++) {
u32 base = k * 1024;
if (fat32_read_sectors(fat_byte_off / 512 + k * 8, 8, g_fatscan) != 0)
continue;
u32 n = max_c - base; if (n > 1024) n = 1024;
for (u32 i = 0; i < n; i++) {
u32 c = base + i;
if (c < 2) continue;
if ((r32(g_fatscan + i * 4) & 0x0FFFFFFF) == 0) return c;
}
}
return 0;
}
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;
@@ -818,54 +919,32 @@ static int fat32_write_root_file(const char *name11, const u8 *data, u32 size) {
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;
cur = fat32_fat_read_entry(fat_byte_off, cur);
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; }
}
u32 newc = fat32_find_free_cluster(fat_byte_off, (fat_sectors * 512) / 4);
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;
}
}
logh("[DSK] fat32 write: alloc clus=", newc);
/* Mark newly allocated cluster as EOC immediately to prevent re-allocation */
if (fat32_fat_write_entry(fat_byte_off, newc, 0x0FFFFFF8) != 0) return -7;
/* 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);
if (prev_clus >= 2) {
if (fat32_fat_write_entry(fat_byte_off, prev_clus, newc) != 0) return -7;
}
prev_clus = newc;
count++;
}
/* BUG-20260730: Terminate the chain, saving original next pointer before overwriting with EOC */
/* 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;
}
u32 original_next = fat32_fat_read_entry(fat_byte_off, prev_clus);
fat32_fat_write_entry(fat_byte_off, prev_clus, 0x0FFFFFF8);
/* 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; }
u32 nn = fat32_fat_read_entry(fat_byte_off, next);
fat32_fat_write_entry(fat_byte_off, next, 0);
next = nn;
}
}
@@ -873,40 +952,17 @@ static int fat32_write_root_file(const char *name11, const u8 *data, u32 size) {
/* 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; }
}
u32 newc = fat32_find_free_cluster(fat_byte_off, (fat_sectors * 512) / 4);
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;
}
}
logh("[DSK] fat32 write: alloc clus=", newc);
/* Mark newly allocated cluster as EOC immediately to prevent re-allocation */
if (fat32_fat_write_entry(fat_byte_off, newc, 0x0FFFFFF8) != 0) return -7;
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);
}
if (fat32_fat_write_entry(fat_byte_off, prev_clus, newc) != 0) return -7;
}
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 */
@@ -931,9 +987,7 @@ static int fat32_write_root_file(const char *name11, const u8 *data, u32 size) {
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;
cur = fat32_fat_read_entry(fat_byte_off, cur);
}
/* 5. Update directory entry */
@@ -1307,6 +1361,26 @@ static int dsk_load_elf(u8 *data, u32 size, void **entry_out) {
/* 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. */
/* 按名字加载模块 ELF:先根目录,后 SYSTEM/DESHAB64/ 与 SYSTEM/USER/USE/ 回退。 */
static int dsk_load_module(const char name11[12], u8 **data, u32 *size) {
if (fat32_read_root_file(name11, data, size) == 0) return 0;
static const char *pfxs[] = { "SYSTEM /DESHAB64 /", "SYSTEM /USER /USE /" };
for (int pi = 0; pi < 2; pi++) {
char path[40];
int i = 0, j;
const char *pfx = pfxs[pi];
while (pfx[i]) { path[i] = pfx[i]; i++; }
for (j = 0; j < 11; j++) path[i++] = name11[j];
path[i] = 0;
logl("[DSK] load_and_run: trying fallback path");
if (fat32_read_sectors(0, 256, g_disk) == 0 &&
fat32_read_path(path, data, size) == 0) return 0;
}
logl("[DSK] load_and_run: fat32 read failed for ");
swrite(name11); swrite("\n");
return -1;
}
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);
@@ -1314,29 +1388,7 @@ static int dsk_load_and_run(const char name11[12], const dsk_boot_context *ctx)
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) {
/* 依次回退:SYSTEM/DESHAB64/ → SYSTEM/USER/USE/(FirstInit.elf 部署位) */
static const char *pfxs[] = { "SYSTEM /DESHAB64 /", "SYSTEM /USER /USE /" };
int loaded = 0;
for (int pi = 0; pi < 2 && !loaded; pi++) {
char path[40];
int i = 0, j;
const char *pfx = pfxs[pi];
while (pfx[i]) { path[i] = pfx[i]; i++; }
for (j = 0; j < 11; j++) path[i++] = name11[j];
path[i] = 0;
logl("[DSK] load_and_run: trying fallback path");
if (fat32_read_sectors(0, 256, g_disk) == 0 &&
fat32_read_path(path, &data, &size) == 0) {
loaded = 1;
}
}
if (!loaded) {
logl("[DSK] load_and_run: fat32 read failed for ");
swrite(name11); swrite("\n");
return -1;
}
}
if (dsk_load_module(name11, &data, &size) != 0) 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; }
logl("[DSK] jumping to module");
void(*fn)(const dsk_boot_context*)=(void(*)(const dsk_boot_context*))entry;
@@ -1664,11 +1716,13 @@ static void dsk_persist_userconf(const 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");
/* 严格错误策略:FirstInit 返回却没留下配置缓冲 = 向导失败,零降级 */
dsk_fatal("FS-E05 FIRSTINIT NO CONF BUFFER");
return;
}
if (!g_block_write) {
logl("[DSK] no block_write, cannot persist user.conf");
/* 严格错误策略:块层无写通道 = FS 不可写,零降级 */
dsk_fatal("FS-E01 NO BLOCK WRITE PROVIDER");
return;
}
const u8 *conf = (const u8 *)conf_ptr;
@@ -1679,6 +1733,20 @@ static void dsk_persist_userconf(const dsk_boot_context *ctx) {
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);
if (wrc != 0) dsk_fatal("FS-E02 USER.CONF WRITE FAILED");
/* 1b. Write-verify: 回读 USER.CONF 逐字节比对,确保 FAT32 写路径真的落盘 */
{
u8 *vdata = 0; u32 vsize = 0;
if (fat32_read_root_file(cn, &vdata, &vsize) != 0)
dsk_fatal("FS-E04 USER.CONF VERIFY READ FAILED");
if (vsize != (u32)conf_sz)
dsk_fatal("FS-E04 USER.CONF VERIFY SIZE MISMATCH");
for (u32 i = 0; i < (u32)conf_sz; i++) {
if (vdata[i] != conf[i]) dsk_fatal("FS-E04 USER.CONF VERIFY DATA MISMATCH");
}
logl("[DSK] USER.CONF verify ok");
}
/* 2. Flip firstInit.txt: '0' -> '1',保留第二行 dev_mode 标志 */
char fn[12]; /* FIRSTINTXT */
@@ -1694,6 +1762,7 @@ static void dsk_persist_userconf(const dsk_boot_context *ctx) {
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);
if (frc != 0) dsk_fatal("FS-E03 FIRSTINIT.TXT WRITE FAILED");
/* Clear reserved so login path doesn't see stale pointer */
ctx_mut->reserved[0] = 0;
@@ -1722,6 +1791,53 @@ static void dsk_schedule_netman(const dsk_boot_context *ctx, int load_netman) {
else logl("[DSK] netman not found");
}
/* 调度 login.elf:读取 USER.CONF 传给 login,成功置 reserved[2]=1。
* 返回 1 = 登录成功;0 = 失败(调用方决定是否 fatal)。
* 首次启动(向导后强制重登)与常规启动共用此路径。 */
static int dsk_run_login(const dsk_boot_context *ctx) {
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 (dsk_load_module(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");
}
} else {
logl("[DSK] login.elf load failed");
}
} else {
logl("[DSK] login.elf not found");
}
DSK_TS_END(login_phase, "login phase");
return login_ok;
}
/* 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. */
@@ -1743,6 +1859,10 @@ static void dsk_spinner_and_check(const void *boot_ctx_ptr) {
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"); }
/* ext4 p2 数据分区挂载 + 启动读写自检(任何失败 fatal panic,FS-E2x/FS-E3x) */
ext4_mount(g_block_read, g_block_write, dsk_fatal, logl, logh);
ext4_boot_selftest();
u32 *sfb=(u32*)(u64)g_fb_addr;
logh("[DSK] block_read ptr=", (u64)g_block_read);
@@ -1809,36 +1929,28 @@ static void dsk_spinner_and_check(const void *boot_ctx_ptr) {
else logl("[DSK] compat: PE DLL search disabled");
milestone_write(3, "FUCK config loaded");
/* Gradient background + centered Logo.png (5 seconds) */
/* Gradient background + centered "DESHAB P01" text(Logo.png 图像已移除) */
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 */
/* "DESHAB P01" 文字垂直居中(不再绘制 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 */
i64 text_x = (i64)g_fb_w / 2 - text_w / 2;
i64 text_y = (i64)g_fb_h / 2 - g_ascii_h / 2;
/* 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 */
/* Hold text 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");
logl("[DSK] boot text 5s done, proceeding");
/* Follow-up splash: dcplogo.png 3s, then OpenXJ380 xjlogo.png 3s */
dsk_splash(sfb, g_dcp_logo_rgba, g_dcp_logo_w, g_dcp_logo_h,
@@ -1917,47 +2029,7 @@ static void dsk_spinner_and_check(const void *boot_ctx_ptr) {
if (skip_login || skip_firstinit) {
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");
dsk_run_login(ctx);
}
/* default_shell=cmd → 直接进 CMD.ELF(PE/EXE 兼容层前端),
@@ -2009,9 +2081,8 @@ static void dsk_spinner_and_check(const void *boot_ctx_ptr) {
en[6]='~';en[7]='1';en[8]='E';en[9]='L';en[10]='F';en[11]=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_choose_and_run_session(ctx, sfb, &dsk_cfg, dsk_cfg_ok);
/* 严格错误策略:首次启动却没有 FirstInit.elf = 未实现路径,零降级 */
dsk_fatal("FS-E07 FIRSTINIT.ELF NOT FOUND");
return;
}
logl("[DSK] FirstInit returned, persisting user.conf");
@@ -2020,6 +2091,15 @@ static void dsk_spinner_and_check(const void *boot_ctx_ptr) {
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);
/* 向导完成后强制重新登录:进桌面前必须再走一次 login.elf。
* 零降级策略:登录被跳过/失败(如 Esc 跳过)不允许静默进桌面。 */
if (skip_login) {
logl("[DSK:SCHED] first-boot login skipped by FUCK config");
} else if (!dsk_run_login(ctx)) {
dsk_fatal("FS-E06 LOGIN REQUIRED AFTER FIRSTINIT");
}
logl("[DSK] loading desktop");
milestone_write(6, "desktop loading");
dsk_choose_and_run_session(ctx, sfb, &dsk_cfg, dsk_cfg_ok);