Add PCI driver
This commit is contained in:
132
src/core/efi.h
132
src/core/efi.h
@@ -1,11 +1,31 @@
|
|||||||
#ifndef EFI_H
|
#ifndef EFI_H
|
||||||
#define EFI_H
|
#define EFI_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define NULL ((void*)0)
|
#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 uint64_t EFI_STATUS;
|
||||||
typedef void* EFI_HANDLE;
|
typedef void* EFI_HANDLE;
|
||||||
|
|
||||||
#define EFI_SUCCESS 0
|
#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 {
|
typedef struct {
|
||||||
uint64_t signature;
|
uint64_t signature;
|
||||||
@@ -15,6 +35,7 @@ typedef struct {
|
|||||||
uint32_t reserved;
|
uint32_t reserved;
|
||||||
} EFI_TABLE_HEADER;
|
} EFI_TABLE_HEADER;
|
||||||
|
|
||||||
|
// Simple Text Output Protocol
|
||||||
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||||
typedef EFI_STATUS (*EFI_TEXT_STRING)(
|
typedef EFI_STATUS (*EFI_TEXT_STRING)(
|
||||||
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||||
@@ -38,6 +59,112 @@ typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
|
|||||||
void *mode;
|
void *mode;
|
||||||
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
} 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 {
|
typedef struct EFI_SYSTEM_TABLE {
|
||||||
EFI_TABLE_HEADER hdr;
|
EFI_TABLE_HEADER hdr;
|
||||||
uint16_t *firmwareVendor;
|
uint16_t *firmwareVendor;
|
||||||
@@ -49,8 +176,9 @@ typedef struct EFI_SYSTEM_TABLE {
|
|||||||
void *standardErrorHandle;
|
void *standardErrorHandle;
|
||||||
void *stdErr;
|
void *stdErr;
|
||||||
void *runtimeServices;
|
void *runtimeServices;
|
||||||
void *bootServices;
|
EFI_BOOT_SERVICES *BootServices;
|
||||||
uint64_t numberOfTableEntries;
|
uint64_t numberOfTableEntries;
|
||||||
void *configurationTable;
|
void *configurationTable;
|
||||||
} EFI_SYSTEM_TABLE;
|
} EFI_SYSTEM_TABLE;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -99,6 +99,28 @@ JSValue jsKCClearScreen(JSContext *ctx, JSValueConst jsThis, int argc, JSValueCo
|
|||||||
return JS_UNDEFINED;
|
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) {
|
void initKC(JSContext *ctx) {
|
||||||
JSValue global = JS_GetGlobalObject(ctx);
|
JSValue global = JS_GetGlobalObject(ctx);
|
||||||
JSValue kc = JS_NewObject(ctx);
|
JSValue kc = JS_NewObject(ctx);
|
||||||
@@ -107,6 +129,7 @@ void initKC(JSContext *ctx) {
|
|||||||
|
|
||||||
JS_SetPropertyStr(ctx, kc, "println", JS_NewCFunction(ctx, jsKCPrintln, "println", 1));
|
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, "clearScreen", JS_NewCFunction(ctx, jsKCClearScreen, "clearScreen", 0));
|
||||||
|
JS_SetPropertyStr(ctx, kc, "pciReadDword", JS_NewCFunction(ctx, jsKCPCIReadDword, "pciReadDword", 1));
|
||||||
|
|
||||||
JS_FreeValue(ctx, global);
|
JS_FreeValue(ctx, global);
|
||||||
}
|
}
|
||||||
|
|||||||
82
src/system/src/kernel/drivers/dev/pci.drv.ts
Normal file
82
src/system/src/kernel/drivers/dev/pci.drv.ts
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/system/src/kernel/drivers/kdriver.ts
Normal file
20
src/system/src/kernel/drivers/kdriver.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Logger } from "../lib/logger";
|
import { Logger } from "../lib/logger";
|
||||||
import { SysFS } from "./filesystem/sys.fs";
|
import { SysFS } from "./filesystem/sys.fs";
|
||||||
import { ConsoleKModule } from "./modules/console/console.kmod";
|
import { ConsoleKModule } from "./modules/console/console.kmod";
|
||||||
|
import { DriverKModule } from "./modules/driver";
|
||||||
import { VFSKModule } from "./modules/vfs/vfs.kmod";
|
import { VFSKModule } from "./modules/vfs/vfs.kmod";
|
||||||
|
|
||||||
export function KMain() {
|
export function KMain() {
|
||||||
@@ -8,11 +9,9 @@ export function KMain() {
|
|||||||
Logger.log("[Kernel] Initializing kernel...");
|
Logger.log("[Kernel] Initializing kernel...");
|
||||||
|
|
||||||
ConsoleKModule.init();
|
ConsoleKModule.init();
|
||||||
|
|
||||||
VFSKModule.init();
|
VFSKModule.init();
|
||||||
VFSKModule.instance.mount(SysFS.instance, "/sys");
|
VFSKModule.instance.mount(SysFS.instance, "/sys");
|
||||||
|
|
||||||
SysFS.instance.pMkdir("/pci");
|
DriverKModule.init();
|
||||||
SysFS.instance.pWriteFile("/pci/test", "test");
|
|
||||||
|
|
||||||
Logger.log(SysFS.instance.readFile("/pci/test"));
|
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/system/src/kernel/modules/driver.ts
Normal file
25
src/system/src/kernel/modules/driver.ts
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ export class VFSKModule extends KernelModule {
|
|||||||
mount(fs: FileSystem, mountPoint: string) {
|
mount(fs: FileSystem, mountPoint: string) {
|
||||||
if (!this.initialized) return;
|
if (!this.initialized) return;
|
||||||
|
|
||||||
Logger.log(`Mounting ${fs.id} at ${mountPoint}`);
|
Logger.log(`[VFS] Mounting ${fs.id} at ${mountPoint}`);
|
||||||
this.#mounts.set(mountPoint, fs);
|
this.#mounts.set(mountPoint, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
src/system/src/types/kc.d.ts
vendored
1
src/system/src/types/kc.d.ts
vendored
@@ -1,4 +1,5 @@
|
|||||||
declare namespace kc {
|
declare namespace kc {
|
||||||
function println(msg: string): void;
|
function println(msg: string): void;
|
||||||
function clearScreen(): void;
|
function clearScreen(): void;
|
||||||
|
function pciReadDword(addr: number): number;
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/system/src/util/hex.ts
Normal file
3
src/system/src/util/hex.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export function numtohex(num: number) {
|
||||||
|
return num.toString(16);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user