ohhhhhhhhhhh (exclude linux-extra-rootfs.img build artifact)
This commit is contained in:
+67
-21
@@ -22,6 +22,7 @@
|
||||
#define DESHAB_FAT32_IO_H
|
||||
|
||||
#include "fat32_lfn.h"
|
||||
#include "fat32_part.h"
|
||||
|
||||
/* ---- block 设备函数类型(与 shell/DSK 一致:index 参数固定 0) ---- */
|
||||
typedef int (*f32_block_read_fn)(u32 index, u64 lba, u32 count, void *buf);
|
||||
@@ -60,27 +61,39 @@ static inline int f32_neq11(const char *a, const char *b) {
|
||||
#define F32_DATA_BYTES 262144
|
||||
#endif
|
||||
static u8 f32_disk[131072]; /* 256 扇区 BPB+FAT+根目录缓存 */
|
||||
static u8 f32_cluster[4096]; /* 单簇缓冲 */
|
||||
static u8 f32_cluster[FAT32_MAX_CLUSTER_BYTES]; /* 单簇缓冲:ESP>=4GiB 时为 32KiB */
|
||||
static u8 f32_data[F32_DATA_BYTES]; /* 文件数据缓冲 */
|
||||
static int f32_disk_loaded = 0; /* f32_disk 是否已加载 BPB+FAT */
|
||||
static u32 f32_lba_base = 0; /* GPT ESP start (0 for superfloppy / SATA) */
|
||||
|
||||
/* 初始化:注入 block_read/block_write 函数指针 */
|
||||
static inline void f32_init(f32_block_read_fn rd, f32_block_write_fn wr) {
|
||||
f32_blk_read = rd;
|
||||
f32_blk_write = wr;
|
||||
f32_disk_loaded = 0;
|
||||
f32_lba_base = 0;
|
||||
}
|
||||
|
||||
static inline int f32_read_sectors(u32 lba, u32 count, u8 *out) {
|
||||
return f32_blk_read ? f32_blk_read(0, lba, count, out) : -1;
|
||||
return f32_blk_read ? f32_blk_read(0, (u64)lba + f32_lba_base, count, out) : -1;
|
||||
}
|
||||
static inline int f32_write_sectors(u32 lba, u32 count, const u8 *buf) {
|
||||
return f32_blk_write ? f32_blk_write(0, lba, count, buf) : -1;
|
||||
return f32_blk_write ? f32_blk_write(0, (u64)lba + f32_lba_base, count, buf) : -1;
|
||||
}
|
||||
|
||||
static inline int f32_bpb_ok_at(u32 abs_lba) {
|
||||
u8 sec[512];
|
||||
const f32_bpb *bpb;
|
||||
if (!f32_blk_read || f32_blk_read(0, abs_lba, 1, sec) != 0) return 0;
|
||||
bpb = (const f32_bpb *)sec;
|
||||
return (bpb->boot_sig == 0xAA55 && bpb->bps == 512 && bpb->spf != 0 && bpb->root_clus >= 2);
|
||||
}
|
||||
|
||||
/* 确保 f32_disk 已加载 BPB+FAT+根目录(256 扇区) */
|
||||
static inline int f32_disk_load(void) {
|
||||
if (f32_disk_loaded) return 0;
|
||||
f32_lba_base = (u32)fat32_part_probe(f32_blk_read, 0);
|
||||
if (!f32_bpb_ok_at(f32_lba_base)) return -2;
|
||||
if (f32_read_sectors(0, 256, f32_disk) != 0) return -1;
|
||||
const f32_bpb *bpb = (const f32_bpb *)f32_disk;
|
||||
if (bpb->boot_sig != 0xAA55 || bpb->bps != 512) return -2;
|
||||
@@ -177,7 +190,7 @@ static inline int f32_read_root_file(const char *name11, u8 **out_data, u32 *out
|
||||
if ((u64)lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
cb = f32_disk + (u64)lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(lba, 8, f32_cluster) != 0) return -4;
|
||||
if (f32_read_sectors(lba, spc, f32_cluster) != 0) return -4;
|
||||
cb = f32_cluster;
|
||||
}
|
||||
if (f32_find_in_root(cb, spc, name11, &found_clus, &found_size, 0) == 0) { found = 1; break; }
|
||||
@@ -197,7 +210,7 @@ static inline int f32_read_root_file(const char *name11, u8 **out_data, u32 *out
|
||||
if ((u64)fc_lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
fb = f32_disk + (u64)fc_lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(fc_lba, 8, f32_cluster) != 0) return -7;
|
||||
if (f32_read_sectors(fc_lba, spc, f32_cluster) != 0) return -7;
|
||||
fb = f32_cluster;
|
||||
}
|
||||
for (u32 b = 0; b < fc_bytes; b++) dst[b] = fb[b];
|
||||
@@ -662,7 +675,7 @@ static inline int f32_list_root(f32_list_cb emit, void *user_data) {
|
||||
if ((u64)lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
cb = f32_disk + (u64)lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(lba, 8, f32_cluster) != 0) return -4;
|
||||
if (f32_read_sectors(lba, spc, f32_cluster) != 0) return -4;
|
||||
cb = f32_cluster;
|
||||
}
|
||||
const f32_dirent *dir = (const f32_dirent *)cb;
|
||||
@@ -685,18 +698,7 @@ done:
|
||||
|
||||
/* ---- 子目录遍历支持(Phase 2.2 fileman 扩展) ---- */
|
||||
|
||||
/* 目录条目(供 fileman 等工具使用) */
|
||||
typedef struct {
|
||||
char name[13]; /* 8.3 显示名 */
|
||||
u32 clus; /* 首簇号 */
|
||||
u32 size; /* 文件大小(目录为 0) */
|
||||
u8 attr;
|
||||
u8 is_dir;
|
||||
u8 has_lfn; /* 1=long_name 字段有效 */
|
||||
char long_name[260]; /* LFN 长文件名(ASCII) */
|
||||
} f32_entry;
|
||||
|
||||
typedef int (*f32_list_entry_cb)(const f32_entry *e, void *user_data);
|
||||
/* f32_entry / f32_list_entry_cb 定义已移至 fat32_lfn.h(本头包含之)。 */
|
||||
|
||||
/* 列举指定目录簇的内容(含 LFN 长文件名)。
|
||||
* dir_clus = 0 表示根目录(自动从 BPB 取 root_clus)。
|
||||
@@ -717,7 +719,7 @@ static inline int f32_list_dir(u32 dir_clus, f32_list_entry_cb emit, void *user_
|
||||
if ((u64)lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
cb = f32_disk + (u64)lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(lba, 8, f32_cluster) != 0) return -4;
|
||||
if (f32_read_sectors(lba, spc, f32_cluster) != 0) return -4;
|
||||
cb = f32_cluster;
|
||||
}
|
||||
const u8 *entries = (const u8 *)cb;
|
||||
@@ -781,7 +783,7 @@ static inline int f32_read_file_by_clus(u32 clus, u32 size, u8 *out_buf, u32 buf
|
||||
if ((u64)fc_lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
fb = f32_disk + (u64)fc_lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(fc_lba, 8, f32_cluster) != 0) return -7;
|
||||
if (f32_read_sectors(fc_lba, spc, f32_cluster) != 0) return -7;
|
||||
fb = f32_cluster;
|
||||
}
|
||||
for (u32 b = 0; b < fc_bytes; b++) dst[b] = fb[b];
|
||||
@@ -822,7 +824,7 @@ static inline int f32_find_in_dir_lfn(u32 dir_clus, const char *long_name,
|
||||
if ((u64)lba * 512 + (u64)spc * 512 <= 256ULL * 512)
|
||||
cb = f32_disk + (u64)lba * 512;
|
||||
else {
|
||||
if (f32_read_sectors(lba, 8, f32_cluster) != 0) return -4;
|
||||
if (f32_read_sectors(lba, spc, f32_cluster) != 0) return -4;
|
||||
cb = f32_cluster;
|
||||
}
|
||||
const u8 *entries = (const u8 *)cb;
|
||||
@@ -961,6 +963,50 @@ static inline int f32_read_path_lfn(const char *path, u8 **out_data, u32 *out_si
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 按长路径读取文件到调用者指定缓冲(流式直读,绕过 f32_data 尺寸上限)。
|
||||
* path : '/' 分隔的长文件名路径(如 "system/font/simhei_16.dbf")
|
||||
* dst : 目标缓冲(如固定地址字库区)
|
||||
* cap : 缓冲容量(字节)
|
||||
* out_size : 返回文件大小(可为 0)
|
||||
* 返回 0 成功,负值失败(-4 = 文件超过 cap)。 */
|
||||
static inline int f32_read_path_lfn_to(const char *path, u8 *dst, u32 cap, u32 *out_size) {
|
||||
if (!path || !dst) return -1;
|
||||
if (f32_disk_load() != 0) return -1;
|
||||
|
||||
/* 分离目录部分与文件名 */
|
||||
u32 path_len = 0;
|
||||
while (path[path_len]) path_len++;
|
||||
u32 last_slash = 0xFFFFFFFFu;
|
||||
for (u32 i = 0; i < path_len; i++) {
|
||||
if (path[i] == '/') last_slash = i;
|
||||
}
|
||||
const char *fname = (last_slash == 0xFFFFFFFFu) ? path : path + last_slash + 1;
|
||||
|
||||
/* 定位父目录簇 */
|
||||
u32 dir_clus = 0;
|
||||
if (last_slash == 0xFFFFFFFFu) {
|
||||
const f32_bpb *bpb = (const f32_bpb *)f32_disk;
|
||||
dir_clus = bpb->root_clus;
|
||||
} else {
|
||||
char dirpath[260];
|
||||
u32 dn = last_slash;
|
||||
if (dn >= sizeof(dirpath)) dn = sizeof(dirpath) - 1;
|
||||
for (u32 i = 0; i < dn; i++) dirpath[i] = path[i];
|
||||
dirpath[dn] = 0;
|
||||
if (f32_find_path_dir_lfn(dirpath, &dir_clus) != 0) return -2;
|
||||
}
|
||||
|
||||
/* 在父目录中查找文件 */
|
||||
u32 file_clus = 0, file_size = 0;
|
||||
if (f32_find_in_dir_lfn(dir_clus, fname, 0, &file_clus, &file_size) != 0) return -3;
|
||||
if (file_size > cap) return -4;
|
||||
|
||||
/* 读取文件数据到目标缓冲 */
|
||||
if (f32_read_file_by_clus(file_clus, file_size, dst, cap) != 0) return -5;
|
||||
if (out_size) *out_size = file_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 按长路径写入文件(存在则替换,不存在则在父目录中新建 8.3 项)。
|
||||
* path : '/' 分隔路径(如 "system/deshab64/FUCK"),文件名段必须可转 8.3
|
||||
* 返回 0 成功,负值失败(-6 = 文件名不是合法 8.3)。 */
|
||||
|
||||
@@ -42,6 +42,19 @@ typedef struct {
|
||||
int valid; /* 1=LFN 链完整且 checksum 与短名项匹配 */
|
||||
} fat32_lfn_buf;
|
||||
|
||||
/* 目录条目(供 fileman / linux_compat 列举使用)。 */
|
||||
typedef struct {
|
||||
char name[13];
|
||||
u32 clus;
|
||||
u32 size;
|
||||
u8 attr;
|
||||
u8 is_dir;
|
||||
u8 has_lfn;
|
||||
char long_name[260];
|
||||
} f32_entry;
|
||||
|
||||
typedef int (*f32_list_entry_cb)(const f32_entry *e, void *user_data);
|
||||
|
||||
/* 初始化/清空 LFN 缓冲 */
|
||||
static inline void fat32_lfn_init(fat32_lfn_buf *buf) {
|
||||
buf->count = 0;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/* fat32_part.h — locate a FAT32 volume on a superfloppy or GPT ESP.
|
||||
*
|
||||
* Callers already define u8/u16/u32/u64. The read callback matches
|
||||
* dkm_block_api.read: (index, lba, count, buf).
|
||||
*/
|
||||
#ifndef DESHAB_FAT32_PART_H
|
||||
#define DESHAB_FAT32_PART_H
|
||||
|
||||
/* pack_system_image.sh uses 64 sectors/cluster (32KiB) when the ESP is >= 4GiB.
|
||||
* Every FAT32 cluster buffer in DSK/UTSM/userland must cover that size. */
|
||||
#ifndef FAT32_MAX_CLUSTER_BYTES
|
||||
#define FAT32_MAX_CLUSTER_BYTES 32768u
|
||||
#endif
|
||||
|
||||
typedef int (*fat32_part_read_fn)(u32 index, u64 lba, u32 count, void *buf);
|
||||
|
||||
static inline int fat32_part_bpb_ok(const u8 *sec) {
|
||||
u32 spf;
|
||||
if (!sec) return 0;
|
||||
if (sec[510] != 0x55 || sec[511] != 0xAA) return 0;
|
||||
if (sec[11] != 0x00 || sec[12] != 0x02) return 0; /* 512-byte sectors */
|
||||
spf = (u32)sec[36] | ((u32)sec[37] << 8) | ((u32)sec[38] << 16) | ((u32)sec[39] << 24);
|
||||
if (spf == 0) return 0;
|
||||
if (sec[13] == 0) return 0; /* sectors per cluster */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline u64 fat32_part_r64(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);
|
||||
}
|
||||
|
||||
/* EFI System Partition type GUID c12a7328-f81f-11d2-ba4b-00a0c93ec93b */
|
||||
static const u8 fat32_part_esp_guid[16] = {
|
||||
0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
|
||||
0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b
|
||||
};
|
||||
|
||||
/* Return the LBA of the FAT32 BPB relative to the whole disk.
|
||||
* 0 means LBA0 is already a FAT32 superfloppy (or probe failed). */
|
||||
static inline u64 fat32_part_probe(fat32_part_read_fn rd, u32 index) {
|
||||
u8 sec[512];
|
||||
u32 i, ent_size;
|
||||
u64 entries_lba;
|
||||
if (!rd) return 0;
|
||||
if (rd(index, 0, 1, sec) == 0 && fat32_part_bpb_ok(sec)) return 0;
|
||||
if (rd(index, 1, 1, sec) == 0 &&
|
||||
sec[0] == 'E' && sec[1] == 'F' && sec[2] == 'I' && sec[3] == ' ' &&
|
||||
sec[4] == 'P' && sec[5] == 'A' && sec[6] == 'R' && sec[7] == 'T') {
|
||||
entries_lba = fat32_part_r64(sec + 72);
|
||||
ent_size = (u32)sec[84] | ((u32)sec[85] << 8)
|
||||
| ((u32)sec[86] << 16) | ((u32)sec[87] << 24);
|
||||
if (ent_size == 0) ent_size = 128;
|
||||
if (entries_lba == 0) entries_lba = 2;
|
||||
if (rd(index, entries_lba, 1, sec) == 0 && ent_size >= 40 && ent_size <= 512) {
|
||||
for (i = 0; i + ent_size <= 512; i += ent_size) {
|
||||
u32 j, match = 1;
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (sec[i + j] != fat32_part_esp_guid[j]) { match = 0; break; }
|
||||
}
|
||||
if (match) return fat32_part_r64(sec + i + 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rd(index, 2048, 1, sec) == 0 && fat32_part_bpb_ok(sec)) return 2048;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DESHAB_FAT32_PART_H */
|
||||
Reference in New Issue
Block a user