feat: GPT, FAT32 driver, disks app, userspace adapted for multiple drives, and more
This commit is contained in:
@@ -54,6 +54,7 @@ namespace Montauk {
|
||||
static constexpr uint64_t SYS_RECVFROM = 40;
|
||||
static constexpr uint64_t SYS_FWRITE = 41;
|
||||
static constexpr uint64_t SYS_FCREATE = 42;
|
||||
static constexpr uint64_t SYS_FDELETE = 77;
|
||||
static constexpr uint64_t SYS_TERMSCALE = 43;
|
||||
static constexpr uint64_t SYS_RESOLVE = 44;
|
||||
static constexpr uint64_t SYS_GETRANDOM = 45;
|
||||
@@ -88,6 +89,15 @@ namespace Montauk {
|
||||
// Kernel introspection syscalls
|
||||
static constexpr uint64_t SYS_MEMSTATS = 67;
|
||||
|
||||
// Storage / partition syscalls
|
||||
static constexpr uint64_t SYS_PARTLIST = 70;
|
||||
static constexpr uint64_t SYS_DISKREAD = 71;
|
||||
static constexpr uint64_t SYS_DISKWRITE = 72;
|
||||
static constexpr uint64_t SYS_GPTINIT = 73;
|
||||
static constexpr uint64_t SYS_GPTADD = 74;
|
||||
static constexpr uint64_t SYS_FSMOUNT = 75;
|
||||
static constexpr uint64_t SYS_FSFORMAT = 76;
|
||||
|
||||
static constexpr int SOCK_TCP = 1;
|
||||
static constexpr int SOCK_UDP = 2;
|
||||
|
||||
@@ -198,6 +208,44 @@ namespace Montauk {
|
||||
char _pad2[1];
|
||||
};
|
||||
|
||||
struct PartGuid {
|
||||
uint32_t Data1;
|
||||
uint16_t Data2;
|
||||
uint16_t Data3;
|
||||
uint8_t Data4[8];
|
||||
};
|
||||
|
||||
struct PartInfo {
|
||||
int32_t blockDev; // block device index
|
||||
uint32_t _pad0;
|
||||
uint64_t startLba;
|
||||
uint64_t endLba;
|
||||
uint64_t sectorCount;
|
||||
PartGuid typeGuid;
|
||||
PartGuid uniqueGuid;
|
||||
uint64_t attributes;
|
||||
char name[72]; // ASCII partition name
|
||||
char typeName[24]; // human-readable type name
|
||||
};
|
||||
|
||||
struct GptAddParams {
|
||||
int32_t blockDev;
|
||||
uint32_t _pad0;
|
||||
uint64_t startLba; // 0 = auto (fill largest free region)
|
||||
uint64_t endLba; // 0 = auto
|
||||
PartGuid typeGuid;
|
||||
char name[72];
|
||||
};
|
||||
|
||||
// Filesystem type IDs for SYS_FSFORMAT
|
||||
static constexpr int FS_TYPE_FAT32 = 1;
|
||||
|
||||
struct FsFormatParams {
|
||||
int32_t partIndex; // global partition index
|
||||
int32_t fsType; // FS_TYPE_FAT32, etc.
|
||||
char label[32]; // volume label
|
||||
};
|
||||
|
||||
struct ProcInfo {
|
||||
int32_t pid;
|
||||
int32_t parentPid;
|
||||
|
||||
@@ -76,6 +76,9 @@ struct DesktopState {
|
||||
SvgIcon icon_folder_lg;
|
||||
SvgIcon icon_file_lg;
|
||||
SvgIcon icon_exec_lg;
|
||||
SvgIcon icon_drive;
|
||||
SvgIcon icon_drive_lg;
|
||||
SvgIcon icon_delete;
|
||||
|
||||
SvgIcon icon_settings;
|
||||
SvgIcon icon_reboot;
|
||||
@@ -88,6 +91,7 @@ struct DesktopState {
|
||||
SvgIcon icon_mandelbrot;
|
||||
SvgIcon icon_devexplorer;
|
||||
SvgIcon icon_spreadsheet;
|
||||
SvgIcon icon_disks;
|
||||
|
||||
bool ctx_menu_open;
|
||||
int ctx_menu_x, ctx_menu_y;
|
||||
|
||||
@@ -161,6 +161,23 @@ inline int svg_parse_fixed(const char* s, fixed_t* out) {
|
||||
val += (int32_t)(((int64_t)frac << 16) / frac_div);
|
||||
}
|
||||
|
||||
// Scientific notation (e.g. 2e-3, 7e-3)
|
||||
if (*p == 'e' || *p == 'E') {
|
||||
++p;
|
||||
bool exp_neg = false;
|
||||
if (*p == '-') { exp_neg = true; ++p; }
|
||||
else if (*p == '+') { ++p; }
|
||||
int exp_val = 0;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
exp_val = exp_val * 10 + (*p - '0');
|
||||
++p;
|
||||
}
|
||||
for (int i = 0; i < exp_val; i++) {
|
||||
if (exp_neg) val /= 10;
|
||||
else val *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) val = -val;
|
||||
*out = val;
|
||||
return (int)(p - s);
|
||||
@@ -1207,6 +1224,12 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
|
||||
// Heap-allocated path data buffer (avoids 8 KiB on the stack)
|
||||
char* d_buf = (char*)montauk::malloc(SVG_MAX_PATH_LEN);
|
||||
|
||||
// Group fill inheritance stack: track <g fill="..."> so child elements inherit
|
||||
static constexpr int MAX_GROUP_DEPTH = 8;
|
||||
struct GroupFill { Color color; bool has_fill; };
|
||||
GroupFill g_stack[MAX_GROUP_DEPTH];
|
||||
int g_depth = 0;
|
||||
|
||||
// Scan for <path, <circle, <rect elements — rasterize each individually
|
||||
// Skip elements inside <defs> blocks (they define reusable items, not rendered directly)
|
||||
const char* p = svg_data;
|
||||
@@ -1230,6 +1253,42 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track </g> closing tags to pop the group fill stack
|
||||
if (remaining > 3 && svg_strncmp(p, "</g>", 4)) {
|
||||
if (g_depth > 0) g_depth--;
|
||||
p += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track <g> opening tags for fill inheritance
|
||||
if (remaining > 2 && svg_strncmp(p, "<g", 2) && (svg_char_is_ws(p[2]) || p[2] == '>')) {
|
||||
const char* g_start = p;
|
||||
const char* g_end = p;
|
||||
while (g_end < end && *g_end != '>') ++g_end;
|
||||
if (g_end < end) ++g_end;
|
||||
int g_len = (int)(g_end - g_start);
|
||||
|
||||
if (g_depth < MAX_GROUP_DEPTH) {
|
||||
g_stack[g_depth].has_fill = false;
|
||||
Color gc = fill_color;
|
||||
char fbuf[64];
|
||||
int fLen = svg_get_attr(g_start, g_len, " fill", fbuf, sizeof(fbuf));
|
||||
if (fLen > 0) {
|
||||
int fr = svg_resolve_fill_value(fbuf, &gc, &grads);
|
||||
if (fr == 1) {
|
||||
g_stack[g_depth].color = gc;
|
||||
g_stack[g_depth].has_fill = true;
|
||||
} else if (fr == -1) {
|
||||
// fill="none" on group — children inherit none
|
||||
g_stack[g_depth].has_fill = false;
|
||||
}
|
||||
}
|
||||
g_depth++;
|
||||
}
|
||||
p = g_end;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for <path
|
||||
if (remaining > 5 && svg_strncmp(p, "<path", 5) && (svg_char_is_ws(p[5]) || p[5] == '/')) {
|
||||
const char* elem_start = p;
|
||||
@@ -1244,8 +1303,12 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine fill color for this element
|
||||
// Determine fill color: element's own fill, or inherit from nearest <g>
|
||||
Color elem_color = fill_color;
|
||||
// Apply inherited group fill as default
|
||||
for (int gi = g_depth - 1; gi >= 0; gi--) {
|
||||
if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; }
|
||||
}
|
||||
int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css);
|
||||
if (fillResult == -1) { p = elem_end; continue; } // fill="none"
|
||||
|
||||
@@ -1278,6 +1341,9 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
|
||||
}
|
||||
|
||||
Color elem_color = fill_color;
|
||||
for (int gi = g_depth - 1; gi >= 0; gi--) {
|
||||
if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; }
|
||||
}
|
||||
int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css);
|
||||
if (fillResult == -1) { p = elem_end; continue; }
|
||||
|
||||
@@ -1321,6 +1387,9 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
|
||||
}
|
||||
|
||||
Color elem_color = fill_color;
|
||||
for (int gi = g_depth - 1; gi >= 0; gi--) {
|
||||
if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; }
|
||||
}
|
||||
int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css);
|
||||
if (fillResult == -1) { p = elem_end; continue; }
|
||||
|
||||
|
||||
@@ -143,6 +143,9 @@ namespace montauk {
|
||||
inline int fcreate(const char* path) {
|
||||
return (int)syscall1(Montauk::SYS_FCREATE, (uint64_t)path);
|
||||
}
|
||||
inline int fdelete(const char* path) {
|
||||
return (int)syscall1(Montauk::SYS_FDELETE, (uint64_t)path);
|
||||
}
|
||||
|
||||
// Memory
|
||||
inline void* alloc(uint64_t size) { return (void*)syscall1(Montauk::SYS_ALLOC, size); }
|
||||
@@ -298,6 +301,35 @@ namespace montauk {
|
||||
return (int)syscall2(Montauk::SYS_DISKINFO, (uint64_t)buf, (uint64_t)port);
|
||||
}
|
||||
|
||||
// Partition table
|
||||
inline int partlist(Montauk::PartInfo* buf, int max) {
|
||||
return (int)syscall2(Montauk::SYS_PARTLIST, (uint64_t)buf, (uint64_t)max);
|
||||
}
|
||||
|
||||
// Raw block device I/O (driver-agnostic)
|
||||
inline int64_t disk_read(int blockDev, uint64_t lba, uint32_t sectorCount, void* buf) {
|
||||
return syscall4(Montauk::SYS_DISKREAD, (uint64_t)blockDev, lba,
|
||||
(uint64_t)sectorCount, (uint64_t)buf);
|
||||
}
|
||||
inline int64_t disk_write(int blockDev, uint64_t lba, uint32_t sectorCount, const void* buf) {
|
||||
return syscall4(Montauk::SYS_DISKWRITE, (uint64_t)blockDev, lba,
|
||||
(uint64_t)sectorCount, (uint64_t)buf);
|
||||
}
|
||||
|
||||
// GPT management
|
||||
inline int gpt_init(int blockDev) {
|
||||
return (int)syscall1(Montauk::SYS_GPTINIT, (uint64_t)blockDev);
|
||||
}
|
||||
inline int gpt_add(const Montauk::GptAddParams* params) {
|
||||
return (int)syscall1(Montauk::SYS_GPTADD, (uint64_t)params);
|
||||
}
|
||||
inline int fs_mount(int partIndex, int driveNum) {
|
||||
return (int)syscall2(Montauk::SYS_FSMOUNT, (uint64_t)partIndex, (uint64_t)driveNum);
|
||||
}
|
||||
inline int fs_format(const Montauk::FsFormatParams* params) {
|
||||
return (int)syscall1(Montauk::SYS_FSFORMAT, (uint64_t)params);
|
||||
}
|
||||
|
||||
// Kernel introspection
|
||||
inline void memstats(Montauk::MemStats* out) { syscall1(Montauk::SYS_MEMSTATS, (uint64_t)out); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user