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
|
||||
#define EFI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -99,6 +99,28 @@ 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);
|
||||
@@ -107,6 +129,7 @@ void initKC(JSContext *ctx) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 { 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();
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!this.initialized) return;
|
||||
|
||||
Logger.log(`Mounting ${fs.id} at ${mountPoint}`);
|
||||
Logger.log(`[VFS] Mounting ${fs.id} at ${mountPoint}`);
|
||||
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 {
|
||||
function println(msg: string): 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