Compare commits
3 Commits
9882280973
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f6b4039348 | |||
| 8761d6867c | |||
|
|
f2b5e17856 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ out/
|
||||
node_modules/
|
||||
*.iso
|
||||
*.img
|
||||
.clangd
|
||||
@@ -36,6 +36,12 @@ st run build
|
||||
|
||||
The built ISO can be found in `out/` directory.
|
||||
|
||||
## How to setup development environment?
|
||||
|
||||
```bash
|
||||
./src/scripts/setup_dev.sh
|
||||
```
|
||||
|
||||
## If you are an employer looking at this...
|
||||
|
||||
I would appreciate if you messaged me and gave me some well-paid job. Also...
|
||||
|
||||
@@ -244,15 +244,119 @@ long strtol(const char *str, char **endptr, int base) {
|
||||
return result * sign;
|
||||
}
|
||||
|
||||
#define HEAP_SIZE (8 * 1024 * 1024)
|
||||
static unsigned char heap[HEAP_SIZE];
|
||||
// Dynamic heap - will be initialized based on available RAM
|
||||
static unsigned char *heap = NULL;
|
||||
static size_t heap_size = 0;
|
||||
static size_t heap_pos = 0;
|
||||
|
||||
// Forward declare EFI types we need
|
||||
typedef uint64_t EFI_STATUS;
|
||||
typedef void* EFI_HANDLE;
|
||||
typedef uint64_t UINT64;
|
||||
typedef uint32_t UINT32;
|
||||
typedef uintptr_t UINTN;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Type;
|
||||
UINT64 PhysicalStart;
|
||||
UINT64 VirtualStart;
|
||||
UINT64 NumberOfPages;
|
||||
UINT64 Attribute;
|
||||
} EFI_MEMORY_DESCRIPTOR;
|
||||
|
||||
typedef struct EFI_BOOT_SERVICES_PARTIAL {
|
||||
// EFI_TABLE_HEADER (24 bytes) + 5 pointers (RaiseTPL, RestoreTPL, AllocatePages, FreePages, GetMemoryMap)
|
||||
char padding[64]; // 24 + 5*8 = 64 bytes to reach AllocatePool
|
||||
EFI_STATUS (*AllocatePool)(UINT32 PoolType, UINTN Size, void **Buffer);
|
||||
} EFI_BOOT_SERVICES_PARTIAL;
|
||||
|
||||
typedef struct {
|
||||
char hdr[24]; // EFI_TABLE_HEADER
|
||||
void *firmwareVendor;
|
||||
UINT32 firmwareRevision;
|
||||
void *consoleInHandle;
|
||||
void *conIn;
|
||||
void *consoleOutHandle;
|
||||
void *ConOut;
|
||||
void *standardErrorHandle;
|
||||
void *stdErr;
|
||||
void *runtimeServices;
|
||||
EFI_BOOT_SERVICES_PARTIAL *BootServices;
|
||||
} EFI_SYSTEM_TABLE_PARTIAL;
|
||||
|
||||
#define EfiConventionalMemory 7
|
||||
|
||||
// Initialize heap with maximum available memory
|
||||
void init_heap(void *system_table) {
|
||||
// Static fallback heap in case EFI allocation fails
|
||||
static unsigned char static_heap[64 * 1024 * 1024]; // 64 MB fallback
|
||||
|
||||
EFI_SYSTEM_TABLE_PARTIAL *st = (EFI_SYSTEM_TABLE_PARTIAL*)system_table;
|
||||
|
||||
// Safety check
|
||||
if (!st || !st->BootServices || !st->BootServices->AllocatePool) {
|
||||
printf("WARNING: EFI Boot Services not available, using static heap\n");
|
||||
heap = static_heap;
|
||||
heap_size = sizeof(static_heap);
|
||||
heap_pos = 0;
|
||||
printf("Heap initialized: %zu MB (static fallback)\n", heap_size / (1024 * 1024));
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to allocate a very large heap - start with 16 GB and work down if needed
|
||||
size_t sizes[] = {
|
||||
16ULL * 1024 * 1024 * 1024, // 16 GB
|
||||
8ULL * 1024 * 1024 * 1024, // 8 GB
|
||||
4ULL * 1024 * 1024 * 1024, // 4 GB
|
||||
2ULL * 1024 * 1024 * 1024, // 2 GB
|
||||
1ULL * 1024 * 1024 * 1024, // 1 GB
|
||||
512ULL * 1024 * 1024, // 512 MB
|
||||
256ULL * 1024 * 1024, // 256 MB
|
||||
128ULL * 1024 * 1024, // 128 MB
|
||||
64ULL * 1024 * 1024, // 64 MB
|
||||
32ULL * 1024 * 1024, // 32 MB
|
||||
16ULL * 1024 * 1024, // 16 MB
|
||||
8ULL * 1024 * 1024 // 8 MB (fallback)
|
||||
};
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
EFI_STATUS status = st->BootServices->AllocatePool(
|
||||
EfiConventionalMemory,
|
||||
sizes[i],
|
||||
(void**)&heap
|
||||
);
|
||||
|
||||
if (status == 0) { // EFI_SUCCESS
|
||||
heap_size = sizes[i];
|
||||
heap_pos = 0;
|
||||
if (heap_size >= 1024ULL * 1024 * 1024) {
|
||||
printf("Heap initialized: %zu GB (%zu bytes)\n",
|
||||
heap_size / (1024ULL * 1024 * 1024), heap_size);
|
||||
} else {
|
||||
printf("Heap initialized: %zu MB (%zu bytes)\n",
|
||||
heap_size / (1024 * 1024), heap_size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If all EFI allocations failed, use static heap
|
||||
printf("WARNING: EFI allocation failed, using static heap\n");
|
||||
heap = static_heap;
|
||||
heap_size = sizeof(static_heap);
|
||||
heap_pos = 0;
|
||||
printf("Heap initialized: %zu MB (static fallback)\n", heap_size / (1024 * 1024));
|
||||
}
|
||||
|
||||
void *malloc(size_t size) {
|
||||
if (!heap) {
|
||||
printf("malloc failed: heap not initialized\n");
|
||||
return (void*)0;
|
||||
}
|
||||
size = (size + 7) & ~7;
|
||||
size_t total = size + 8;
|
||||
if (heap_pos + total > HEAP_SIZE) {
|
||||
printf("malloc failed: OOM\n");
|
||||
if (heap_pos + total > heap_size) {
|
||||
printf("malloc failed: OOM (requested %zu, available %zu)\n", total, heap_size - heap_pos);
|
||||
return (void*)0;
|
||||
}
|
||||
*(size_t*)&heap[heap_pos] = size;
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include <stdint.h>
|
||||
#include "efi.h"
|
||||
#include "quickjs.h"
|
||||
#include "stdio.h"
|
||||
#include "system_prog.h"
|
||||
#include "util.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include "stdio.h"
|
||||
#include "quickjs.h"
|
||||
#include "efi.h"
|
||||
#include "util.h"
|
||||
#include "system_prog.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static EFI_SYSTEM_TABLE *gST = NULL;
|
||||
|
||||
// Declare heap initialization function from minilibc.c
|
||||
extern void init_heap(void *system_table);
|
||||
|
||||
void print(uint16_t *str) {
|
||||
if (gST && gST->ConOut)
|
||||
gST->ConOut->OutputString(gST->ConOut, str);
|
||||
@@ -29,7 +32,8 @@ int printf(const char *format, ...) {
|
||||
}
|
||||
|
||||
int fprintf(FILE *stream, const char *format, ...) {
|
||||
if (stream != stdout && stream != stderr) return 0;
|
||||
if (stream != stdout && stream != stderr)
|
||||
return 0;
|
||||
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
@@ -44,7 +48,8 @@ int fprintf(FILE *stream, const char *format, ...) {
|
||||
}
|
||||
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
if (stream != stdout && stream != stderr) return 0;
|
||||
if (stream != stdout && stream != stderr)
|
||||
return 0;
|
||||
|
||||
const char *p = ptr;
|
||||
size_t total = size * nmemb;
|
||||
@@ -53,7 +58,8 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
|
||||
while (i < total) {
|
||||
size_t chunk = total - i;
|
||||
if (chunk > 1024) chunk = 1024;
|
||||
if (chunk > 1024)
|
||||
chunk = 1024;
|
||||
|
||||
memcpy(buf, p + i, chunk);
|
||||
buf[chunk] = 0;
|
||||
@@ -66,24 +72,27 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
}
|
||||
|
||||
int fputc(int c, FILE *stream) {
|
||||
if (stream != stdout && stream != stderr) return c;
|
||||
char buf[2] = { (char)c, 0 };
|
||||
if (stream != stdout && stream != stderr)
|
||||
return c;
|
||||
char buf[2] = {(char)c, 0};
|
||||
|
||||
print(AsciiToUnicode(buf));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int putchar(int c) {
|
||||
return fputc(c, stdout);
|
||||
}
|
||||
int putchar(int c) { return fputc(c, stdout); }
|
||||
|
||||
// ------------------------------- Kernel C TS bindings -------------------------------
|
||||
JSValue jsKCPrintln(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc < 1) return JS_ThrowSyntaxError(ctx, "Missing argument");
|
||||
// ------------------------------- Kernel C TS bindings
|
||||
// -------------------------------
|
||||
JSValue jsKCPrintln(JSContext *ctx, JSValueConst jsThis, int argc,
|
||||
JSValueConst *argv) {
|
||||
if (argc < 1)
|
||||
return JS_ThrowSyntaxError(ctx, "Missing argument");
|
||||
|
||||
const char *str = JS_ToCString(ctx, argv[0]);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
print(AsciiToUnicode(str));
|
||||
print(L"\r\n");
|
||||
@@ -93,25 +102,32 @@ JSValue jsKCPrintln(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSValue jsKCClearScreen(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
JSValue jsKCClearScreen(JSContext *ctx, JSValueConst jsThis, int argc,
|
||||
JSValueConst *argv) {
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSValue jsKCPCIReadDword(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc < 1) return JS_ThrowSyntaxError(ctx, "Missing argument");
|
||||
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
|
||||
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_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);
|
||||
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);
|
||||
return JS_ThrowInternalError(
|
||||
ctx, "Failed to locate PCI Root Bridge IO Protocol: %d", status);
|
||||
}
|
||||
|
||||
UINT32 data = 0;
|
||||
@@ -134,7 +150,8 @@ void initKC(JSContext *ctx) {
|
||||
JS_FreeValue(ctx, global);
|
||||
}
|
||||
|
||||
// ------------------------------------- EFI main -------------------------------------
|
||||
// ------------------------------------- EFI main
|
||||
// -------------------------------------
|
||||
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
(void)ImageHandle;
|
||||
|
||||
@@ -143,6 +160,9 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
|
||||
print(L"Booting LintsOS...\r\n");
|
||||
|
||||
// Initialize heap with maximum available memory
|
||||
init_heap(SystemTable);
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
if (!rt) {
|
||||
print(L"!!! Kernel panic: Failed to create runtime !!!\r\n");
|
||||
@@ -159,16 +179,21 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
initKC(ctx);
|
||||
|
||||
JSValue val;
|
||||
JSValue eval_result = JS_Eval(ctx, SYSTEM_PROG_JS, strlen(SYSTEM_PROG_JS), "<input>", JS_EVAL_TYPE_GLOBAL);
|
||||
if (JS_IsException(eval_result)) val = eval_result;
|
||||
JSValue eval_result = JS_Eval(ctx, SYSTEM_PROG_JS, strlen(SYSTEM_PROG_JS),
|
||||
"<input>", JS_EVAL_TYPE_GLOBAL);
|
||||
if (JS_IsException(eval_result))
|
||||
val = eval_result;
|
||||
else {
|
||||
JS_FreeValue(ctx, eval_result);
|
||||
|
||||
JSValue global_obj = JS_GetGlobalObject(ctx);
|
||||
JSValue kentry_func = JS_GetPropertyStr(ctx, global_obj, "KEntry");
|
||||
|
||||
if (JS_IsFunction(ctx, kentry_func)) val = JS_Call(ctx, kentry_func, JS_UNDEFINED, 0, NULL);
|
||||
else val = JS_ThrowReferenceError(ctx, "KEntry function not found or not callable");
|
||||
if (JS_IsFunction(ctx, kentry_func))
|
||||
val = JS_Call(ctx, kentry_func, JS_UNDEFINED, 0, NULL);
|
||||
else
|
||||
val = JS_ThrowReferenceError(ctx,
|
||||
"KEntry function not found or not callable");
|
||||
|
||||
JS_FreeValue(ctx, kentry_func);
|
||||
JS_FreeValue(ctx, global_obj);
|
||||
@@ -181,7 +206,8 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
if (str) {
|
||||
printf("!!! Kernel panic: %s !!!\n", str);
|
||||
JS_FreeCString(ctx, str);
|
||||
} else printf("!!! Kernel panic: [unknown] !!!\n");
|
||||
} else
|
||||
printf("!!! Kernel panic: [unknown] !!!\n");
|
||||
|
||||
JS_FreeValue(ctx, ex);
|
||||
} else {
|
||||
@@ -189,7 +215,8 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
if (str) {
|
||||
printf("!!! Kernel panic: %s !!!\n", str);
|
||||
JS_FreeCString(ctx, str);
|
||||
} else printf("!!! Kernel panic: [unknown] !!!\n");
|
||||
} else
|
||||
printf("!!! Kernel panic: [unknown] !!!\n");
|
||||
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
@@ -197,7 +224,8 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
for(;;);
|
||||
for (;;)
|
||||
;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
6
src/scripts/dev-setup/default.clangd
Normal file
6
src/scripts/dev-setup/default.clangd
Normal file
@@ -0,0 +1,6 @@
|
||||
CompileFlags:
|
||||
CompilationDatabase: .
|
||||
Add:
|
||||
- "-I%%workspaceFolder%%/src/core/compat"
|
||||
- "-I%%workspaceFolder%%/src/lib/quickjs"
|
||||
- "-I%%workspaceFolder%%/out/system"
|
||||
1
src/scripts/setup_dev.sh
Executable file
1
src/scripts/setup_dev.sh
Executable file
@@ -0,0 +1 @@
|
||||
cp ./src/scripts/dev-setup/default.clangd .clangd && sed -i.bak "s|%%workspaceFolder%%|$(pwd)|g" .clangd && rm .clangd.bak
|
||||
Reference in New Issue
Block a user