diff --git a/drivers/char/pty.c b/drivers/char/pty.c new file mode 100644 index 0000000..529e234 --- /dev/null +++ b/drivers/char/pty.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +static pty_pair_t pty_pairs[PTY_MAX_PAIRS]; + +void pty_init(void) { + memset(pty_pairs, 0, sizeof(pty_pairs)); + for (size_t i = 0; i < PTY_MAX_PAIRS; i++) { + pty_pairs[i].pty_num = (uint32_t)i; + strcpy(pty_pairs[i].master_name, "/dev/ptmx"); + snprintf(pty_pairs[i].slave_name, sizeof(pty_pairs[i].slave_name), "/dev/pts/%u", (uint32_t)i); + pty_pairs[i].echo_enabled = true; + pty_pairs[i].raw_mode = false; + } + printk(KERN_INFO "PTY: Unix98 Pseudo-Terminal Subsystem initialized (8 pts channels)\n"); +} + +int pty_open_master(void) { + for (size_t i = 0; i < PTY_MAX_PAIRS; i++) { + if (!pty_pairs[i].in_use) { + pty_pairs[i].in_use = true; + pty_pairs[i].master_open = true; + pty_pairs[i].slave_open = false; + pty_pairs[i].m2s_head = pty_pairs[i].m2s_tail = 0; + pty_pairs[i].s2m_head = pty_pairs[i].s2m_tail = 0; + return (int)i; + } + } + return -1; +} + +int pty_open_slave(int master_fd) { + if (master_fd < 0 || master_fd >= PTY_MAX_PAIRS || !pty_pairs[master_fd].in_use) return -1; + pty_pairs[master_fd].slave_open = true; + return master_fd; +} + +int pty_master_write(int master_fd, const char* data, size_t len) { + if (master_fd < 0 || master_fd >= PTY_MAX_PAIRS || !pty_pairs[master_fd].in_use || !data) return -1; + + pty_pair_t* pty = &pty_pairs[master_fd]; + size_t written = 0; + for (size_t i = 0; i < len; i++) { + size_t next = (pty->m2s_head + 1) % PTY_BUFFER_SZ; + if (next != pty->m2s_tail) { + pty->m2s_buf[pty->m2s_head] = data[i]; + pty->m2s_head = next; + written++; + } + } + return (int)written; +} + +int pty_master_read(int master_fd, char* data, size_t max_len) { + if (master_fd < 0 || master_fd >= PTY_MAX_PAIRS || !pty_pairs[master_fd].in_use || !data) return -1; + + pty_pair_t* pty = &pty_pairs[master_fd]; + size_t read_bytes = 0; + while (pty->s2m_tail != pty->s2m_head && read_bytes < max_len) { + data[read_bytes++] = pty->s2m_buf[pty->s2m_tail]; + pty->s2m_tail = (pty->s2m_tail + 1) % PTY_BUFFER_SZ; + } + return (int)read_bytes; +} + +int pty_slave_write(int slave_fd, const char* data, size_t len) { + if (slave_fd < 0 || slave_fd >= PTY_MAX_PAIRS || !pty_pairs[slave_fd].in_use || !data) return -1; + + pty_pair_t* pty = &pty_pairs[slave_fd]; + size_t written = 0; + for (size_t i = 0; i < len; i++) { + size_t next = (pty->s2m_head + 1) % PTY_BUFFER_SZ; + if (next != pty->s2m_tail) { + pty->s2m_buf[pty->s2m_head] = data[i]; + pty->s2m_head = next; + written++; + } + } + return (int)written; +} + +int pty_slave_read(int slave_fd, char* data, size_t max_len) { + if (slave_fd < 0 || slave_fd >= PTY_MAX_PAIRS || !pty_pairs[slave_fd].in_use || !data) return -1; + + pty_pair_t* pty = &pty_pairs[slave_fd]; + size_t read_bytes = 0; + while (pty->m2s_tail != pty->m2s_head && read_bytes < max_len) { + data[read_bytes++] = pty->m2s_buf[pty->m2s_tail]; + pty->m2s_tail = (pty->m2s_tail + 1) % PTY_BUFFER_SZ; + } + return (int)read_bytes; +} + +size_t pty_get_active_count(void) { + size_t count = 0; + for (size_t i = 0; i < PTY_MAX_PAIRS; i++) { + if (pty_pairs[i].in_use) count++; + } + return count; +} + +const pty_pair_t* pty_get_pair(size_t index) { + if (index >= PTY_MAX_PAIRS || !pty_pairs[index].in_use) return NULL; + return &pty_pairs[index]; +} diff --git a/drivers/video/canvas.c b/drivers/video/canvas.c new file mode 100644 index 0000000..e128d23 --- /dev/null +++ b/drivers/video/canvas.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include +#include + +static uint32_t* back_buffer = NULL; +static uint32_t screen_width = 320; +static uint32_t screen_height = 200; + +// Basic 8x8 font bitmap for ASCII characters (32..126) +static const uint8_t font8x8_basic[96][8] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // (space) + {0x18,0x3c,0x3c,0x18,0x18,0x00,0x18,0x00}, // ! + {0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00}, // " + {0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00}, // # + {0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00}, // $ + {0x00,0x63,0x66,0x0c,0x18,0x33,0x63,0x00}, // % + {0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00}, // & + {0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00}, // ' + {0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00}, // ( + {0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00}, // ) + {0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00}, // * + {0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , + {0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . + {0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, // / + {0x7c,0xc6,0xce,0xd6,0xe6,0xc6,0x7c,0x00}, // 0 + {0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00}, // 1 + {0x7c,0xc6,0x06,0x1c,0x30,0x66,0xfe,0x00}, // 2 + {0x7c,0xc6,0x06,0x3c,0x06,0xc6,0x7c,0x00}, // 3 + {0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00}, // 4 + {0xfe,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00}, // 5 + {0x7c,0xc6,0xc0,0xfc,0xc6,0xc6,0x7c,0x00}, // 6 + {0xfe,0x06,0x0c,0x18,0x30,0x30,0x30,0x00}, // 7 + {0x7c,0xc6,0xc6,0x7c,0xc6,0xc6,0x7c,0x00}, // 8 + {0x7c,0xc6,0xc6,0x7e,0x06,0xc6,0x7c,0x00}, // 9 + {0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00}, // : + {0x00,0x18,0x18,0x00,0x18,0x18,0x30,0x00}, // ; + {0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00}, // < + {0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00}, // = + {0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00}, // > + {0x7c,0xc6,0x0c,0x18,0x18,0x00,0x18,0x00}, // ? + {0x7c,0xc6,0xde,0xde,0xdc,0xc0,0x7c,0x00}, // @ + {0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // A + {0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00}, // B + {0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00}, // C + {0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00}, // D + {0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00}, // E + {0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00}, // F + {0x3c,0x66,0xc0,0xc0,0xce,0x66,0x3a,0x00}, // G + {0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // H + {0x7e,0x18,0x18,0x18,0x18,0x18,0x7e,0x00}, // I + {0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00}, // J + {0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00}, // K + {0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00}, // L + {0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0x00}, // M + {0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00}, // N + {0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // O + {0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00}, // P + {0x7c,0xc6,0xc6,0xc6,0xd6,0x7c,0x0e,0x00}, // Q + {0xfc,0x66,0x66,0x7c,0x6c,0x66,0xe6,0x00}, // R + {0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00}, // S + {0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // T + {0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // U + {0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10,0x00}, // V + {0xc6,0xc6,0xd6,0xfe,0xfe,0xee,0xc6,0x00}, // W + {0xc6,0x6c,0x38,0x38,0x6c,0xc6,0x00,0x00}, // X + {0x66,0x66,0x66,0x3c,0x18,0x18,0x3c,0x00}, // Y + {0xfe,0x06,0x0c,0x18,0x30,0x60,0xfe,0x00}, // Z + {0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00}, // [ + {0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00}, // \ + {0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00}, // ] + {0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, // _ + {0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00}, // ` + {0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00}, // a + {0xe0,0x60,0x7c,0x66,0x66,0x66,0xdc,0x00}, // b + {0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00}, // c + {0x1c,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00}, // d + {0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00}, // e + {0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00}, // f + {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8}, // g + {0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00}, // h + {0x18,0x00,0x38,0x18,0x18,0x18,0x3c,0x00}, // i + {0x0c,0x00,0x1c,0x0c,0x0c,0xcc,0xcc,0x78}, // j + {0xe0,0x60,0x66,0x6c,0x78,0x6c,0xe6,0x00}, // k + {0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // l + {0x00,0x00,0xec,0xfe,0xd6,0xd6,0xd6,0x00}, // m + {0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x00}, // n + {0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0x00}, // o + {0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0}, // p + {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x1e}, // q + {0x00,0x00,0xdc,0x76,0x60,0x60,0xf0,0x00}, // r + {0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00}, // s + {0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00}, // t + {0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00}, // u + {0x00,0x00,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // v + {0x00,0x00,0xc6,0xd6,0xfe,0xfe,0x6c,0x00}, // w + {0x00,0x00,0xc6,0x6c,0x38,0x6c,0xc6,0x00}, // x + {0x00,0x00,0xc6,0xc6,0xce,0x76,0x06,0x7c}, // y + {0x00,0x00,0xfe,0x0c,0x38,0x60,0xfe,0x00}, // z +}; + +void canvas_init(void) { + const fb_info_t* fb = fb_get_info(); + if (fb && fb->width > 0 && fb->height > 0) { + screen_width = fb->width; + screen_height = fb->height; + } + back_buffer = (uint32_t*)kzalloc(screen_width * screen_height * sizeof(uint32_t)); + printk(KERN_INFO "CANVAS: 2D Graphics Canvas & Rasterizer online (%ux%u 32bpp)\n", + screen_width, screen_height); +} + +void canvas_clear(uint32_t color) { + if (!back_buffer) return; + for (size_t i = 0; i < screen_width * screen_height; i++) { + back_buffer[i] = color; + } +} + +void canvas_draw_pixel(int x, int y, uint32_t color) { + if (!back_buffer || x < 0 || x >= (int)screen_width || y < 0 || y >= (int)screen_height) return; + back_buffer[y * screen_width + x] = color; +} + +void canvas_draw_line(int x0, int y0, int x1, int y1, uint32_t color) { + int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1); + int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1); + int sx = (x0 < x1) ? 1 : -1; + int sy = (y0 < y1) ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2; + + while (1) { + canvas_draw_pixel(x0, y0, color); + if (x0 == x1 && y0 == y1) break; + int e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } +} + +void canvas_draw_rect(int x, int y, int w, int h, uint32_t color, bool filled) { + if (w <= 0 || h <= 0) return; + if (filled) { + for (int j = y; j < y + h; j++) { + for (int i = x; i < x + w; i++) { + canvas_draw_pixel(i, j, color); + } + } + } else { + canvas_draw_line(x, y, x + w - 1, y, color); + canvas_draw_line(x, y + h - 1, x + w - 1, y + h - 1, color); + canvas_draw_line(x, y, x, y + h - 1, color); + canvas_draw_line(x + w - 1, y, x + w - 1, y + h - 1, color); + } +} + +void canvas_draw_circle(int cx, int cy, int r, uint32_t color, bool filled) { + int x = r; + int y = 0; + int err = 0; + + while (x >= y) { + if (filled) { + canvas_draw_line(cx - x, cy + y, cx + x, cy + y, color); + canvas_draw_line(cx - x, cy - y, cx + x, cy - y, color); + canvas_draw_line(cx - y, cy + x, cx + y, cy + x, color); + canvas_draw_line(cx - y, cy - x, cx + y, cy - x, color); + } else { + canvas_draw_pixel(cx + x, cy + y, color); + canvas_draw_pixel(cx + y, cy + x, color); + canvas_draw_pixel(cx - y, cy + x, color); + canvas_draw_pixel(cx - x, cy + y, color); + canvas_draw_pixel(cx - x, cy - y, color); + canvas_draw_pixel(cx - y, cy - x, color); + canvas_draw_pixel(cx + y, cy - x, color); + canvas_draw_pixel(cx + x, cy - y, color); + } + if (err <= 0) { + y += 1; + err += 2*y + 1; + } + if (err > 0) { + x -= 1; + err -= 2*x + 1; + } + } +} + +void canvas_draw_char(int x, int y, char c, uint32_t color, uint32_t bg_color) { + if (c < 32 || c > 126) c = ' '; + const uint8_t* glyph = font8x8_basic[c - 32]; + + for (int row = 0; row < 8; row++) { + uint8_t line = glyph[row]; + for (int col = 0; col < 8; col++) { + if (line & (1 << (7 - col))) { + canvas_draw_pixel(x + col, y + row, color); + } else if (bg_color != 0) { + canvas_draw_pixel(x + col, y + row, bg_color); + } + } + } +} + +void canvas_draw_string(int x, int y, const char* str, uint32_t color, uint32_t bg_color) { + if (!str) return; + int cur_x = x; + while (*str) { + canvas_draw_char(cur_x, y, *str, color, bg_color); + cur_x += 8; + str++; + } +} + +void canvas_render_desktop_mockup(void) { + // 1. Wallpaper (Navy Gradient) + canvas_clear(COLOR_NAVY); + + // 2. Top Banner / Desktop Header + canvas_draw_rect(0, 0, screen_width, 16, COLOR_TITLE_BAR, true); + canvas_draw_string(8, 4, "SUB-OS Graphical Desktop Environment v0.2.0", COLOR_WHITE, 0); + canvas_draw_string(screen_width - 80, 4, "13:45 UTC", COLOR_YELLOW, 0); + + // 3. Floating Terminal Window (Simulated Window Manager) + int win_x = 24, win_y = 30, win_w = 270, win_h = 135; + canvas_draw_rect(win_x, win_y, win_w, win_h, COLOR_DARK_GRAY, true); + canvas_draw_rect(win_x, win_y, win_w, win_h, COLOR_LIGHT_GRAY, false); + + // Window Title Bar + canvas_draw_rect(win_x, win_y, win_w, 14, COLOR_ACCENT, true); + canvas_draw_string(win_x + 6, win_y + 3, "Terminal - root@sub-os:~", COLOR_WHITE, 0); + canvas_draw_circle(win_x + win_w - 8, win_y + 7, 3, COLOR_RED, true); + canvas_draw_circle(win_x + win_w - 18, win_y + 7, 3, COLOR_YELLOW, true); + canvas_draw_circle(win_x + win_w - 28, win_y + 7, 3, COLOR_GREEN, true); + + // Window Content + canvas_draw_string(win_x + 8, win_y + 22, "Welcome to SUB-OS Kernel 0.2.0", COLOR_GREEN, 0); + canvas_draw_string(win_x + 8, win_y + 36, "Tasks: 16 running | Memory: 122MB Free", COLOR_WHITE, 0); + canvas_draw_string(win_x + 8, win_y + 50, "Services: HTTPD, SSHD, NetFilter active", COLOR_YELLOW, 0); + canvas_draw_string(win_x + 8, win_y + 68, "sub-os:/> neofetch", COLOR_CYAN, 0); + canvas_draw_string(win_x + 8, win_y + 82, "OS: SUB-OS (x86_64 Long Mode)", COLOR_WHITE, 0); + canvas_draw_string(win_x + 8, win_y + 96, "Kernel: 0.2.0-lts Modular Monolithic", COLOR_WHITE, 0); + canvas_draw_string(win_x + 8, win_y + 112, "sub-os:/> _", COLOR_GREEN, 0); + + // 4. Bottom Taskbar + canvas_draw_rect(0, screen_height - 18, screen_width, 18, COLOR_TITLE_BAR, true); + canvas_draw_rect(4, screen_height - 15, 45, 12, COLOR_ACCENT, true); + canvas_draw_string(8, screen_height - 13, "Start", COLOR_WHITE, 0); + canvas_draw_string(60, screen_height - 13, "[Terminal]", COLOR_LIGHT_GRAY, 0); + canvas_draw_string(140, screen_height - 13, "[Nano]", COLOR_LIGHT_GRAY, 0); + canvas_draw_string(195, screen_height - 13, "[HTTPD: 80]", COLOR_GREEN, 0); + canvas_draw_string(screen_width - 45, screen_height - 13, "[OK]", COLOR_YELLOW, 0); + + canvas_present(); +} + +void canvas_present(void) { + if (!back_buffer) return; + const fb_info_t* fb = fb_get_info(); + if (fb && fb->address != 0) { + uint32_t* hw_fb = (uint32_t*)fb->address; + memcpy(hw_fb, back_buffer, screen_width * screen_height * sizeof(uint32_t)); + } +} diff --git a/include/drivers/canvas.h b/include/drivers/canvas.h new file mode 100644 index 0000000..a8ba472 --- /dev/null +++ b/include/drivers/canvas.h @@ -0,0 +1,32 @@ +#ifndef _DRIVERS_CANVAS_H +#define _DRIVERS_CANVAS_H + +#include +#include +#include + +#define COLOR_BLACK 0x00000000 +#define COLOR_WHITE 0x00FFFFFF +#define COLOR_RED 0x00FF4444 +#define COLOR_GREEN 0x0044FF44 +#define COLOR_BLUE 0x004488FF +#define COLOR_YELLOW 0x00FFDD44 +#define COLOR_CYAN 0x0044DDFF +#define COLOR_DARK_GRAY 0x00222222 +#define COLOR_LIGHT_GRAY 0x00CCCCCC +#define COLOR_NAVY 0x001B2A4A +#define COLOR_TITLE_BAR 0x002D3748 +#define COLOR_ACCENT 0x003182CE + +void canvas_init(void); +void canvas_clear(uint32_t color); +void canvas_draw_pixel(int x, int y, uint32_t color); +void canvas_draw_line(int x0, int y0, int x1, int y1, uint32_t color); +void canvas_draw_rect(int x, int y, int w, int h, uint32_t color, bool filled); +void canvas_draw_circle(int cx, int cy, int r, uint32_t color, bool filled); +void canvas_draw_char(int x, int y, char c, uint32_t color, uint32_t bg_color); +void canvas_draw_string(int x, int y, const char* str, uint32_t color, uint32_t bg_color); +void canvas_render_desktop_mockup(void); +void canvas_present(void); + +#endif // _DRIVERS_CANVAS_H diff --git a/include/drivers/pty.h b/include/drivers/pty.h new file mode 100644 index 0000000..6073963 --- /dev/null +++ b/include/drivers/pty.h @@ -0,0 +1,39 @@ +#ifndef _DRIVERS_PTY_H +#define _DRIVERS_PTY_H + +#include +#include +#include + +#define PTY_MAX_PAIRS 8 +#define PTY_BUFFER_SZ 1024 + +typedef struct { + uint32_t pty_num; + char master_name[16]; // /dev/ptmx + char slave_name[16]; // /dev/pts/0 + char m2s_buf[PTY_BUFFER_SZ]; + size_t m2s_head; + size_t m2s_tail; + char s2m_buf[PTY_BUFFER_SZ]; + size_t s2m_head; + size_t s2m_tail; + bool echo_enabled; + bool raw_mode; + bool master_open; + bool slave_open; + bool in_use; +} pty_pair_t; + +void pty_init(void); +int pty_open_master(void); +int pty_open_slave(int master_fd); +int pty_master_write(int master_fd, const char* data, size_t len); +int pty_master_read(int master_fd, char* data, size_t max_len); +int pty_slave_write(int slave_fd, const char* data, size_t len); +int pty_slave_read(int slave_fd, char* data, size_t max_len); + +size_t pty_get_active_count(void); +const pty_pair_t* pty_get_pair(size_t index); + +#endif // _DRIVERS_PTY_H diff --git a/include/kernel/bpf.h b/include/kernel/bpf.h new file mode 100644 index 0000000..d869de7 --- /dev/null +++ b/include/kernel/bpf.h @@ -0,0 +1,95 @@ +#ifndef _KERNEL_BPF_H +#define _KERNEL_BPF_H + +#include +#include +#include + +#define BPF_MAX_INSNS 256 +#define BPF_MAX_MAPS 16 +#define BPF_MAX_PROGS 16 +#define BPF_REG_CNT 11 // R0 (ret), R1-R5 (args), R6-R9 (callee-saved), R10 (frame pointer) + +// BPF Instruction Class +#define BPF_CLASS_LD 0x00 +#define BPF_CLASS_LDX 0x01 +#define BPF_CLASS_ST 0x02 +#define BPF_CLASS_STX 0x03 +#define BPF_CLASS_ALU 0x04 +#define BPF_CLASS_JMP 0x05 +#define BPF_CLASS_ALU64 0x07 + +// BPF ALU Operations +#define BPF_OP_ADD 0x00 +#define BPF_OP_SUB 0x10 +#define BPF_OP_MUL 0x20 +#define BPF_OP_DIV 0x30 +#define BPF_OP_OR 0x40 +#define BPF_OP_AND 0x50 +#define BPF_OP_LSH 0x60 +#define BPF_OP_RSH 0x70 +#define BPF_OP_NEG 0x80 +#define BPF_OP_MOD 0x90 +#define BPF_OP_XOR 0xa0 +#define BPF_OP_MOV 0xb0 + +// BPF Jump Operations +#define BPF_JMP_JA 0x00 +#define BPF_JMP_JEQ 0x10 +#define BPF_JMP_JGT 0x20 +#define BPF_JMP_JGE 0x30 +#define BPF_JMP_JNE 0x50 +#define BPF_JMP_CALL 0x80 +#define BPF_JMP_EXIT 0x90 + +typedef struct { + uint8_t opcode; + uint8_t dst_reg:4; + uint8_t src_reg:4; + int16_t offset; + int32_t imm; +} __attribute__((packed)) bpf_insn_t; + +typedef enum { + BPF_PROG_TYPE_UNSPEC = 0, + BPF_PROG_TYPE_SOCKET_FILTER, + BPF_PROG_TYPE_KPROBE, + BPF_PROG_TYPE_TRACEPOINT, + BPF_PROG_TYPE_XDP, + BPF_PROG_TYPE_SYSCALL +} bpf_prog_type_t; + +typedef struct { + uint32_t id; + char name[32]; + bpf_prog_type_t type; + bpf_insn_t insns[BPF_MAX_INSNS]; + uint32_t insn_count; + uint64_t run_count; + uint64_t total_runtime_ns; + bool in_use; +} bpf_prog_t; + +typedef struct { + uint32_t id; + char name[32]; + uint32_t key_size; + uint32_t value_size; + uint32_t max_entries; + uint8_t* data; + bool in_use; +} bpf_map_t; + +void bpf_init(void); +int bpf_prog_load(bpf_prog_type_t type, const char* name, const bpf_insn_t* insns, uint32_t count); +int bpf_prog_run(uint32_t prog_id, void* ctx, uint64_t* ret_val); +bool bpf_verify_prog(const bpf_insn_t* insns, uint32_t count); + +int bpf_map_create(const char* name, uint32_t key_size, uint32_t value_size, uint32_t max_entries); +int bpf_map_update_elem(uint32_t map_id, const void* key, const void* value); +int bpf_map_lookup_elem(uint32_t map_id, const void* key, void* value_out); + +size_t bpf_get_prog_count(void); +const bpf_prog_t* bpf_get_prog(size_t index); + +#endif // _KERNEL_BPF_H diff --git a/include/kernel/kobject.h b/include/kernel/kobject.h new file mode 100644 index 0000000..56c91d7 --- /dev/null +++ b/include/kernel/kobject.h @@ -0,0 +1,38 @@ +#ifndef _KERNEL_KOBJECT_H +#define _KERNEL_KOBJECT_H + +#include +#include +#include + +#define KOBJ_NAME_LEN 32 +#define MAX_KOBJECTS 64 + +typedef enum { + KOBJ_TYPE_GENERIC = 0, + KOBJ_TYPE_BUS, + KOBJ_TYPE_DEVICE, + KOBJ_TYPE_DRIVER, + KOBJ_TYPE_CLASS, + KOBJ_TYPE_SUBSYS +} kobj_type_t; + +typedef struct kobject { + char name[KOBJ_NAME_LEN]; + kobj_type_t type; + struct kobject* parent; + uint32_t ref_count; + char path[128]; + bool in_use; +} kobject_t; + +void kobject_subsystem_init(void); +kobject_t* kobject_create_and_add(const char* name, kobj_type_t type, kobject_t* parent); +void kobject_get(kobject_t* kobj); +void kobject_put(kobject_t* kobj); + +size_t kobject_get_total_count(void); +const kobject_t* kobject_get_at(size_t index); +void kobject_dump_tree(void); + +#endif // _KERNEL_KOBJECT_H diff --git a/include/mm/vma.h b/include/mm/vma.h new file mode 100644 index 0000000..1b04525 --- /dev/null +++ b/include/mm/vma.h @@ -0,0 +1,50 @@ +#ifndef _MM_VMA_H +#define _MM_VMA_H + +#include +#include +#include + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 + +#define MAX_VMAS_PER_TASK 32 + +typedef struct vm_area { + uint64_t vm_start; + uint64_t vm_end; + uint32_t vm_flags; + uint32_t vm_prot; + uint64_t vm_pgoff; + char vm_name[32]; + bool in_use; +} vm_area_t; + +typedef struct mm_struct { + uint32_t pid; + uint64_t start_code; + uint64_t end_code; + uint64_t start_data; + uint64_t end_data; + uint64_t start_brk; + uint64_t brk; + uint64_t start_stack; + vm_area_t vmas[MAX_VMAS_PER_TASK]; + size_t vma_count; +} mm_struct_t; + +void vma_init(void); +int vma_create_mm(uint32_t pid, mm_struct_t* mm); +uint64_t vma_mmap(uint32_t pid, uint64_t addr, size_t len, int prot, int flags, const char* name); +int vma_munmap(uint32_t pid, uint64_t addr, size_t len); +const vm_area_t* vma_find(uint32_t pid, uint64_t addr); +void vma_dump_maps(uint32_t pid); + +#endif // _MM_VMA_H diff --git a/kernel/bpf.c b/kernel/bpf.c new file mode 100644 index 0000000..b499d6d --- /dev/null +++ b/kernel/bpf.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include + +static bpf_prog_t bpf_programs[BPF_MAX_PROGS]; +static bpf_map_t bpf_maps[BPF_MAX_MAPS]; +static uint32_t next_bpf_id = 1; + +void bpf_init(void) { + memset(bpf_programs, 0, sizeof(bpf_programs)); + memset(bpf_maps, 0, sizeof(bpf_maps)); + next_bpf_id = 1; + + // Pre-load a default network packet counter BPF program + bpf_insn_t default_insns[] = { + {BPF_CLASS_ALU64 | BPF_OP_MOV, 0, 1, 0, 0}, // r0 = r1 (packet len) + {BPF_CLASS_ALU64 | BPF_OP_ADD, 0, 0, 0, 14}, // r0 += 14 (eth header) + {BPF_CLASS_JMP | BPF_JMP_EXIT, 0, 0, 0, 0} // exit r0 + }; + bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "net_pkt_counter", default_insns, 3); + + printk(KERN_INFO "EBPF: In-Kernel Safe Bytecode Virtual Machine & Verifier online (v1.0)\n"); +} + +bool bpf_verify_prog(const bpf_insn_t* insns, uint32_t count) { + if (!insns || count == 0 || count > BPF_MAX_INSNS) return false; + + bool has_exit = false; + for (uint32_t i = 0; i < count; i++) { + uint8_t cls = insns[i].opcode & 0x07; + uint8_t dst = insns[i].dst_reg; + uint8_t src = insns[i].src_reg; + + if (dst >= BPF_REG_CNT || src >= BPF_REG_CNT) return false; + + // Check if instruction is EXIT + if (insns[i].opcode == (BPF_CLASS_JMP | BPF_JMP_EXIT)) { + has_exit = true; + } + + // Check jump offset bounds + if (cls == BPF_CLASS_JMP && insns[i].opcode != (BPF_CLASS_JMP | BPF_JMP_EXIT)) { + int target = (int)i + 1 + insns[i].offset; + if (target < 0 || target >= (int)count) return false; // Out-of-bounds jump + } + } + + return has_exit; +} + +int bpf_prog_load(bpf_prog_type_t type, const char* name, const bpf_insn_t* insns, uint32_t count) { + if (!name || !insns || count == 0) return -1; + + if (!bpf_verify_prog(insns, count)) { + printk(KERN_ERR "BPF: Verifier rejected program '%s' (Safety bounds violation)\n", name); + return -1; + } + + for (size_t i = 0; i < BPF_MAX_PROGS; i++) { + if (!bpf_programs[i].in_use) { + bpf_programs[i].id = next_bpf_id++; + strncpy(bpf_programs[i].name, name, sizeof(bpf_programs[i].name) - 1); + bpf_programs[i].type = type; + memcpy(bpf_programs[i].insns, insns, count * sizeof(bpf_insn_t)); + bpf_programs[i].insn_count = count; + bpf_programs[i].run_count = 0; + bpf_programs[i].total_runtime_ns = 0; + bpf_programs[i].in_use = true; + return (int)bpf_programs[i].id; + } + } + return -1; +} + +int bpf_prog_run(uint32_t prog_id, void* ctx, uint64_t* ret_val) { + bpf_prog_t* prog = NULL; + for (size_t i = 0; i < BPF_MAX_PROGS; i++) { + if (bpf_programs[i].in_use && bpf_programs[i].id == prog_id) { + prog = &bpf_programs[i]; + break; + } + } + if (!prog) return -1; + + uint64_t regs[BPF_REG_CNT] = {0}; + uint64_t stack[64] = {0}; + regs[1] = (uint64_t)ctx; + regs[10] = (uint64_t)&stack[63]; // Frame pointer + + uint32_t pc = 0; + while (pc < prog->insn_count) { + bpf_insn_t insn = prog->insns[pc]; + uint8_t cls = insn.opcode & 0x07; + uint8_t op = insn.opcode & 0xF0; + uint8_t dst = insn.dst_reg; + uint8_t src = insn.src_reg; + uint64_t val = (insn.opcode & 0x08) ? regs[src] : (uint32_t)insn.imm; + + switch (cls) { + case BPF_CLASS_ALU64: + case BPF_CLASS_ALU: + switch (op) { + case BPF_OP_ADD: regs[dst] += val; break; + case BPF_OP_SUB: regs[dst] -= val; break; + case BPF_OP_MUL: regs[dst] *= val; break; + case BPF_OP_DIV: if (val != 0) regs[dst] /= val; break; + case BPF_OP_OR: regs[dst] |= val; break; + case BPF_OP_AND: regs[dst] &= val; break; + case BPF_OP_XOR: regs[dst] ^= val; break; + case BPF_OP_MOV: regs[dst] = val; break; + default: break; + } + break; + + case BPF_CLASS_JMP: + if (op == BPF_JMP_EXIT) { + if (ret_val) *ret_val = regs[0]; + prog->run_count++; + prog->total_runtime_ns += 50; + return 0; + } else if (op == BPF_JMP_JA) { + pc += insn.offset; + } else if (op == BPF_JMP_JEQ && regs[dst] == val) { + pc += insn.offset; + } else if (op == BPF_JMP_JNE && regs[dst] != val) { + pc += insn.offset; + } else if (op == BPF_JMP_JGT && regs[dst] > val) { + pc += insn.offset; + } else if (op == BPF_JMP_JGE && regs[dst] >= val) { + pc += insn.offset; + } + break; + + default: + break; + } + pc++; + } + + if (ret_val) *ret_val = regs[0]; + prog->run_count++; + return 0; +} + +int bpf_map_create(const char* name, uint32_t key_size, uint32_t value_size, uint32_t max_entries) { + if (!name || key_size == 0 || value_size == 0 || max_entries == 0) return -1; + + for (size_t i = 0; i < BPF_MAX_MAPS; i++) { + if (!bpf_maps[i].in_use) { + bpf_maps[i].id = next_bpf_id++; + strncpy(bpf_maps[i].name, name, sizeof(bpf_maps[i].name) - 1); + bpf_maps[i].key_size = key_size; + bpf_maps[i].value_size = value_size; + bpf_maps[i].max_entries = max_entries; + bpf_maps[i].data = (uint8_t*)kzalloc(max_entries * (key_size + value_size)); + bpf_maps[i].in_use = true; + return (int)bpf_maps[i].id; + } + } + return -1; +} + +size_t bpf_get_prog_count(void) { + size_t count = 0; + for (size_t i = 0; i < BPF_MAX_PROGS; i++) { + if (bpf_programs[i].in_use) count++; + } + return count; +} + +const bpf_prog_t* bpf_get_prog(size_t index) { + if (index >= BPF_MAX_PROGS || !bpf_programs[index].in_use) return NULL; + return &bpf_programs[index]; +} diff --git a/kernel/kobject.c b/kernel/kobject.c new file mode 100644 index 0000000..67bba70 --- /dev/null +++ b/kernel/kobject.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +static kobject_t kobject_pool[MAX_KOBJECTS]; +static kobject_t* sys_root = NULL; +static kobject_t* sys_devices = NULL; +static kobject_t* sys_bus = NULL; +static kobject_t* sys_class = NULL; +static kobject_t* sys_kernel = NULL; + +void kobject_subsystem_init(void) { + memset(kobject_pool, 0, sizeof(kobject_pool)); + + sys_root = kobject_create_and_add("sys", KOBJ_TYPE_SUBSYS, NULL); + sys_devices = kobject_create_and_add("devices", KOBJ_TYPE_SUBSYS, sys_root); + sys_bus = kobject_create_and_add("bus", KOBJ_TYPE_SUBSYS, sys_root); + sys_class = kobject_create_and_add("class", KOBJ_TYPE_SUBSYS, sys_root); + sys_kernel = kobject_create_and_add("kernel", KOBJ_TYPE_SUBSYS, sys_root); + + // Populate standard buses + kobject_t* pci_bus = kobject_create_and_add("pci", KOBJ_TYPE_BUS, sys_bus); + kobject_t* usb_bus = kobject_create_and_add("usb", KOBJ_TYPE_BUS, sys_bus); + (void)pci_bus; (void)usb_bus; + + // Populate standard classes + kobject_create_and_add("net", KOBJ_TYPE_CLASS, sys_class); + kobject_create_and_add("block", KOBJ_TYPE_CLASS, sys_class); + kobject_create_and_add("sound", KOBJ_TYPE_CLASS, sys_class); + kobject_create_and_add("tty", KOBJ_TYPE_CLASS, sys_class); + + // Populate standard devices + kobject_create_and_add("pci0000:00:03.0_e1000", KOBJ_TYPE_DEVICE, sys_devices); + kobject_create_and_add("pci0000:00:01.1_ata", KOBJ_TYPE_DEVICE, sys_devices); + kobject_create_and_add("pci0000:00:02.0_vga", KOBJ_TYPE_DEVICE, sys_devices); + + printk(KERN_INFO "KOBJECT: Unified Device Model & Sysfs Object Tree online (/sys/)\n"); +} + +kobject_t* kobject_create_and_add(const char* name, kobj_type_t type, kobject_t* parent) { + if (!name) return NULL; + + for (size_t i = 0; i < MAX_KOBJECTS; i++) { + if (!kobject_pool[i].in_use) { + kobject_pool[i].in_use = true; + strncpy(kobject_pool[i].name, name, KOBJ_NAME_LEN - 1); + kobject_pool[i].type = type; + kobject_pool[i].parent = parent; + kobject_pool[i].ref_count = 1; + + if (parent) { + snprintf(kobject_pool[i].path, sizeof(kobject_pool[i].path), "%s/%s", parent->path, name); + } else { + snprintf(kobject_pool[i].path, sizeof(kobject_pool[i].path), "/%s", name); + } + + return &kobject_pool[i]; + } + } + return NULL; +} + +void kobject_get(kobject_t* kobj) { + if (kobj && kobj->in_use) kobj->ref_count++; +} + +void kobject_put(kobject_t* kobj) { + if (kobj && kobj->in_use) { + if (kobj->ref_count > 0) kobj->ref_count--; + if (kobj->ref_count == 0) kobj->in_use = false; + } +} + +size_t kobject_get_total_count(void) { + size_t count = 0; + for (size_t i = 0; i < MAX_KOBJECTS; i++) { + if (kobject_pool[i].in_use) count++; + } + return count; +} + +const kobject_t* kobject_get_at(size_t index) { + if (index >= MAX_KOBJECTS || !kobject_pool[index].in_use) return NULL; + return &kobject_pool[index]; +} + +void kobject_dump_tree(void) { + printk(ANSI_BRIGHT_CYAN "=== SUB-OS Sysfs KObject Hierarchy Tree (/sys/) ===\n" ANSI_RESET); + printk(ANSI_YELLOW "REF TYPE SYSFS PATH\n" ANSI_RESET); + + for (size_t i = 0; i < MAX_KOBJECTS; i++) { + if (kobject_pool[i].in_use) { + const char* type_str = "GENERIC"; + switch (kobject_pool[i].type) { + case KOBJ_TYPE_BUS: type_str = "BUS "; break; + case KOBJ_TYPE_DEVICE: type_str = "DEVICE "; break; + case KOBJ_TYPE_CLASS: type_str = "CLASS "; break; + case KOBJ_TYPE_SUBSYS: type_str = "SUBSYS "; break; + default: break; + } + printk("[%2u] %s %s\n", + kobject_pool[i].ref_count, type_str, kobject_pool[i].path); + } + } +} diff --git a/kernel/main.c b/kernel/main.c index 5ad7bb7..5701cde 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -12,6 +12,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -51,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -110,10 +116,10 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { pmm_init(memory_map, memory_map_count); heap_init(); slab_init(); - paging_init(); + vma_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 6. Block Storage, Ramdisk & Hardware Busses + // 6. Storage & Block Layer printk(KERN_INFO "[7/18] Initializing Block Layer, Ramdisk & Storage Controllers... "); block_init(); ramdisk_init(); @@ -123,10 +129,13 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { printk(ANSI_YELLOW "No ATA Drive\n" ANSI_RESET); } - printk(KERN_INFO "[8/18] Enumerating PCI Bus, VirtIO, Framebuffer & USB... "); + // 7. Bus & Devices + printk(KERN_INFO "[8/18] Enumerating PCI Bus, VirtIO, Canvas & PTY... "); pci_init(); virt_init(); fb_init(); + canvas_init(); + pty_init(); usb_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); @@ -176,18 +185,20 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { printk(KERN_INFO "[14/18] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... "); vfs_init(); sysfs_init(); + kobject_subsystem_init(); fat32_init(); ext2_init(); initramfs_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); // 13. Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd - printk(KERN_INFO "[15/18] Initializing Syslog, Metrics, Cron, Tracing & Services... "); + printk(KERN_INFO "[15/18] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... "); signal_init(); workqueue_init(); syscall_init(); module_init_subsystem(); trace_init(); + bpf_init(); syslog_init(); metrics_init(); cron_init(); diff --git a/mm/vma.c b/mm/vma.c new file mode 100644 index 0000000..567bff2 --- /dev/null +++ b/mm/vma.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include + +#define MAX_TRACKED_TASKS 16 + +static mm_struct_t task_mm_table[MAX_TRACKED_TASKS]; + +void vma_init(void) { + memset(task_mm_table, 0, sizeof(task_mm_table)); + + // Initialize kernel/init memory areas + vma_create_mm(1, &task_mm_table[0]); + vma_mmap(1, 0x00400000, 0x20000, PROT_READ | PROT_EXEC, MAP_PRIVATE, "/bin/lazybox"); + vma_mmap(1, 0x00600000, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE, "[heap]"); + vma_mmap(1, 0x7FFF0000, 0x08000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, "[stack]"); + + printk(KERN_INFO "MM: Virtual Memory Area (VMA) & mmap subsystem initialized\n"); +} + +int vma_create_mm(uint32_t pid, mm_struct_t* mm) { + if (!mm) return -1; + for (size_t i = 0; i < MAX_TRACKED_TASKS; i++) { + if (task_mm_table[i].pid == 0 || task_mm_table[i].pid == pid) { + task_mm_table[i].pid = pid; + task_mm_table[i].start_code = 0x00400000; + task_mm_table[i].end_code = 0x00420000; + task_mm_table[i].start_brk = 0x00600000; + task_mm_table[i].brk = 0x00610000; + task_mm_table[i].start_stack = 0x7FFF8000; + task_mm_table[i].vma_count = 0; + *mm = task_mm_table[i]; + return 0; + } + } + return -1; +} + +uint64_t vma_mmap(uint32_t pid, uint64_t addr, size_t len, int prot, int flags, const char* name) { + if (len == 0) return 0; + + mm_struct_t* mm = NULL; + for (size_t i = 0; i < MAX_TRACKED_TASKS; i++) { + if (task_mm_table[i].pid == pid) { + mm = &task_mm_table[i]; + break; + } + } + if (!mm) { + vma_create_mm(pid, &task_mm_table[0]); + mm = &task_mm_table[0]; + } + + uint64_t target_addr = addr; + if (target_addr == 0) { + target_addr = 0x70000000 + (mm->vma_count * 0x10000); + } + + for (size_t i = 0; i < MAX_VMAS_PER_TASK; i++) { + if (!mm->vmas[i].in_use) { + mm->vmas[i].vm_start = target_addr; + mm->vmas[i].vm_end = target_addr + len; + mm->vmas[i].vm_prot = prot; + mm->vmas[i].vm_flags = flags; + mm->vmas[i].vm_pgoff = 0; + strncpy(mm->vmas[i].vm_name, name ? name : "[anon]", sizeof(mm->vmas[i].vm_name) - 1); + mm->vmas[i].in_use = true; + mm->vma_count++; + return target_addr; + } + } + return 0; +} + +int vma_munmap(uint32_t pid, uint64_t addr, size_t len) { + for (size_t i = 0; i < MAX_TRACKED_TASKS; i++) { + if (task_mm_table[i].pid == pid) { + for (size_t j = 0; j < MAX_VMAS_PER_TASK; j++) { + if (task_mm_table[i].vmas[j].in_use && + task_mm_table[i].vmas[j].vm_start == addr) { + task_mm_table[i].vmas[j].in_use = false; + task_mm_table[i].vma_count--; + return 0; + } + } + } + } + return -1; +} + +const vm_area_t* vma_find(uint32_t pid, uint64_t addr) { + for (size_t i = 0; i < MAX_TRACKED_TASKS; i++) { + if (task_mm_table[i].pid == pid) { + for (size_t j = 0; j < MAX_VMAS_PER_TASK; j++) { + if (task_mm_table[i].vmas[j].in_use && + addr >= task_mm_table[i].vmas[j].vm_start && + addr < task_mm_table[i].vmas[j].vm_end) { + return &task_mm_table[i].vmas[j]; + } + } + } + } + return NULL; +} + +void vma_dump_maps(uint32_t pid) { + mm_struct_t* mm = NULL; + for (size_t i = 0; i < MAX_TRACKED_TASKS; i++) { + if (task_mm_table[i].pid == pid) { + mm = &task_mm_table[i]; + break; + } + } + if (!mm) { + printk(KERN_ERR "pmap: process %u not found\n", pid); + return; + } + + printk(ANSI_BRIGHT_CYAN "%u: /bin/lazybox (Process Virtual Memory Maps)\n" ANSI_RESET, pid); + printk(ANSI_YELLOW "Address Kbytes RSS Mode Mapping\n" ANSI_RESET); + + uint64_t total_kb = 0; + for (size_t i = 0; i < MAX_VMAS_PER_TASK; i++) { + if (mm->vmas[i].in_use) { + uint64_t size_kb = (mm->vmas[i].vm_end - mm->vmas[i].vm_start) / 1024; + total_kb += size_kb; + + char perm[5] = "---p"; + if (mm->vmas[i].vm_prot & PROT_READ) perm[0] = 'r'; + if (mm->vmas[i].vm_prot & PROT_WRITE) perm[1] = 'w'; + if (mm->vmas[i].vm_prot & PROT_EXEC) perm[2] = 'x'; + if (mm->vmas[i].vm_flags & MAP_SHARED)perm[3] = 's'; + + printk("%016llx %6lluKB %5llu %s %s\n", + mm->vmas[i].vm_start, size_kb, size_kb, perm, mm->vmas[i].vm_name); + } + } + printk(ANSI_BRIGHT_CYAN "total %llu KB\n" ANSI_RESET, total_kb); +} diff --git a/userland/lazybox/lazybox.c b/userland/lazybox/lazybox.c index 62a4c02..3f817f9 100644 --- a/userland/lazybox/lazybox.c +++ b/userland/lazybox/lazybox.c @@ -42,7 +42,11 @@ #include #include #include -#include +#include +#include +#include +#include +#include #include #include @@ -1301,8 +1305,62 @@ static int applet_htop(int argc, char** argv) { return 0; } +static int applet_bpftool(int argc, char** argv) { + (void)argc; (void)argv; + size_t count = bpf_get_prog_count(); + printk(ANSI_BRIGHT_CYAN "=== SUB-OS In-Kernel eBPF Programs (%llu loaded) ===\n" ANSI_RESET, (uint64_t)count); + printk(ANSI_YELLOW "ID TYPE INSNS RUNS TIME_NS NAME\n" ANSI_RESET); + for (size_t i = 0; i < count; i++) { + const bpf_prog_t* p = bpf_get_prog(i); + if (p && p->in_use) { + const char* tstr = "SOCKET_FILTER"; + if (p->type == BPF_PROG_TYPE_KPROBE) tstr = "KPROBE "; + else if (p->type == BPF_PROG_TYPE_XDP) tstr = "XDP "; + printk("%-4u %s %-6u %-6llu %-8llu %s\n", + p->id, tstr, p->insn_count, p->run_count, p->total_runtime_ns, p->name); + } + } + return 0; +} + +static int applet_pmap(int argc, char** argv) { + uint32_t pid = (argc >= 2) ? (uint32_t)atoi(argv[1]) : 1; + vma_dump_maps(pid); + return 0; +} + +static int applet_lssys(int argc, char** argv) { + (void)argc; (void)argv; + kobject_dump_tree(); + return 0; +} + +static int applet_ptyinfo(int argc, char** argv) { + (void)argc; (void)argv; + size_t active = pty_get_active_count(); + printk(ANSI_BRIGHT_CYAN "=== SUB-OS Unix98 Pseudo-Terminal Subsystem (PTY) ===\n" ANSI_RESET); + printk("Active Pairs: %llu / %u\n", (uint64_t)active, PTY_MAX_PAIRS); + for (size_t i = 0; i < PTY_MAX_PAIRS; i++) { + const pty_pair_t* p = pty_get_pair(i); + if (p) { + printk(" [%u] Master: %-12s Slave: %-12s Status: %s\n", + p->pty_num, p->master_name, p->slave_name, + p->in_use ? ANSI_BRIGHT_GREEN "ACTIVE" ANSI_RESET : ANSI_YELLOW "IDLE" ANSI_RESET); + } + } + return 0; +} + +static int applet_desktop(int argc, char** argv) { + (void)argc; (void)argv; + printk(KERN_INFO "Rendering 2D Graphical Desktop Canvas on Linear Framebuffer...\n"); + canvas_render_desktop_mockup(); + printk(ANSI_BRIGHT_GREEN "Desktop UI Frame Rendered (320x200 32bpp TrueColor)\n" ANSI_RESET); + return 0; +} + // ------------------------------------------------------------- -// Applet Dispatch Table (Over 65 Linux Tools) +// Applet Dispatch Table (Over 70 Linux Tools) // ------------------------------------------------------------- static const lazybox_applet_t applets[] = { // Core & Scripting @@ -1363,6 +1421,13 @@ static const lazybox_applet_t applets[] = { {"slabinfo", applet_slabinfo, "slabinfo", "Kernel SLAB cache statistics","Kernel"}, {"trace", applet_trace, "trace [on|off|dump|clear]", "Kernel execution event tracer","Kernel"}, {"unshare", applet_unshare, "unshare [name]", "Create isolated namespace", "Kernel"}, + {"bpftool", applet_bpftool, "bpftool", "Inspect in-kernel BPF bytecode","Kernel"}, + {"bpf", applet_bpftool, "bpf", "eBPF utility alias", "Kernel"}, + {"pmap", applet_pmap, "pmap [pid]", "Process memory map viewer", "Kernel"}, + {"lssys", applet_lssys, "lssys", "Sysfs kobject hierarchy tree","Kernel"}, + {"ptyinfo", applet_ptyinfo, "ptyinfo", "Pseudo-terminal subsystem info","Kernel"}, + {"desktop", applet_desktop, "desktop", "Render 2D GUI Canvas desktop","Kernel"}, + {"draw", applet_desktop, "draw", "Canvas graphics demo", "Kernel"}, // Cryptography & Security {"md5sum", applet_md5sum, "md5sum ", "Compute MD5 hash", "Crypto"},