diff --git a/src/os/src/kernel/drivers/dev/pci.ts b/src/os/src/kernel/drivers/dev/pci.ts index 2ab0031..299bc30 100644 --- a/src/os/src/kernel/drivers/dev/pci.ts +++ b/src/os/src/kernel/drivers/dev/pci.ts @@ -1,6 +1,8 @@ import { dwordin, dwordout } from "../../../lib/libts/dword"; import { portin, portout } from "../../../lib/libts/port"; import { Logger } from "../../../lib/libstd/logger/logger.kmod"; +import { sysfs_mkdir, sysfs_writeFile } from "../../filesystem/sysfs"; +import { Path } from "../../../lib/libstd/path"; const KDRIVER_PCI_CONFIG_ADDR = 0xcf8; const KDRIVER_PCI_CONFIG_DATA = 0xcfc; @@ -37,13 +39,11 @@ export function kdriver_dev_pci_checkDevice( const classCode = kdriver_dev_pci_getClassCode(bus, device, func); const subclass = kdriver_dev_pci_getSubclass(bus, device, func); + const filename = bus + ":" + device + ":" + func; + Logger.log( "[PCI] Found device pci:" + - bus + - ":" + - device + - ":" + - func + + filename + " (vendor:" + vendorId.toString(16) + ", device:" + @@ -54,6 +54,14 @@ export function kdriver_dev_pci_checkDevice( subclass.toString(16) + ")" ); + + const dirname = Path.join("/pci", filename); + + sysfs_mkdir(dirname); + sysfs_writeFile(Path.join(dirname, "vendor"), vendorId); + sysfs_writeFile(Path.join(dirname, "device"), deviceId); + sysfs_writeFile(Path.join(dirname, "class"), classCode); + sysfs_writeFile(Path.join(dirname, "subclass"), subclass); } export function kdriver_dev_pci_getDeviceId( diff --git a/src/os/src/kernel/filesystem/sysfs.ts b/src/os/src/kernel/filesystem/sysfs.ts new file mode 100644 index 0000000..33e98af --- /dev/null +++ b/src/os/src/kernel/filesystem/sysfs.ts @@ -0,0 +1,138 @@ +import { Logger } from "../../lib/libstd/logger/logger.kmod"; +import { Path } from "../../lib/libstd/path"; +import type { + KFilesystemDriver, + KFilesystemEntity, + KFilesystemMemdata, + KFilesystemStat, +} from "../../types/filesystem/fs"; + +const sysfs_data: KFilesystemMemdata = []; + +export function sysfs_driver(): KFilesystemDriver { + return { + id: "sysfs", + init: sysfs_init, + listDir(path: string): KFilesystemEntity[] | null { + return sysfs_listDir(path); + }, + readFile(path: string): unknown { + return sysfs_readFile(path); + }, + writeFile(path: string, content: unknown): void { + throw new Error("Cannot write to sysfs files."); + }, + createFile(path: string, content: unknown): void { + throw new Error("Cannot create files in sysfs."); + }, + mkdir(path: string): void { + throw new Error("Cannot create directories in sysfs."); + }, + stat(path: string): KFilesystemStat | null { + return sysfs_statEntity(path); + }, + }; +} + +export function sysfs_init(): void { + sysfs_data.push({ + name: "root", + path: "/", + type: "folder", + size: 0, + contents: null, + }); + + sysfs_mkdir("/pci"); +} + +export function sysfs_getEntity(path: string): KFilesystemEntity | null { + for (let i = 0; i < sysfs_data.length; i++) { + const entity = sysfs_data[i]!; + + if (entity.path === path) return entity; + } + + return null; +} + +export function sysfs_statEntity(path: string): KFilesystemStat | null { + const entity = sysfs_getEntity(path); + if (!entity) return null; + + return { + name: entity.name, + type: entity.type, + size: entity.size, + }; +} + +export function sysfs_mkdir(path: string): void { + if (sysfs_getEntity(path)) return; + + const parent = Path.dirname(path); + if (!sysfs_getEntity(parent)) return; + + sysfs_data.push({ + name: Path.filename(path), + path, + type: "folder", + size: 0, + contents: null, + }); +} + +export function sysfs_createFile(path: string, content: unknown): void { + if (sysfs_getEntity(path)) return; + + const parent = Path.dirname(path); + if (!sysfs_getEntity(parent)) return; + + const size = String(content).length; + + sysfs_data.push({ + name: Path.filename(path), + path, + type: "file", + size, + contents: content, + }); +} + +export function sysfs_writeFile(path: string, content: unknown): void { + const entity = sysfs_getEntity(path); + if (!entity) return sysfs_createFile(path, content); + + if (entity.type !== "file") return; + + entity.contents = content; + entity.size = String(content).length; +} + +export function sysfs_readFile(path: string): unknown { + const entity = sysfs_getEntity(path); + if (!entity) return null; + + if (entity.type !== "file") return null; + + return entity.contents; +} + +export function sysfs_listDir(path: string): KFilesystemEntity[] | null { + const entity = sysfs_getEntity(path); + if (!entity) return null; + + if (entity.type !== "folder") return null; + + const contents: KFilesystemEntity[] = []; + + for (let i = 0; i < sysfs_data.length; i++) { + const e = sysfs_data[i]!; + + if (Path.dirname(e.path) === path) { + contents.push(e); + } + } + + return contents; +} diff --git a/src/os/src/kernel/index.ts b/src/os/src/kernel/index.ts index 88ab0b5..dbe0a56 100644 --- a/src/os/src/kernel/index.ts +++ b/src/os/src/kernel/index.ts @@ -7,10 +7,16 @@ import { kdriver_etc_serial_read, kdriver_etc_serial_transmit, } from "./drivers/etc/serial"; +import { sysfs_driver, sysfs_readFile } from "./filesystem/sysfs"; import { kmod_drivers_init, kmod_drivers_register, } from "./modules/drivers/drivers.kmod"; +import { + kmod_filesystem_init, + kmod_filesystem_mount, + kmod_filesystem_readFile, +} from "./modules/filesystem/filesystem.kmod"; import { kmod_graphics_vga_clear, kmod_graphics_vga_init, @@ -23,11 +29,18 @@ export function kmain() { kmod_drivers_register(); Logger.log("[Kernel] Drivers initialized."); - Logger.log("[Kernel] Initializing PCI..."); + Logger.log("[Kernel] Initializing filesystem module..."); + kmod_filesystem_init(); + kmod_filesystem_mount("/sys", sysfs_driver); + + Logger.log("[Kernel] Initializing PCI devices..."); kdriver_dev_pci_detectDevices(); Logger.log("[Kernel] Initializing VGA module..."); kmod_graphics_vga_init(); kmod_graphics_vga_pushLine("[Kernel] Kernel initialized successfully."); kmod_graphics_vga_pushLine("Current date: " + getDate().toDateString()); + kmod_graphics_vga_pushLine( + Number(kmod_filesystem_readFile("/sys/pci/0:1:0/vendor")).toString(16) + ); } diff --git a/src/os/src/kernel/modules/filesystem/filesystem.kmod.ts b/src/os/src/kernel/modules/filesystem/filesystem.kmod.ts new file mode 100644 index 0000000..845d91e --- /dev/null +++ b/src/os/src/kernel/modules/filesystem/filesystem.kmod.ts @@ -0,0 +1,111 @@ +import { Logger } from "../../../lib/libstd/logger/logger.kmod"; +import type { + KFilesystemDriver, + KFilesystemEntity, + KFilesystemMount, + KFilesystemMountdata, + KFilesystemStat, +} from "../../../types/filesystem/fs"; + +const kmod_filesystem_data: KFilesystemMountdata = []; + +export function kmod_filesystem_init(): void {} + +export function kmod_filesystem_mount( + mpoint: string, + drv: () => KFilesystemDriver +): void { + const driver = drv(); + + driver.init(); + + kmod_filesystem_data.push({ + mountpoint: mpoint, + driver: driver, + }); + + Logger.log("[Filesystem] Mounted " + driver.id + " at " + mpoint); +} + +export function kmod_filesystem_findMount(p: string): KFilesystemMount | null { + for (let i = 0; i < kmod_filesystem_data.length; i++) { + const mount = kmod_filesystem_data[i]!; + + if (p.startsWith(mount.mountpoint)) { + return mount; + } + } + + return null; +} + +export function kmod_filesystem_stripMountpoint( + mount: KFilesystemMount, + p: string +): string { + if (mount.mountpoint === "/") return p; + + return p.slice(mount.mountpoint.length) || "/"; +} + +export function kmod_filesystem_listDir( + path: string +): KFilesystemEntity[] | null { + const mount = kmod_filesystem_findMount(path); + if (!mount) return null; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + return mount.driver.listDir(strippedPath); +} + +export function kmod_filesystem_readFile(path: string): unknown { + const mount = kmod_filesystem_findMount(path); + if (!mount) return null; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + return mount.driver.readFile(strippedPath); +} + +export function kmod_filesystem_writeFile( + path: string, + content: unknown +): void { + const mount = kmod_filesystem_findMount(path); + if (!mount) return; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + mount.driver.writeFile(strippedPath, content); +} + +export function kmod_filesystem_createFile( + path: string, + content: unknown +): void { + const mount = kmod_filesystem_findMount(path); + if (!mount) return; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + mount.driver.createFile(strippedPath, content); +} + +export function kmod_filesystem_mkdir(path: string): void { + const mount = kmod_filesystem_findMount(path); + if (!mount) return; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + mount.driver.mkdir(strippedPath); +} + +export function kmod_filesystem_stat(path: string): KFilesystemStat | null { + const mount = kmod_filesystem_findMount(path); + if (!mount) return null; + + const strippedPath = kmod_filesystem_stripMountpoint(mount, path); + + return mount.driver.stat(strippedPath); +} diff --git a/src/os/src/lib/libstd/path.ts b/src/os/src/lib/libstd/path.ts new file mode 100644 index 0000000..6fbe459 --- /dev/null +++ b/src/os/src/lib/libstd/path.ts @@ -0,0 +1,30 @@ +export const Path = { + dirname(p: string): string { + const parts = p.split("/"); + + parts.pop(); + + if (parts.length <= 1) return "/"; + + return parts.join("/"); + }, + filename(p: string): string { + const parts = p.split("/"); + + const n = parts.pop(); + + if (!n) return ""; + return n; + }, + join(p1: string, p2: string): string { + if (p1.endsWith("/")) { + p1 = p1.slice(0, -1); + } + + if (p2.startsWith("/")) { + p2 = p2.slice(1); + } + + return p1 + "/" + p2; + }, +}; diff --git a/src/os/src/types/filesystem/fs.ts b/src/os/src/types/filesystem/fs.ts new file mode 100644 index 0000000..0d2cd2e --- /dev/null +++ b/src/os/src/types/filesystem/fs.ts @@ -0,0 +1,33 @@ +export type KFilesystemMountdata = KFilesystemMount[]; + +export type KFilesystemMount = { + mountpoint: string; + driver: KFilesystemDriver; +}; + +export type KFilesystemDriver = { + id: string; + init: () => void; + listDir(path: string): KFilesystemEntity[] | null; + readFile(path: string): unknown; + writeFile(path: string, content: unknown): void; + createFile(path: string, content: unknown): void; + mkdir(path: string): void; + stat(path: string): KFilesystemStat | null; +}; + +export type KFilesystemMemdata = KFilesystemEntity[]; + +export type KFilesystemEntity = { + name: string; + path: string; + size: number; + contents: unknown; + type: "file" | "folder"; +}; + +export type KFilesystemStat = { + name: string; + type: "file" | "folder"; + size: number; +};