Add PCI driver

This commit is contained in:
2025-11-30 10:47:59 +01:00
parent af5d8c709b
commit f483a34d3c
9 changed files with 338 additions and 25 deletions

View File

@@ -90,26 +90,102 @@ int snprintf(char *str, size_t size, const char *format, ...) {
// sprintf is a macro in CrtLibSupport.h, so we don't define it.
// Math
// Duktape needs math. EDK2 doesn't provide standard math lib.
// We might need to implement simple versions or pull in a math lib.
// For now, stubs.
double floor(double x) { return (double)(int)x; } // Very wrong for negative/large
double ceil(double x) { return (double)(int)x + 1; }
double fabs(double x) { return x < 0 ? -x : x; }
double pow(double x, double y) { return 0; } // TODO
double sqrt(double x) { return 0; }
double sin(double x) { return 0; }
double cos(double x) { return 0; }
double tan(double x) { return 0; }
double asin(double x) { return 0; }
double acos(double x) { return 0; }
double atan(double x) { return 0; }
double atan2(double y, double x) { return 0; }
double exp(double x) { return 0; }
double log(double x) { return 0; }
double log10(double x) { return 0; }
double fmod(double x, double y) { return 0; }
// Math functions
// Duktape needs math functions for proper numeric conversions and bitwise operations.
// EDK2 doesn't provide a standard math library, so we implement basic versions here.
double fabs(double x) {
return x < 0.0 ? -x : x;
}
double floor(double x) {
if (x >= 0.0) {
return (double)(INT64)x;
} else {
INT64 i = (INT64)x;
return (double)((x == (double)i) ? i : i - 1);
}
}
double ceil(double x) {
if (x >= 0.0) {
INT64 i = (INT64)x;
return (double)((x == (double)i) ? i : i + 1);
} else {
return (double)(INT64)x;
}
}
double trunc(double x) {
return (double)(INT64)x;
}
double fmod(double x, double y) {
if (y == 0.0) return 0.0;
INT64 quotient = (INT64)(x / y);
return x - quotient * y;
}
// Newton-Raphson square root implementation
double sqrt(double x) {
if (x < 0.0) return 0.0; // Return 0 for negative (should be NaN)
if (x == 0.0) return 0.0;
double guess = x;
double epsilon = 0.00001;
// Newton-Raphson: x_new = (x_old + n/x_old) / 2
for (int i = 0; i < 50; i++) {
double next = (guess + x / guess) / 2.0;
if (fabs(next - guess) < epsilon) break;
guess = next;
}
return guess;
}
// Power function using binary exponentiation for integer exponents
double pow(double base, double exponent) {
// Handle special cases
if (exponent == 0.0) return 1.0;
if (base == 0.0) return 0.0;
if (base == 1.0) return 1.0;
if (exponent == 1.0) return base;
// Check if exponent is an integer
INT64 exp_int = (INT64)exponent;
if ((double)exp_int == exponent) {
// Integer exponent - use binary exponentiation
double result = 1.0;
double current = base;
UINT64 n = (exp_int < 0) ? -exp_int : exp_int;
while (n > 0) {
if (n & 1) result *= current;
current *= current;
n >>= 1;
}
return (exp_int < 0) ? (1.0 / result) : result;
}
// For non-integer exponents, return 0 (would need exp/log)
return 0.0;
}
// Trigonometric functions - stubs (not needed for bitwise ops)
double sin(double x) { return 0.0; }
double cos(double x) { return 0.0; }
double tan(double x) { return 0.0; }
double asin(double x) { return 0.0; }
double acos(double x) { return 0.0; }
double atan(double x) { return 0.0; }
double atan2(double y, double x) { return 0.0; }
double exp(double x) { return 0.0; }
double log(double x) { return 0.0; }
double log10(double x) { return 0.0; }
double cbrt(double x) { return 0.0; }
double log2(double x) { return 0.0; }
// Other
void abort(void) {
@@ -310,9 +386,6 @@ int sscanf(const char *str, const char *format, ...) { return 0; }
time_t time(time_t *tloc) { return 0; }
double difftime(time_t time1, time_t time0) { return (double)(time1 - time0); }
double cbrt(double x) { return 0; }
double log2(double x) { return 0; }
double trunc(double x) { return (double)(int)x; }
// Needed for CrtLibSupport headers to work?

View File

@@ -1,5 +1,8 @@
#include "main.h"
#include "efi.h"
#include "efi.h"
#include <Protocol/CpuIo2.h>
#include <Protocol/PciRootBridgeIo.h>
#include "duktape.h"
#include "embedded_js.h"
@@ -35,6 +38,63 @@ duk_ret_t native_systable_conout_set_attribute(duk_context *ctx) {
return 0;
}
duk_ret_t native_systable_io_dword_in(duk_context *ctx) {
EFI_CPU_IO2_PROTOCOL* cpuIo;
EFI_GUID cpuIoGuid = EFI_CPU_IO2_PROTOCOL_GUID;
systemTable->BootServices->LocateProtocol(&cpuIoGuid, NULL, (void**)&cpuIo);
UINT32 data;
cpuIo->Io.Read(cpuIo, EfiCpuIoWidthUint32, duk_to_uint(ctx, 0), 1, &data);
duk_push_uint(ctx, data);
return 1;
}
duk_ret_t native_systable_io_dword_out(duk_context *ctx) {
EFI_CPU_IO2_PROTOCOL* cpuIo;
EFI_GUID cpuIoGuid = EFI_CPU_IO2_PROTOCOL_GUID;
systemTable->BootServices->LocateProtocol(&cpuIoGuid, NULL, (void**)&cpuIo);
UINT32 data = duk_to_uint(ctx, 1);
cpuIo->Io.Write(cpuIo, EfiCpuIoWidthUint32, duk_to_uint(ctx, 0), 1, &data);
return 0;
}
duk_ret_t native_systable_pci_read_config(duk_context *ctx) {
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* pci;
EFI_GUID pciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
systemTable->BootServices->LocateProtocol(&pciGuid, NULL, (void**)&pci);
UINT64 bus = duk_to_uint(ctx, 0);
UINT64 device = duk_to_uint(ctx, 1);
UINT64 func = duk_to_uint(ctx, 2);
UINT64 offset = duk_to_uint(ctx, 3);
UINT64 address = (bus << 24) | (device << 16) | (func << 8) | (offset & 0xff);
UINT32 data = 0;
pci->Pci.Read(pci, EfiPciWidthUint32, address, 1, &data);
duk_push_uint(ctx, data);
return 1;
}
duk_ret_t native_systable_pci_write_config(duk_context *ctx) {
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* pci;
EFI_GUID pciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
systemTable->BootServices->LocateProtocol(&pciGuid, NULL, (void**)&pci);
UINT64 bus = duk_to_uint(ctx, 0);
UINT64 device = duk_to_uint(ctx, 1);
UINT64 func = duk_to_uint(ctx, 2);
UINT64 offset = duk_to_uint(ctx, 3);
UINT64 address = (bus << 24) | (device << 16) | (func << 8) | (offset & 0xff);
UINT32 data = duk_to_uint(ctx, 4);
pci->Pci.Write(pci, EfiPciWidthUint32, address, 1, &data);
return 0;
}
int kernel_main(EFI_SYSTEM_TABLE *st) {
systemTable = st;
ctx = duk_create_heap_default();
@@ -48,12 +108,27 @@ int kernel_main(EFI_SYSTEM_TABLE *st) {
duk_push_c_function(ctx, native_systable_conout_set_attribute, 1);
duk_put_global_string(ctx, "$___native_systable_conout_setAttribute");
duk_push_c_function(ctx, native_systable_io_dword_in, 1);
duk_put_global_string(ctx, "$___native_systable_io_dword_in");
duk_push_c_function(ctx, native_systable_io_dword_out, 2);
duk_put_global_string(ctx, "$___native_systable_io_dword_out");
duk_push_c_function(ctx, native_systable_pci_read_config, 4);
duk_put_global_string(ctx, "$___native_systable_pci_read_config");
duk_push_c_function(ctx, native_systable_pci_write_config, 5);
duk_put_global_string(ctx, "$___native_systable_pci_write_config");
duk_push_string(ctx, EMBEDDED_JS);
duk_int_t returnCode = duk_peval(ctx);
if (returnCode != 0)
{
duk_safe_to_stacktrace(ctx, -1);
CHAR16 buffer[256];
ascii_to_utf16(duk_safe_to_string(ctx, -1), buffer);
systemTable->ConOut->OutputString(systemTable->ConOut, buffer);
@@ -61,6 +136,8 @@ int kernel_main(EFI_SYSTEM_TABLE *st) {
duk_pop(ctx);
systemTable->ConOut->OutputString(systemTable->ConOut, L"!!! KERNEL EXITED UNEXPECTEDLY !!!\r\n");
halt();
return 0;

View File

@@ -0,0 +1,113 @@
import { Logger } from "../../../libs/logger";
export function kdriver_dev_pci_init() {}
export function kdriver_dev_pci_detectDevices() {
Logger.log("[PCI] Scanning...");
for (let bus = 0; bus < 256; bus++) {
for (let device = 0; device < 32; device++) {
kdriver_dev_pci_checkDevice(bus, device, 0);
const headerType = kdriver_dev_pci_getHeaderType(bus, device, 0);
if ((headerType & 0x80) !== 0) {
for (let func = 1; func < 8; func++) {
kdriver_dev_pci_checkDevice(bus, device, func);
}
}
}
}
}
export function kdriver_dev_pci_checkDevice(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 0);
if (data === 0 || data === -1) return;
const vendorId = data & 0xffff;
const deviceId = data >>> 16;
if (vendorId === 0 || vendorId === 0xffff) return;
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:" +
filename +
" (vendor:" +
vendorId.toString(16) +
", device:" +
deviceId.toString(16) +
", class:" +
classCode.toString(16) +
", subclass:" +
subclass.toString(16) +
")"
);
}
export function kdriver_dev_pci_getDeviceId(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 0);
return data >>> 16;
}
export function kdriver_dev_pci_getVendorId(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 0);
return data & 0xffff;
}
export function kdriver_dev_pci_getClassCode(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 8);
return (data >> 24) & 0xff;
}
export function kdriver_dev_pci_getSubclass(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 8);
return (data >> 16) & 0xff;
}
export function kdriver_dev_pci_getHeaderType(
bus: number,
device: number,
func: number
) {
const data = kdriver_dev_pci_readConfigDword(bus, device, func, 12);
return (data >> 16) & 0xff;
}
export function kdriver_dev_pci_readConfigDword(
bus: number,
device: number,
func: number,
offset: number
) {
return $___native_systable_pci_read_config(bus, device, func, offset);
}

