Skip to content

Commit 1edfe3d

Browse files
Add DEVFS (device filesystem) and integrate FS_DEV into VFS and tools
2 parents e27633d + 6f891c4 commit 1edfe3d

10 files changed

Lines changed: 377 additions & 2 deletions

File tree

source/includes/ahci.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ typedef enum {
182182
FS_UDF,
183183

184184
// OS / Custom
185-
FS_PROC
185+
FS_PROC,
186+
FS_DEV
186187
} partition_fs_type_t;
187188

188189

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @file dev.h
3+
* @author Pradosh (pradoshgame@gmail.com)
4+
* @brief The dev folder to handle by the VFS.
5+
* @version 0.1
6+
* @date 2026-04-04
7+
*/
8+
9+
#ifndef DEV_H
10+
#define DEV_H
11+
12+
#include <basics.h>
13+
#include <filesystems/vfs.h>
14+
15+
void devfs_init(void);
16+
int devfs_open(vfs_file_t* file);
17+
int devfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size);
18+
int devfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size);
19+
void devfs_close(vfs_file_t* file);
20+
int devfs_ls(void);
21+
22+
#endif

source/includes/filesystems/layers/proc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ int procfs_open(vfs_file_t* file);
4545
int procfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size);
4646
int procfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size);
4747
void procfs_close(vfs_file_t* file);
48+
int procfs_ls(void);
4849

