Files
Deshab-OS/CODE/tools/diskinfo/main.c
T
LinehuandCursor 8554a82677 feat(panic): FUCK [panic] mode=strict|fallback + realtest image variant
- UTSM panic_full returns in fallback mode (logs [PANIC:FALLBACK] + code + hit
  count); panic_halt keeps always-halt sites (CPU exception, VMM-E11 LA57,
  VMM-E15 DSK jump, UTSM-E42 test hook). Call sites given safe continuations.
- Mode passed to DSK/FirstInit/login/desktop via DSK_BOOT_FLAG_PANIC_FALLBACK;
  DKM kernel_api.panic / kern.log.panic return to driver; ext4 fatal aborts the
  op via setjmp/longjmp and DSK falls back to FAT32 ESP.
- build.ps1/Makefile: dev=strict, release=fallback, new realtest (release
  options + strict); default -Variant all; serialized iso packing under -j.
- Fix '*/' inside comments (dkm.h, kernel_api.h, bus.c) that broke the build.
- Includes pending work: dkm_bus service bus, mt7920/wlan drivers, desktop
  files/startmenu/prank, pe-tools, diskinfo, docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 23:57:19 +08:00

254 lines
9.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* diskinfo — Deshab 磁盘工具(diskpart 风格,ELF 全屏工具)
*
* 展示:block 设备清单、GPT 分区表(类型/起始/大小)、ESP FAT32
* 容量统计(总簇/空闲簇/已用%)。只读,不写盘。
*
* 构建: cd CODE/tools/diskinfo ; make
* 输出: SYSTEM/bin/diskinfo.elf(开始菜单 bin/xxx.elf 条目启动)
*/
#include "../../firstInit/ascii_bitmaps.c"
#include "../../sdk/include/deshab/deshab.h"
#include "../../sdk/include/deshab/font.h"
#include "../../tools/fat32_part.h"
static dsb_app_context g_ac;
/* ---- 简易格式化 ---- */
static char *fmt_hex(u64 v, char *buf) {
static const char hx[] = "0123456789ABCDEF";
int n = 0;
char tmp[18];
if (!v) { buf[0] = '0'; buf[1] = 0; return buf; }
while (v && n < 16) { tmp[n++] = hx[v & 0xF]; v >>= 4; }
buf[0] = '0'; buf[1] = 'x';
for (int i = 0; i < n; i++) buf[2 + i] = tmp[n - 1 - i];
buf[2 + n] = 0;
return buf;
}
static char *fmt_dec(u64 v, char *buf) {
char tmp[24]; int n = 0;
if (!v) { buf[0] = '0'; buf[1] = 0; return buf; }
while (v && n < 23) { tmp[n++] = (char)('0' + v % 10); v /= 10; }
for (int i = 0; i < n; i++) buf[i] = tmp[n - 1 - i];
buf[n] = 0;
return buf;
}
/* 拼接:a " / " b */
static char *fmt_pair(u64 a, u64 b, char *buf) {
char t1[24], t2[24];
int i = 0;
const char *s = fmt_dec(a, t1);
while (s[i] && i < 40) { buf[i] = s[i]; i++; }
buf[i++] = ' '; buf[i++] = '/'; buf[i++] = ' ';
const char *s2 = fmt_dec(b, t2);
int j = 0;
while (s2[j] && i < 44) buf[i++] = s2[j++];
buf[i] = 0;
return buf;
}
#define INFO_X 12
#define INFO_Y_START (DSB_TITLEBAR_H + 8)
#define LINE_H 20
#define COL_LABEL_W 190
static int g_line = 0;
static void info_line(const char *label, const char *value, u32 val_color) {
i64 y = INFO_Y_START + (i64)g_line * LINE_H;
dsb_draw_string(&g_ac, label, INFO_X, y, DSB_TEXT_DIM, DSB_BG_PRIMARY, 12);
dsb_draw_string(&g_ac, value, INFO_X + COL_LABEL_W, y, val_color, DSB_BG_PRIMARY, 12);
g_line++;
}
static void info_section(const char *title) {
i64 y = INFO_Y_START + (i64)g_line * LINE_H;
dsb_draw_string(&g_ac, title, INFO_X, y, DSB_ACCENT_LIGHT, DSB_BG_PRIMARY, 12);
dsb_fill_rect(&g_ac, INFO_X, y + 16, (i64)g_ac.fb_w - INFO_X * 2, 1, DSB_BORDER);
g_line += 2;
}
/* ---- 静态读缓冲 ---- */
static u8 g_sec[512]; /* MBR / GPT 头 / BPB */
static u8 g_ptes[16384]; /* GPT 分区项(128 项 × 128B = 16KB) */
static u8 g_fat[65536]; /* FAT 扫描块(128 扇区) */
static u64 rd64(const u8 *p) {
return (u64)p[0] | ((u64)p[1] << 8) | ((u64)p[2] << 16) | ((u64)p[3] << 24)
| ((u64)p[4] << 32) | ((u64)p[5] << 40) | ((u64)p[6] << 48)
| ((u64)p[7] << 56);
}
static u32 rd32(const u8 *p) {
return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24);
}
/* block read 直通(fat32_part_probe 回调签名) */
static int blk_read(u32 index, u64 lba, u32 count, void *buf) {
return g_ac.block.read ? g_ac.block.read(index, lba, count, buf) : -1;
}
void dsk_entry(const dsk_boot_context *ctx) {
if (ctx->magic != DSK_BOOT_MAGIC) return;
dsb_app_init(&g_ac, ctx);
char buf[64];
dsb_fill_bg(&g_ac, DSB_BG_PRIMARY);
dsb_draw_titlebar(&g_ac, "DiskInfo - diskpart style", (i64)g_ac.fb_w);
dsb_draw_statusbar(&g_ac, "read-only tool, Esc to exit",
(i64)g_ac.fb_w, (i64)g_ac.fb_h);
/* ---- Block 设备 ---- */
const dkm_kernel_api *api = g_ac.api;
if (!api || !api->block || !api->block->device_count) {
info_section("== Block Devices ==");
info_line("block api", "unavailable", DSB_ERROR);
goto wait_esc;
}
{
u32 ndev = api->block->device_count();
info_section("== Block Devices ==");
info_line("device_count", fmt_dec(ndev, buf), DSB_TEXT_PRIMARY);
for (u32 i = 0; i < ndev && i < 4; i++) {
char label[16];
label[0] = 'd'; label[1] = 'e'; label[2] = 'v'; label[3] = '[';
label[4] = (char)('0' + i); label[5] = ']'; label[6] = 0;
const char *name = api->block->device_name
? api->block->device_name(i) : "?";
info_line(label, name ? name : "?", DSB_ACCENT_LIGHT);
if (api->block->sector_size)
info_line(" sector_size", fmt_dec(api->block->sector_size(i), buf),
DSB_TEXT_PRIMARY);
if (api->block->sector_count)
info_line(" sector_count", fmt_dec(api->block->sector_count(i), buf),
DSB_TEXT_PRIMARY);
}
}
/* ---- GPT 分区表 ---- */
info_section("== GPT Partitions (disk 0) ==");
if (blk_read(0, 1, 1, g_sec) != 0) {
info_line("read LBA1", "failed", DSB_ERROR);
goto wait_esc;
}
if (!(g_sec[0]=='E' && g_sec[1]=='F' && g_sec[2]=='I' && g_sec[3]==' ' &&
g_sec[4]=='P' && g_sec[5]=='A' && g_sec[6]=='R' && g_sec[7]=='T')) {
info_line("signature", "not GPT (MBR raw?)", DSB_WARNING);
goto wait_esc;
}
{
u64 pte_lba = rd64(g_sec + 72);
u32 nent = rd32(g_sec + 80);
u32 esz = rd32(g_sec + 84);
if (esz == 0 || esz > 512) esz = 128;
if (nent > 128) nent = 128;
info_line("entry_lba", fmt_dec(pte_lba, buf), DSB_TEXT_PRIMARY);
info_line("entries", fmt_dec(nent, buf), DSB_TEXT_PRIMARY);
/* 读 128 项 × 128B = 32 扇区 */
if (blk_read(0, pte_lba, 32, g_ptes) != 0) {
info_line("read PTEs", "failed", DSB_ERROR);
goto wait_esc;
}
int shown = 0;
for (u32 i = 0; i < nent; i++) {
const u8 *e = g_ptes + (u64)i * esz;
int used = 0;
for (int k = 0; k < 16; k++) if (e[k]) { used = 1; break; }
if (!used) continue;
u64 first = rd64(e + 32), last = rd64(e + 40);
int is_esp = 1;
for (int k = 0; k < 16; k++)
if (e[k] != fat32_part_esp_guid[k]) { is_esp = 0; break; }
char lb[24];
lb[0] = 'p'; lb[1] = (char)('1' + i);
lb[2] = is_esp ? '*' : ' ';
lb[3] = 0;
/* 类型 GUID 前 4 字节 + 起始 LBA */
char tv[20];
static const char hx[] = "0123456789ABCDEF";
tv[0] = 't'; tv[1] = 'y'; tv[2] = 'p'; tv[3] = 'e'; tv[4] = '=';
for (int k = 0; k < 4; k++) {
tv[5 + k * 2] = hx[e[k] >> 4];
tv[6 + k * 2] = hx[e[k] & 0xF];
}
tv[13] = 0;
info_line(lb, tv, is_esp ? DSB_ACCENT_LIGHT : DSB_TEXT_PRIMARY);
info_line(" first_lba", fmt_dec(first, buf), DSB_TEXT_DIM);
info_line(" sectors", fmt_dec(last - first + 1, buf), DSB_TEXT_DIM);
shown++;
if (shown >= 8) break;
}
if (!shown) info_line("(no partitions)", "", DSB_TEXT_DIM);
}
/* ---- ESP FAT32 容量 ---- */
info_section("== FAT32 Volume (ESP) ==");
{
u64 base = fat32_part_probe(blk_read, 0);
/* probe 语义:0 = superfloppy(BPB 在 LBA0)或失败;>0 = ESP LBA */
if (blk_read(0, base, 1, g_sec) != 0) {
info_line("read BPB", "failed", DSB_ERROR);
goto wait_esc;
}
if (!fat32_part_bpb_ok(g_sec)) {
info_line("BPB", "invalid", DSB_ERROR);
goto wait_esc;
}
u32 spc = g_sec[13];
u32 rsv = (u32)g_sec[14] | ((u32)g_sec[15] << 8);
u32 nfat = g_sec[16];
u32 spf = rd32(g_sec + 36); /* BPB_FATSz32 */
u32 rootc = rd32(g_sec + 44); /* BPB_RootClus */
u64 tot = rd32(g_sec + 32); /* BPB_TotSec32 */
u64 data_sec = rsv + (u64)nfat * spf;
u64 nclus = (tot > data_sec) ? (tot - data_sec) / spc : 0;
{
char lb[16];
for (int i = 0; i < 11; i++) lb[i] = (char)g_sec[71 + i];
lb[11] = 0;
info_line("label", lb, DSB_ACCENT_LIGHT);
}
info_line("bytes/sector", "512", DSB_TEXT_PRIMARY);
info_line("sectors/cluster", fmt_dec(spc, buf), DSB_TEXT_PRIMARY);
info_line("FAT size(sec x n)", fmt_pair(spf, nfat, buf), DSB_TEXT_PRIMARY);
info_line("root_cluster", fmt_dec(rootc, buf), DSB_TEXT_PRIMARY);
info_line("total clusters", fmt_dec(nclus, buf), DSB_TEXT_PRIMARY);
/* 空闲簇扫描:FAT 区按 64KB 块读,统计 (i>=2 && entry==0) */
if (spf) {
u64 fat_lba = base + rsv;
u64 fat_ent = (u64)spf * 512 / 4;
if (fat_ent > nclus + 2) fat_ent = nclus + 2;
u64 free_c = 0;
u32 chunk_sec = sizeof(g_fat) / 512; /* 128 扇区/块 */
u32 ents_per_chunk = chunk_sec * 128; /* FAT 项/块 */
u64 chunks = (fat_ent + ents_per_chunk - 1) / ents_per_chunk;
for (u64 ch = 0; ch < chunks; ch++) {
if (blk_read(0, fat_lba + ch * chunk_sec, chunk_sec, g_fat) != 0)
break;
for (u32 k = 0; k < ents_per_chunk; k++) {
u64 idx = ch * ents_per_chunk + k;
if (idx < 2 || idx >= fat_ent) continue;
u32 v = rd32(g_fat + k * 4) & 0x0FFFFFFFu;
if (v == 0) free_c++;
}
}
info_line("free clusters", fmt_dec(free_c, buf), DSB_SUCCESS);
if (nclus) {
u64 used_pct = (nclus - free_c) * 100 / nclus;
info_line("used", fmt_pair(used_pct, 100, buf), DSB_WARNING);
}
}
}
wait_esc:
/* 等待 Esc 退出 */
for (;;) {
u8 st = dsb_inb(0x64);
if (st & 1) {
u8 sc = dsb_inb(0x60);
if (sc == 1) break; /* Esc make code */
}
__asm__ volatile("pause");
}
}