diff --git a/src/core/efi.h b/src/core/efi.h index bc96962..badb52e 100644 --- a/src/core/efi.h +++ b/src/core/efi.h @@ -1,11 +1,31 @@ #ifndef EFI_H #define EFI_H + +#include + #define NULL ((void*)0) -// EFI definitions +// Basic Types +typedef uint64_t UINT64; +typedef uint32_t UINT32; +typedef uint16_t UINT16; +typedef uint8_t UINT8; +typedef uintptr_t UINTN; +typedef intptr_t INTN; +typedef void VOID; + typedef uint64_t EFI_STATUS; typedef void* EFI_HANDLE; + #define EFI_SUCCESS 0 +#define EFI_ERROR(status) (((INTN)(status)) < 0) + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; typedef struct { uint64_t signature; @@ -15,6 +35,7 @@ typedef struct { uint32_t reserved; } EFI_TABLE_HEADER; +// Simple Text Output Protocol struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef EFI_STATUS (*EFI_TEXT_STRING)( struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, @@ -38,6 +59,112 @@ typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { void *mode; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; +// Boot Services +typedef struct { + EFI_TABLE_HEADER Hdr; + void *RaiseTPL; + void *RestoreTPL; + void *AllocatePages; + void *FreePages; + void *GetMemoryMap; + void *AllocatePool; + void *FreePool; + void *CreateEvent; + void *SetTimer; + void *WaitForEvent; + void *SignalEvent; + void *CloseEvent; + void *CheckEvent; + void *InstallProtocolInterface; + void *ReinstallProtocolInterface; + void *UninstallProtocolInterface; + void *HandleProtocol; + void *Reserved; + void *RegisterProtocolNotify; + void *LocateHandle; + void *LocateDevicePath; + void *InstallConfigurationTable; + void *LoadImage; + void *StartImage; + void *Exit; + void *UnloadImage; + void *ExitBootServices; + void *GetNextMonotonicCount; + void *Stall; + void *SetWatchdogTimer; + void *ConnectController; + void *DisconnectController; + void *OpenProtocol; + void *CloseProtocol; + void *OpenProtocolInformation; + void *ProtocolsPerHandle; + void *LocateHandleBuffer; + EFI_STATUS (*LocateProtocol)(EFI_GUID *Protocol, void *Registration, void **Interface); + void *InstallMultipleProtocolInterfaces; + void *UninstallMultipleProtocolInterfaces; + void *CalculateCrc32; + void *CopyMem; + void *SetMem; + void *CreateEventEx; +} EFI_BOOT_SERVICES; + +// PCI Root Bridge IO Protocol +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +typedef enum { + EfiPciWidthUint8, + EfiPciWidthUint16, + EfiPciWidthUint32, + EfiPciWidthUint64, + EfiPciWidthFifoUint8, + EfiPciWidthFifoUint16, + EfiPciWidthFifoUint32, + EfiPciWidthFifoUint64, + EfiPciWidthFillUint8, + EfiPciWidthFillUint16, + EfiPciWidthFillUint32, + EfiPciWidthFillUint64, + EfiPciWidthMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +typedef +EFI_STATUS +(*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM) ( + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + UINT64 Address, + UINTN Count, + VOID *Buffer + ); + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; + +struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + void *ParentHandle; + void *PollMem; + void *PollIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + void *CopyMem; + void *Map; + void *Unmap; + void *AllocateBuffer; + void *FreeBuffer; + void *Flush; + void *GetAttributes; + void *SetAttributes; + void *Configuration; + UINT32 SegmentNumber; +}; + +// System Table typedef struct EFI_SYSTEM_TABLE { EFI_TABLE_HEADER hdr; uint16_t *firmwareVendor; @@ -49,8 +176,9 @@ typedef struct EFI_SYSTEM_TABLE { void *standardErrorHandle; void *stdErr; void *runtimeServices; - void *bootServices; + EFI_BOOT_SERVICES *BootServices; uint64_t numberOfTableEntries; void *configurationTable; } EFI_SYSTEM_TABLE; + #endif diff --git a/src/core/main.c b/src/core/main.c index 2a058c0..c8e837e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -99,14 +99,37 @@ JSValue jsKCClearScreen(JSContext *ctx, JSValueConst jsThis, int argc, JSValueCo return JS_UNDEFINED; } +JSValue jsKCPCIReadDword(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) { + if (argc < 1) return JS_ThrowSyntaxError(ctx, "Missing argument"); + + uint32_t addr_u32; + JS_ToUint32(ctx, &addr_u32, argv[0]); + UINT64 addr = (UINT64)addr_u32; // Ensure type matches EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_RW's Address parameter + + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* pci; + EFI_GUID pciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; + EFI_STATUS status = gST->BootServices->LocateProtocol(&pciGuid, NULL, (void**)&pci); + + if (EFI_ERROR(status)) { + return JS_ThrowInternalError(ctx, "Failed to locate PCI Root Bridge IO Protocol: %d", status); + } + + UINT32 data = 0; + + status = pci->Pci.Read(pci, EfiPciWidthUint32, addr, 1, &data); + + return JS_NewUint32(ctx, data); +} + void initKC(JSContext *ctx) { JSValue global = JS_GetGlobalObject(ctx); JSValue kc = JS_NewObject(ctx); JS_SetPropertyStr(ctx, global, "kc", kc); - + JS_SetPropertyStr(ctx, kc, "println", JS_NewCFunction(ctx, jsKCPrintln, "println", 1)); JS_SetPropertyStr(ctx, kc, "clearScreen", JS_NewCFunction(ctx, jsKCClearScreen, "clearScreen", 0)); + JS_SetPropertyStr(ctx, kc, "pciReadDword", JS_NewCFunction(ctx, jsKCPCIReadDword, "pciReadDword", 1)); JS_FreeValue(ctx, global); } diff --git a/src/system/src/kernel/drivers/dev/pci.drv.ts b/src/system/src/kernel/drivers/dev/pci.drv.ts new file mode 100644 index 0000000..1729c66 --- /dev/null +++ b/src/system/src/kernel/drivers/dev/pci.drv.ts @@ -0,0 +1,82 @@ +import { Logger } from "../../../lib/logger"; +import { numtohex } from "../../../util/hex"; +import { SysFS } from "../../filesystem/sys.fs"; +import { KernelDriver } from "../kdriver"; + +export class PCIKDriver extends KernelDriver { + static instance: PCIKDriver = new this(); + + constructor() { + super("pci"); + } + + static init() { + PCIKDriver.instance.init(); + } + + override init() { + super.init(); + + SysFS.instance.pMkdir("/pci"); + this.#detectDevices(); + } + + #detectDevices() { + Logger.log("[PCI] Scanning..."); + + for (let bus = 0; bus < 256; bus++) { + for (let device = 0; device < 32; device++) { + this.#checkDevice(bus, device, 0); + } + } + } + + #checkDevice(bus: number, device: number, func: number) { + const data = this.#readConfig(bus, device, func, 0); + if (data === 0 || data === 0xffffffff) return; + + const vendorId = this.#getDeviceVendorId(bus, device, func); + const deviceId = this.#getDeviceId(bus, device, func); + const classId = this.#getDeviceClass(bus, device, func); + const subclassId = this.#getDeviceSubclass(bus, device, func); + + const filename = `pci.${bus}.${device}.${func}`; + + Logger.log( + `[PCI] Found device: ${filename} (vendor: ${numtohex( + vendorId + )}, device: ${numtohex(deviceId)}, class: ${numtohex( + classId + )}, subclass: ${numtohex(subclassId)})` + ); + + SysFS.instance.pMkdir(`/pci/${filename}`); + SysFS.instance.pWriteFile(`/pci/${filename}/vendor`, numtohex(vendorId)); + SysFS.instance.pWriteFile(`/pci/${filename}/device`, numtohex(deviceId)); + SysFS.instance.pWriteFile(`/pci/${filename}/class`, numtohex(classId)); + SysFS.instance.pWriteFile( + `/pci/${filename}/subclass`, + numtohex(subclassId) + ); + } + + #getDeviceId(bus: number, device: number, func: number) { + return this.#readConfig(bus, device, func, 0) >>> 16; + } + + #getDeviceVendorId(bus: number, device: number, func: number) { + return this.#readConfig(bus, device, func, 0) & 0xffff; + } + + #getDeviceClass(bus: number, device: number, func: number) { + return (this.#readConfig(bus, device, func, 8) >> 24) & 0xff; + } + + #getDeviceSubclass(bus: number, device: number, func: number) { + return (this.#readConfig(bus, device, func, 8) >> 16) & 0xff; + } + + #readConfig(bus: number, device: number, func: number, offset: number) { + return kc.pciReadDword((bus << 16) | (device << 11) | (func << 8) | offset); + } +} diff --git a/src/system/src/kernel/drivers/kdriver.ts b/src/system/src/kernel/drivers/kdriver.ts new file mode 100644 index 0000000..8dfc9d4 --- /dev/null +++ b/src/system/src/kernel/drivers/kdriver.ts @@ -0,0 +1,20 @@ +import { Logger } from "../../lib/logger"; + +export class KernelDriver { + #name: string; + #initialized: boolean = false; + + constructor(name: string) { + this.#name = name; + } + + init() { + Logger.log(`[Kernel] Initializing ${this.#name} driver...`); + + this.#initialized = true; + } + + get initialized() { + return this.#initialized; + } +} diff --git a/src/system/src/kernel/index.ts b/src/system/src/kernel/index.ts index 6bef37b..c70a5e7 100644 --- a/src/system/src/kernel/index.ts +++ b/src/system/src/kernel/index.ts @@ -1,6 +1,7 @@ import { Logger } from "../lib/logger"; import { SysFS } from "./filesystem/sys.fs"; import { ConsoleKModule } from "./modules/console/console.kmod"; +import { DriverKModule } from "./modules/driver"; import { VFSKModule } from "./modules/vfs/vfs.kmod"; export function KMain() { @@ -8,11 +9,9 @@ export function KMain() { Logger.log("[Kernel] Initializing kernel..."); ConsoleKModule.init(); + VFSKModule.init(); VFSKModule.instance.mount(SysFS.instance, "/sys"); - SysFS.instance.pMkdir("/pci"); - SysFS.instance.pWriteFile("/pci/test", "test"); - - Logger.log(SysFS.instance.readFile("/pci/test")); + DriverKModule.init(); } diff --git a/src/system/src/kernel/modules/driver.ts b/src/system/src/kernel/modules/driver.ts new file mode 100644 index 0000000..4ecc574 --- /dev/null +++ b/src/system/src/kernel/modules/driver.ts @@ -0,0 +1,25 @@ +import { PCIKDriver } from "../drivers/dev/pci.drv"; +import type { KernelDriver } from "../drivers/kdriver"; +import { KernelModule } from "./kmod"; + +export const DRIVERS: KernelDriver[] = [PCIKDriver.instance]; + +export class DriverKModule extends KernelModule { + static instance: DriverKModule = new this(); + + constructor() { + super("driver"); + } + + static init() { + DriverKModule.instance.init(); + } + + override init() { + super.init(); + + for (const driver of DRIVERS) { + driver.init(); + } + } +} diff --git a/src/system/src/kernel/modules/vfs/vfs.kmod.ts b/src/system/src/kernel/modules/vfs/vfs.kmod.ts index 969b19c..05255a8 100644 --- a/src/system/src/kernel/modules/vfs/vfs.kmod.ts +++ b/src/system/src/kernel/modules/vfs/vfs.kmod.ts @@ -18,7 +18,7 @@ export class VFSKModule extends KernelModule { mount(fs: FileSystem, mountPoint: string) { if (!this.initialized) return; - Logger.log(`Mounting ${fs.id} at ${mountPoint}`); + Logger.log(`[VFS] Mounting ${fs.id} at ${mountPoint}`); this.#mounts.set(mountPoint, fs); } diff --git a/src/system/src/types/kc.d.ts b/src/system/src/types/kc.d.ts index fb4c8a5..e0367a2 100644 --- a/src/system/src/types/kc.d.ts +++ b/src/system/src/types/kc.d.ts @@ -1,4 +1,5 @@ declare namespace kc { function println(msg: string): void; function clearScreen(): void; + function pciReadDword(addr: number): number; } diff --git a/src/system/src/util/hex.ts b/src/system/src/util/hex.ts new file mode 100644 index 0000000..034d731 --- /dev/null +++ b/src/system/src/util/hex.ts @@ -0,0 +1,3 @@ +export function numtohex(num: number) { + return num.toString(16); +}