4950
#endif
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/**
2+
* @file dev.c
3+
* @author Pradosh (pradoshgame@gmail.com)
4+
* @brief The dev folder to handle by the VFS.
5+
* @version 0.1
6+
* @date 2026-04-04
7+
*/
8+
9+
#include <filesystems/layers/dev.h>
10+
#include <ahci.h>
11+
#include <basics.h>
12+
#include <graphics.h>
13+
#include <heap.h>
14+
#include <strings.h>
15+
16+
static uint64_t devfs_rng_state = 0x9E3779B97F4A7C15ULL;
17+
18+
static int devfs_disk_id_from_name(const char* name)
19+
{
20+
if (!name || !*name)
21+
return -1;
22+
23+
for (int i = 0; i < block_device_count; i++) {
24+
block_device_info_t* dev = &block_devices[i];
25+
if (!dev->present)
26+
continue;
27+
28+
if (dev->type != BLOCK_DEVICE_AHCI && dev->type != BLOCK_DEVICE_NVME)
29+
continue;
30+
31+
if (strcmp(dev->name, name) == 0)
32+
return i;
33+
}
34+
35+
return -1;
36+
}
37+
38+
static bool devfs_is_block_node(const char* name)
39+
{
40+
int id = devfs_disk_id_from_name(name);
41+
return id >= 0;
42+
}
43+
44+
void devfs_init(void) {
45+
devfs_rng_state ^= rdtsc64();
46+
}
47+
48+
static uint8_t devfs_next_rand_u8(void)
49+
{
50+
devfs_rng_state ^= devfs_rng_state << 13;
51+
devfs_rng_state ^= devfs_rng_state >> 7;
52+
devfs_rng_state ^= devfs_rng_state << 17;
53+
return (uint8_t)(devfs_rng_state & 0xFF);
54+
}
55+
56+
int devfs_open(vfs_file_t* file)
57+
{
58+
if (!file || !file->rel_path)
59+
return -1;
60+
61+
if (file->rel_path[0] == '\0') {
62+
file->pos = 0;
63+
return 0;
64+
}
65+
66+
if (strcmp(file->rel_path, "null") == 0 ||
67+
strcmp(file->rel_path, "zero") == 0 ||
68+
strcmp(file->rel_path, "random") == 0 ||
69+
strcmp(file->rel_path, "urandom") == 0) {
70+
file->pos = 0;
71+
return 0;
72+
}
73+
74+
if (devfs_is_block_node(file->rel_path)) {
75+
file->pos = 0;
76+
return 0;
77+
}
78+
79+
return -1;
80+
}
81+
82+
int devfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size)
83+
{
84+
if (!file || !buf)
85+
return -1;
86+
87+
if (strcmp(file->rel_path, "null") == 0)
88+
return 0;
89+
90+
if (strcmp(file->rel_path, "zero") == 0) {
91+
memset(buf, 0, size);
92+
file->pos += size;
93+
return (int)size;
94+
}
95+
96+
if (strcmp(file->rel_path, "random") == 0 || strcmp(file->rel_path, "urandom") == 0) {
97+
for (uint32_t i = 0; i < size; i++)
98+
buf[i] = devfs_next_rand_u8();
99+
file->pos += size;
100+
return (int)size;
101+
}
102+
103+
int disk_id = devfs_disk_id_from_name(file->rel_path);
104+
if (disk_id < 0)
105+
return -1;
106+
107+
block_device_info_t* dev = block_get_device(disk_id);
108+
if (!dev || dev->sector_size == 0)
109+
return -1;
110+
111+
uint8_t* secbuf = kmalloc(dev->sector_size);
112+
if (!secbuf)
113+
return -1;
114+
115+
uint32_t done = 0;
116+
while (done < size) {
117+
uint64_t abs = (uint64_t)file->pos + done;
118+
uint64_t lba = abs / dev->sector_size;
119+
uint32_t off = abs % dev->sector_size;
120+
uint32_t chunk = dev->sector_size - off;
121+
122+
if (chunk > (size - done))
123+
chunk = size - done;
124+
125+
if (block_read_sector(disk_id, lba, secbuf, 1) != 0) {
126+
kfree(secbuf);
127+
return done > 0 ? (int)done : -1;
128+
}
129+
130+
memcpy(buf + done, secbuf + off, chunk);
131+
done += chunk;
132+
}
133+
134+
kfree(secbuf);
135+
file->pos += done;
136+
return (int)done;
137+
}
138+
139+
int devfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size)
140+
{
141+
if (!file || !buf)
142+
return -1;
143+
144+
if (strcmp(file->rel_path, "null") == 0) {
145+
file->pos += size;
146+
return (int)size;
147+
}
148+
149+
if (strcmp(file->rel_path, "zero") == 0)
150+
return -1;
151+
152+
if (strcmp(file->rel_path, "random") == 0 || strcmp(file->rel_path, "urandom") == 0) {
153+
file->pos += size;
154+
return (int)size;
155+
}
156+
157+
int disk_id = devfs_disk_id_from_name(file->rel_path);
158+
if (disk_id < 0)
159+
return -1;
160+
161+
block_device_info_t* dev = block_get_device(disk_id);
162+
if (!dev || dev->sector_size == 0)
163+
return -1;
164+
165+
uint8_t* secbuf = kmalloc(dev->sector_size);
166+
if (!secbuf)
167+
return -1;
168+
169+
uint32_t done = 0;
170+
while (done < size) {
171+
uint64_t abs = (uint64_t)file->pos + done;
172+
uint64_t lba = abs / dev->sector_size;
173+
uint32_t off = abs % dev->sector_size;
174+
uint32_t chunk = dev->sector_size - off;
175+
176+
if (chunk > (size - done))
177+
chunk = size - done;
178+
179+
if (off != 0 || chunk != dev->sector_size) {
180+
if (block_read_sector(disk_id, lba, secbuf, 1) != 0) {
181+
kfree(secbuf);
182+
return done > 0 ? (int)done : -1;
183+
}
184+
} else {
185+
memset(secbuf, 0, dev->sector_size);
186+
}
187+
188+
memcpy(secbuf + off, buf + done, chunk);
189+
190+
if (block_write_sector(disk_id, lba, secbuf, 1) != 0) {
191+
kfree(secbuf);
192+
return done > 0 ? (int)done : -1;
193+
}
194+
195+
done += chunk;
196+
}
197+
198+
kfree(secbuf);
199+
file->pos += done;
200+
return (int)done;
201+
}
202+
203+
void devfs_close(vfs_file_t* file)
204+
{
205+
(void)file;
206+
}
207+
208+
int devfs_ls(void)
209+
{
210+
printfnoln(blue_color "null " reset_color);
211+
printfnoln(blue_color "zero " reset_color);
212+
printfnoln(blue_color "random " reset_color);
213+
printfnoln(blue_color "urandom " reset_color);
214+
215+
for (int i = 0; i < block_device_count; i++) {
216+
block_device_info_t* dev = &block_devices[i];
217+
if (!dev->present)
218+
continue;
219+
220+
if (dev->type != BLOCK_DEVICE_AHCI && dev->type != BLOCK_DEVICE_NVME)
221+
continue;
222+
223+
printfnoln(blue_color "%s " reset_color, dev->name);
224+
}
225+
226+
return 0;
227+
}