View File

@@ -1,13 +1,19 @@
import { Logger } from "../libs/logger";
import { kdriver_dev_pci_detectDevices } from "./drivers/dev/pci.kdriver";
import {
kmod_console_clearScreen,
kmod_console_outputString,
} from "./modules/console/console.kmod";
import { kmod_drivers_init } from "./modules/drivers.kmod";
export function kmain() {
kmod_console_clearScreen();
Logger.log("[Kernel] Starting kernel...");
kmod_drivers_init();
kdriver_dev_pci_detectDevices();
return 0;
}

View File

@@ -0,0 +1,12 @@
import { Logger } from "../../libs/logger";
import { kdriver_dev_pci_init } from "../drivers/dev/pci.kdriver";
const drivers = [kdriver_dev_pci_init];
export function kmod_drivers_init() {
Logger.log("[Kernel] Initializing drivers...");
for (let i = 0; i < drivers.length; i++) {
drivers[i]!();
}
}

7
os/src/libs/io.ts Normal file
View File

@@ -0,0 +1,7 @@
export function dwordin(port: number): number {
return $___native_systable_io_dwordin(port);
}
export function dwordout(port: number, value: number) {
$___native_systable_io_dwordout(port, value);
}

View File

@@ -3,3 +3,24 @@ declare function $___native_systable_conout_clearScreen(): void;
declare function $___native_systable_conout_setAttribute(
attribute: number
): void;
declare function $___native_systable_io_dwordin(port: number): number;
declare function $___native_systable_io_dwordout(
port: number,
value: number
): void;
declare function $___native_systable_pci_read_config(
bus: number,
device: number,
func: number,
offset: number
): number;
declare function $___native_systable_pci_write_config(
bus: number,
device: number,
func: number,
offset: number,
value: number
): void;

View File

@@ -3,8 +3,8 @@ const fs = require("fs");
const script = fs.readFileSync("out/os/index.js", "utf-8");
const processed = script
/*.replaceAll("let ", "var ")
.replaceAll("const ", "var ")*/
.replaceAll("let ", "var ")
.replaceAll("const ", "var ")
.replaceAll("\n`", "\\n`")
.replaceAll("`", "'");

4
scripts/run.sh Executable file
View File

@@ -0,0 +1,4 @@
./scripts/build_ts.sh
./scripts/build_c.sh
./scripts/out_to_iso.sh
./scripts/run_vbox.sh