Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion source/includes/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ typedef enum {
FS_UDF,

// OS / Custom
FS_PROC
FS_PROC,
FS_DEV
} partition_fs_type_t;


Expand Down
22 changes: 22 additions & 0 deletions source/includes/filesystems/layers/dev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @file dev.h
* @author Pradosh (pradoshgame@gmail.com)
* @brief The dev folder to handle by the VFS.
* @version 0.1
* @date 2026-04-04
*/

#ifndef DEV_H
#define DEV_H

#include <basics.h>
#include <filesystems/vfs.h>

void devfs_init(void);
int devfs_open(vfs_file_t* file);
int devfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size);
int devfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size);
void devfs_close(vfs_file_t* file);
int devfs_ls(void);

#endif
1 change: 1 addition & 0 deletions source/includes/filesystems/layers/proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ int procfs_open(vfs_file_t* file);
int procfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size);
int procfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size);
void procfs_close(vfs_file_t* file);
int procfs_ls(void);

#endif
227 changes: 227 additions & 0 deletions source/kernel/C/filesystems/layers/dev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/**
* @file dev.c
* @author Pradosh (pradoshgame@gmail.com)
* @brief The dev folder to handle by the VFS.
* @version 0.1
* @date 2026-04-04
*/

#include <filesystems/layers/dev.h>
#include <ahci.h>
#include <basics.h>
#include <graphics.h>
#include <heap.h>
#include <strings.h>

static uint64_t devfs_rng_state = 0x9E3779B97F4A7C15ULL;

static int devfs_disk_id_from_name(const char* name)
{
if (!name || !*name)
return -1;

for (int i = 0; i < block_device_count; i++) {
block_device_info_t* dev = &block_devices[i];
if (!dev->present)
continue;

if (dev->type != BLOCK_DEVICE_AHCI && dev->type != BLOCK_DEVICE_NVME)
continue;

if (strcmp(dev->name, name) == 0)
return i;
}

return -1;
}

static bool devfs_is_block_node(const char* name)
{
int id = devfs_disk_id_from_name(name);
return id >= 0;
}

void devfs_init(void) {
devfs_rng_state ^= rdtsc64();
}

static uint8_t devfs_next_rand_u8(void)
{
devfs_rng_state ^= devfs_rng_state << 13;
devfs_rng_state ^= devfs_rng_state >> 7;
devfs_rng_state ^= devfs_rng_state << 17;
return (uint8_t)(devfs_rng_state & 0xFF);
}

int devfs_open(vfs_file_t* file)
{
if (!file || !file->rel_path)
return -1;

if (file->rel_path[0] == '\0') {
file->pos = 0;
return 0;
}

if (strcmp(file->rel_path, "null") == 0 ||
strcmp(file->rel_path, "zero") == 0 ||
strcmp(file->rel_path, "random") == 0 ||
strcmp(file->rel_path, "urandom") == 0) {
file->pos = 0;
return 0;
}

if (devfs_is_block_node(file->rel_path)) {
file->pos = 0;
return 0;
}

return -1;
}

int devfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size)
{
if (!file || !buf)
return -1;

if (strcmp(file->rel_path, "null") == 0)
return 0;

if (strcmp(file->rel_path, "zero") == 0) {
memset(buf, 0, size);
file->pos += size;
return (int)size;
}

if (strcmp(file->rel_path, "random") == 0 || strcmp(file->rel_path, "urandom") == 0) {
for (uint32_t i = 0; i < size; i++)
buf[i] = devfs_next_rand_u8();
file->pos += size;
return (int)size;
}

int disk_id = devfs_disk_id_from_name(file->rel_path);
if (disk_id < 0)
return -1;

block_device_info_t* dev = block_get_device(disk_id);
if (!dev || dev->sector_size == 0)
return -1;

uint8_t* secbuf = kmalloc(dev->sector_size);
if (!secbuf)
return -1;

uint32_t done = 0;
while (done < size) {
uint64_t abs = (uint64_t)file->pos + done;
uint64_t lba = abs / dev->sector_size;
uint32_t off = abs % dev->sector_size;
uint32_t chunk = dev->sector_size - off;

if (chunk > (size - done))
chunk = size - done;

if (block_read_sector(disk_id, lba, secbuf, 1) != 0) {
kfree(secbuf);
return done > 0 ? (int)done : -1;
}

memcpy(buf + done, secbuf + off, chunk);
done += chunk;
}

kfree(secbuf);
file->pos += done;
return (int)done;
}

int devfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size)
{
if (!file || !buf)
return -1;

if (strcmp(file->rel_path, "null") == 0) {
file->pos += size;
return (int)size;
}

if (strcmp(file->rel_path, "zero") == 0)
return -1;

if (strcmp(file->rel_path, "random") == 0 || strcmp(file->rel_path, "urandom") == 0) {
file->pos += size;
return (int)size;
}

int disk_id = devfs_disk_id_from_name(file->rel_path);
if (disk_id < 0)
return -1;

block_device_info_t* dev = block_get_device(disk_id);
if (!dev || dev->sector_size == 0)
return -1;

uint8_t* secbuf = kmalloc(dev->sector_size);
if (!secbuf)
return -1;

uint32_t done = 0;
while (done < size) {
uint64_t abs = (uint64_t)file->pos + done;
uint64_t lba = abs / dev->sector_size;
uint32_t off = abs % dev->sector_size;
uint32_t chunk = dev->sector_size - off;

if (chunk > (size - done))
chunk = size - done;

if (off != 0 || chunk != dev->sector_size) {
if (block_read_sector(disk_id, lba, secbuf, 1) != 0) {
kfree(secbuf);
return done > 0 ? (int)done : -1;
}
} else {
memset(secbuf, 0, dev->sector_size);
}

memcpy(secbuf + off, buf + done, chunk);

if (block_write_sector(disk_id, lba, secbuf, 1) != 0) {
kfree(secbuf);
return done > 0 ? (int)done : -1;
}

done += chunk;
}

kfree(secbuf);
file->pos += done;
return (int)done;
}

void devfs_close(vfs_file_t* file)
{
(void)file;
}

int devfs_ls(void)
{
printfnoln(blue_color "null " reset_color);
printfnoln(blue_color "zero " reset_color);
printfnoln(blue_color "random " reset_color);
printfnoln(blue_color "urandom " reset_color);

for (int i = 0; i < block_device_count; i++) {
block_device_info_t* dev = &block_devices[i];
if (!dev->present)
continue;

if (dev->type != BLOCK_DEVICE_AHCI && dev->type != BLOCK_DEVICE_NVME)
continue;

printfnoln(blue_color "%s " reset_color, dev->name);
}

return 0;
}
35 changes: 35 additions & 0 deletions source/kernel/C/filesystems/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <graphics.h>
#include <filesystems/fat16.h>
#include <filesystems/iso9660.h>
#include <filesystems/layers/proc.h>
#include <filesystems/layers/dev.h>
#include <heap.h>
#include <strings.h>

Expand Down Expand Up @@ -143,6 +145,8 @@ int vfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size)
switch(file->mnt->type){
case FS_PROC:
return procfs_read(file, buf, size);
case FS_DEV:
return devfs_read(file, buf, size);
case FS_FAT16:
return fat16_read(&file->f.fat16, buf, size);
case FS_FAT32:
Expand Down Expand Up @@ -173,6 +177,8 @@ int vfs_write(vfs_file_t* file, const uint8_t* buf, uint32_t size)
switch(file->mnt->type){
case FS_PROC:
return -10; // not implemented
case FS_DEV:
return devfs_write(file, buf, size);
case FS_FAT16:
return fat16_write(&file->f.fat16, buf, size);
case FS_FAT32:
Expand All @@ -198,6 +204,8 @@ void vfs_close(vfs_file_t* file) {
switch(file->mnt->type){
case FS_PROC:
return; // not implemented
case FS_DEV:
return devfs_close(file);
case FS_FAT16:
return fat16_close(&file->f.fat16);
case FS_FAT32:
Expand Down Expand Up @@ -244,6 +252,12 @@ int vfs_ls(const char* path)
entries = true;
}
}
if(res.mnt->type == FS_DEV) {
if (res.rel_path[0] == '\0') {
devfs_ls();
entries = true;
}
}

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

if (res.mnt->type == FS_DEV) {
strncpy(out->rel_path, res.rel_path, sizeof(out->rel_path));
out->mnt = res.mnt;
out->flags = flags;

if (devfs_open(out) != 0)
return -1;

return 0;
}

if (res.mnt->type == FS_FAT16) {
fat16_fs_t* fs = (fat16_fs_t*)res.mnt->fs;
int ret;
Expand Down Expand Up @@ -569,6 +594,16 @@ int vfs_cd(const char* path)
return 0;
}

if (res.mnt->type == FS_DEV) {
if (*res.rel_path)
return -4;

vfs_cwd_cluster = 0;
strncpy(vfs_cwd, norm, sizeof(vfs_cwd));
vfs_cwd[sizeof(vfs_cwd) - 1] = 0;
return 0;
}

if (res.mnt->type == FS_FAT32) {
fat32_fs_t* fs = (fat32_fs_t*)res.mnt->fs;
uint32_t new_cluster = fs->root_cluster;
Expand Down
2 changes: 2 additions & 0 deletions source/kernel/C/shell/commands/lsblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static const char* fs_name(partition_fs_type_t fs)
case FS_FAT32: return "fat32";
case FS_ISO9660: return "iso9660";
case FS_PROC: return "proc";
case FS_DEV: return "dev";
default: return "unknown";
}
}
Expand Down Expand Up @@ -58,6 +59,7 @@ static const char* ro_flag_for_filesystem(partition_fs_type_t fs)
switch (fs) {
case FS_ISO9660:
case FS_PROC:
case FS_DEV:
return "1";
default:
return "0";
Expand Down
Loading