source/kernel/C/filesystems/vfs.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <graphics.h>
1515
#include <filesystems/fat16.h>
1616
#include <filesystems/iso9660.h>
17+
#include <filesystems/layers/proc.h>
18+
#include <filesystems/layers/dev.h>
1719
#include <heap.h>
1820
#include <strings.h>
1921

@@ -143,6 +145,8 @@ int vfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size)
143145
switch(file->mnt->type){
144146
case FS_PROC:
145147
return procfs_read(file, buf, size);
148+
case FS_DEV:
149+
return devfs_read(file, buf, size);
146150
case FS_FAT16:
147151
return fat16_read(&file->f.fat16, buf, size);
148152
case FS_FAT32:
@@ -173,6 +177,8 @@ int vfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size)
173177
switch(file->mnt->type){
174178
case FS_PROC:
175179
return -10; // not implemented
180+
case FS_DEV:
181+
return devfs_write(file, buf, size);
176182
case FS_FAT16:
177183
return fat16_write(&file->f.fat16, buf, size);
178184
case FS_FAT32:
@@ -198,6 +204,8 @@ void vfs_close(vfs_file_t* file) {
198204
switch(file->mnt->type){
199205
case FS_PROC:
200206
return; // not implemented
207+
case FS_DEV:
208+
return devfs_close(file);
201209
case FS_FAT16:
202210
return fat16_close(&file->f.fat16);
203211
case FS_FAT32:
@@ -244,6 +252,12 @@ int vfs_ls(const char* path)
244252
entries = true;
245253
}
246254
}
255+
if(res.mnt->type == FS_DEV) {
256+
if (res.rel_path[0] == '\0') {
257+
devfs_ls();
258+
entries = true;
259+
}
260+
}
247261

248262
if (res.mnt->type == FS_FAT16) {
249263
fat16_fs_t* fs = (fat16_fs_t*)res.mnt->fs;
@@ -348,6 +362,17 @@ int vfs_open(const char* path, int flags, vfs_file_t* out)
348362
return 0;
349363
}
350364

365+
if (res.mnt->type == FS_DEV) {
366+
strncpy(out->rel_path, res.rel_path, sizeof(out->rel_path));
367+
out->mnt = res.mnt;
368+
out->flags = flags;
369+
370+
if (devfs_open(out) != 0)
371+
return -1;
372+
373+
return 0;
374+
}
375+
351376
if (res.mnt->type == FS_FAT16) {
352377
fat16_fs_t* fs = (fat16_fs_t*)res.mnt->fs;
353378
int ret;
@@ -569,6 +594,16 @@ int vfs_cd(const char* path)
569594
return 0;
570595
}
571596

597+
if (res.mnt->type == FS_DEV) {
598+
if (*res.rel_path)
599+
return -4;
600+
601+
vfs_cwd_cluster = 0;
602+
strncpy(vfs_cwd, norm, sizeof(vfs_cwd));
603+
vfs_cwd[sizeof(vfs_cwd) - 1] = 0;
604+
return 0;
605+
}
606+
572607
if (res.mnt->type == FS_FAT32) {
573608
fat32_fs_t* fs = (fat32_fs_t*)res.mnt->fs;
574609
uint32_t new_cluster = fs->root_cluster;

source/kernel/C/shell/commands/lsblk.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static const char* fs_name(partition_fs_type_t fs)
2929
case FS_FAT32: return "fat32";
3030
case FS_ISO9660: return "iso9660";
3131
case FS_PROC: return "proc";
32+
case FS_DEV: return "dev";
3233
default: return "unknown";
3334
}
3435
}
@@ -58,6 +59,7 @@ static const char* ro_flag_for_filesystem(partition_fs_type_t fs)
5859
switch (fs) {
5960
case FS_ISO9660:
6061
case FS_PROC:
62+
case FS_DEV:
6163
return "1";
6264
default:
6365
return "0";

0 commit comments

Comments
 (0)