Add PCI driver
This commit is contained in:
@@ -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?
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user