diff --git a/boredos.iso b/boredos.iso index 8fa38ac..8df977c 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/memory_manager.o b/build/memory_manager.o index 35707d6..5a1ea03 100644 Binary files a/build/memory_manager.o and b/build/memory_manager.o differ diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 4696ee6..9ce6acf 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -80,47 +80,38 @@ uint64_t elf_load(const char *path, uint64_t user_pml4) { if (p_memsz == 0) continue; - // Calculate page-aligned boundaries - uint64_t align_offset = p_vaddr & 0xFFF; - uint64_t start_page = p_vaddr & ~0xFFF; - uint64_t num_pages = (p_memsz + align_offset + 0xFFF) / 4096; + // Calculate boundaries for bulk allocation + uintptr_t align_offset = p_vaddr & 0xFFF; + uintptr_t start_page = p_vaddr & ~0xFFFFFFFFFFFFF000ULL; // Wait, mask should be ~0xFFF + start_page = p_vaddr & ~0xFFFULL; + size_t total_needed = (p_memsz + align_offset + 4095) & ~4095ULL; + size_t num_pages = total_needed / 4096; - // Allocate and Map Pages + // Bulk allocate physical memory for the entire segment + // Note: We allocate page by page but map them sequentially. + // A better way is to allocate a large contiguous block if possible, + // but our kmalloc_aligned handles arbitrary sizes. + void* bulk_phys = kmalloc_aligned(total_needed, 4096); + if (!bulk_phys) { + serial_write("[ELF] Error: Out of memory bulk allocating segment\n"); + fat32_close(file); + return 0; + } + + // Zero out entire segment (BSS and padding) in one go + mem_memset(bulk_phys, 0, total_needed); + + // Bulk read from disk for the entire filesz part + if (p_filesz > 0) { + fat32_seek(file, p_offset, 0); + fat32_read(file, (uint8_t*)bulk_phys + align_offset, (uint32_t)p_filesz); + } + + // Map all pages for (uint64_t p = 0; p < num_pages; p++) { uint64_t vaddr = start_page + (p * 4096); - void* phys = kmalloc_aligned(4096, 4096); - if (!phys) { - serial_write("[ELF] Error: Out of memory mapping PT_LOAD\n"); - fat32_close(file); - return 0; - } - - // Map page to user space (Present, RW, User) - paging_map_page(user_pml4, vaddr, v2p((uint64_t)phys), 0x07); - - // Zero out the entire page (handles BSS and padding) - uint8_t* dest = (uint8_t*)phys; - for (int j=0; j<4096; j++) dest[j] = 0; - - // Copy data from file if available for this page - uint64_t page_vaddr_start = vaddr; - uint64_t page_vaddr_end = vaddr + 4096; - - // What part of the segment (p_vaddr to p_vaddr + p_filesz) overlaps this page? - uint64_t overlap_vaddr_start = p_vaddr; - if (page_vaddr_start > overlap_vaddr_start) overlap_vaddr_start = page_vaddr_start; - - uint64_t overlap_vaddr_end = p_vaddr + p_filesz; - if (page_vaddr_end < overlap_vaddr_end) overlap_vaddr_end = page_vaddr_end; - - if (overlap_vaddr_start < overlap_vaddr_end) { - uint64_t copy_size = overlap_vaddr_end - overlap_vaddr_start; - uint64_t dest_offset = overlap_vaddr_start - page_vaddr_start; - uint64_t file_offset = p_offset + (overlap_vaddr_start - p_vaddr); - - fat32_seek(file, file_offset, 0); - fat32_read(file, dest + dest_offset, (uint32_t)copy_size); - } + uint64_t phys_addr = v2p((uint64_t)bulk_phys + (p * 4096)); + paging_map_page(user_pml4, vaddr, phys_addr, 0x07); } } } diff --git a/src/kernel/lwipopts.h b/src/kernel/lwipopts.h index cc4cd01..795f494 100644 --- a/src/kernel/lwipopts.h +++ b/src/kernel/lwipopts.h @@ -21,11 +21,11 @@ #define LWIP_NETIF_LINK_CALLBACK 1 #define TCP_MSS 1460 -#define TCP_WND (4 * TCP_MSS) -#define TCP_SND_BUF (4 * TCP_MSS) +#define TCP_WND (32 * TCP_MSS) +#define TCP_SND_BUF (32 * TCP_MSS) +#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF/TCP_MSS)) #define MEM_ALIGNMENT 8 -#define MEM_SIZE (256 * 1024) #define LWIP_CHKSUM_ALGORITHM 3 @@ -34,6 +34,9 @@ // Memory management #define MEMP_MEM_MALLOC 0 #define MEM_LIBC_MALLOC 0 -#define MEM_SIZE (2 * 1024 * 1024) +#define MEM_SIZE (16 * 1024 * 1024) +#define PBUF_POOL_SIZE 256 +#define MEMP_NUM_TCP_SEG 128 +#define MEMP_NUM_PBUF 256 #endif /* LWIPOPTS_H */ diff --git a/src/kernel/memory_manager.c b/src/kernel/memory_manager.c index 26d4a44..9ff9031 100644 --- a/src/kernel/memory_manager.c +++ b/src/kernel/memory_manager.c @@ -148,6 +148,29 @@ void memory_manager_init_from_memmap(struct limine_memmap_response *memmap) { serial_write(" MB\n"); } +// Internal helper to insert a block at a specific index +static void insert_block_at(int idx, void* addr, size_t size, bool allocated, uint32_t id) { + if (block_count >= MAX_ALLOCATIONS) return; + for (int j = block_count; j > idx; j--) { + block_list[j] = block_list[j - 1]; + } + block_list[idx].address = addr; + block_list[idx].size = size; + block_list[idx].allocated = allocated; + block_list[idx].allocation_id = id; + block_list[idx].timestamp = (allocated) ? get_timestamp() : 0; + block_count++; +} + +// Internal helper to remove a block at a specific index +static void remove_block_at(int idx) { + if (idx < 0 || idx >= block_count) return; + for (int j = idx; j < block_count - 1; j++) { + block_list[j] = block_list[j + 1]; + } + block_count--; +} + void* kmalloc_aligned(size_t size, size_t alignment) { if (!initialized || size == 0) return NULL; @@ -171,52 +194,53 @@ void* kmalloc_aligned(size_t size, size_t alignment) { size_t padding = aligned_addr - block_start; if (block_size >= size + padding) { - int needed_slots = 0; - if (padding > 0) needed_slots++; + // Check if we have enough slots for potential splits + int extra_needed = 0; + if (padding > 0) extra_needed++; size_t remaining_size = block_size - (size + padding); - if (remaining_size > 0) { - needed_slots++; - } else { - // The current slot will be reused for the allocation. - } - - if (block_count + needed_slots > MAX_ALLOCATIONS) { - continue; // Cannot fit metadata for this split + if (remaining_size > 0) extra_needed++; + + if (block_count + extra_needed > MAX_ALLOCATIONS) { + continue; } void* ptr = (void*)aligned_addr; + uint32_t alloc_id = ++allocation_counter; + + // We are splitting block_list[i]. + // Possible outcomes: + // 1. [Padding (Free)] [Allocated] [Remaining (Free)] + // 2. [Padding (Free)] [Allocated] + // 3. [Allocated] [Remaining (Free)] + // 4. [Allocated] + + // We'll modify block_list[i] and insert others as needed. + // To keep things simple and maintain sorted order, we update from right to left or carefully. - // Perform the split - if (remaining_size > 0) { - - block_list[block_count].address = ptr; - block_list[block_count].size = size; - block_list[block_count].allocated = true; - block_list[block_count].allocation_id = ++allocation_counter; - block_list[block_count].timestamp = get_timestamp(); - block_count++; - - block_list[i].address = (void*)(aligned_addr + size); - block_list[i].size = remaining_size; - block_list[i].allocated = false; - } else { + if (padding > 0 && remaining_size > 0) { + // Case 1: Split into 3 + block_list[i].size = padding; // Padding stays at i + insert_block_at(i + 1, ptr, size, true, alloc_id); + insert_block_at(i + 2, (void*)(aligned_addr + size), remaining_size, false, 0); + } else if (padding > 0) { + // Case 2: Split into 2 + block_list[i].size = padding; + insert_block_at(i + 1, ptr, size, true, alloc_id); + } else if (remaining_size > 0) { + // Case 3: Split into 2 block_list[i].address = ptr; block_list[i].size = size; block_list[i].allocated = true; - block_list[i].allocation_id = ++allocation_counter; + block_list[i].allocation_id = alloc_id; + block_list[i].timestamp = get_timestamp(); + insert_block_at(i + 1, (void*)(aligned_addr + size), remaining_size, false, 0); + } else { + // Case 4: Perfect fit + block_list[i].allocated = true; + block_list[i].allocation_id = alloc_id; block_list[i].timestamp = get_timestamp(); } - if (padding > 0) { - block_list[block_count].address = (void*)block_start; - block_list[block_count].size = padding; - block_list[block_count].allocated = false; - block_list[block_count].allocation_id = 0; - block_count++; - } - - sort_block_list(); - total_allocated += size; if (total_allocated > peak_allocated) peak_allocated = total_allocated; @@ -257,25 +281,13 @@ void kfree(void *ptr) { block_list[block_idx].allocated = false; block_list[block_idx].allocation_id = 0; - // Merge adjacent blocks. We sort first to make adjacency checking trivial. - sort_block_list(); - - // Re-find the block (it might have moved during sort) - for (int i = 0; i < block_count; i++) { - if (block_list[i].address == ptr) { - block_idx = i; - break; - } - } - // Merge with next block if possible if (block_idx + 1 < block_count && !block_list[block_idx + 1].allocated) { uintptr_t current_end = (uintptr_t)block_list[block_idx].address + block_list[block_idx].size; uintptr_t next_start = (uintptr_t)block_list[block_idx + 1].address; if (current_end == next_start) { block_list[block_idx].size += block_list[block_idx + 1].size; - for (int i = block_idx + 1; i < block_count - 1; i++) block_list[i] = block_list[i + 1]; - block_count--; + remove_block_at(block_idx + 1); } } @@ -285,8 +297,7 @@ void kfree(void *ptr) { uintptr_t current_start = (uintptr_t)block_list[block_idx].address; if (prev_end == current_start) { block_list[block_idx - 1].size += block_list[block_idx].size; - for (int i = block_idx; i < block_count - 1; i++) block_list[i] = block_list[i + 1]; - block_count--; + remove_block_at(block_idx); } } diff --git a/src/kernel/memory_manager.h b/src/kernel/memory_manager.h index 91e557d..14e1147 100644 --- a/src/kernel/memory_manager.h +++ b/src/kernel/memory_manager.h @@ -11,7 +11,7 @@ // Memory Manager Configuration #define DEFAULT_POOL_SIZE (128 * 1024 * 1024) // 128MB default -#define MAX_ALLOCATIONS 16384 // Increased for larger pools +#define MAX_ALLOCATIONS 262144 // Increased for larger pools #define MAX_FRAGMENTATION_SLOTS 2048 // Allocation block metadata diff --git a/src/kernel/network.c b/src/kernel/network.c index 73aa7f6..6460da2 100644 --- a/src/kernel/network.c +++ b/src/kernel/network.c @@ -260,7 +260,11 @@ int network_tcp_recv(void *buf, size_t max_len) { } // We already have data or we timed out (return 0 handled above) - size_t copied = pbuf_copy_partial(tcp_recv_queue, buf, (u16_t)max_len, 0); + size_t to_copy = max_len; + if (to_copy > tcp_recv_queue->tot_len) to_copy = tcp_recv_queue->tot_len; + if (to_copy > 0xFFFF) to_copy = 0xFFFF; // pbuf_copy_partial limit + + size_t copied = pbuf_copy_partial(tcp_recv_queue, buf, (u16_t)to_copy, 0); struct pbuf *remainder = pbuf_free_header(tcp_recv_queue, (u16_t)copied); if (current_tcp_pcb) tcp_recved(current_tcp_pcb, (u16_t)copied); tcp_recv_queue = remainder; diff --git a/src/kernel/userland/browser.c b/src/kernel/userland/browser.c index ce93e44..f598db4 100644 --- a/src/kernel/userland/browser.c +++ b/src/kernel/userland/browser.c @@ -12,7 +12,7 @@ #define WIN_H 960 #define URL_BAR_H 30 #define SCROLL_BAR_W 16 -#define RESP_BUF_SIZE (1024 * 1024) +#define RESP_BUF_SIZE (32 * 1024 * 1024) #define COLOR_URL_BAR 0xFF303030 #define COLOR_URL_TEXT 0xFFF0F0F0 @@ -88,9 +88,11 @@ typedef struct { char form_action[256]; char input_name[64]; int form_id; + int input_cursor; + int input_scroll; } RenderElement; -#define MAX_ELEMENTS 8192 +#define MAX_ELEMENTS 65536 static RenderElement elements[MAX_ELEMENTS]; static int element_count = 0; @@ -103,7 +105,10 @@ static int next_form_id = 1; static ui_window_t win_browser; static int scroll_y = 0; static int total_content_height = 0; -static int focused_element = -1; // -1 for URL bar, >= 0 for page elements +static int focused_element = -1; + +static void parse_html(const char *html); +static void browser_paint(void); static void browser_clear(void) { for (int i = 0; i < element_count; i++) { @@ -146,7 +151,7 @@ static int parse_ip(const char* str, net_ipv4_address_t* ip) { return 0; } -static int fetch_content(const char *url, char *dest_buf, int max_len) { +static int fetch_content(const char *url, char *dest_buf, int max_len, bool progressive) { const char* host_start = url; if (url[0] == 'h' && url[1] == 't' && url[2] == 't' && url[3] == 'p') { if (url[4] == 's' && url[5] == ':') host_start = url + 8; @@ -205,11 +210,25 @@ static int fetch_content(const char *url, char *dest_buf, int max_len) { sys_tcp_send(request, r - request); int total = 0; + int last_render = 0; while (1) { int len = sys_tcp_recv(dest_buf + total, max_len - 1 - total); if (len <= 0) break; total += len; if (total >= max_len - 1) break; + + if (progressive && total - last_render > 16384) { + dest_buf[total] = 0; + char *body = strstr(dest_buf, "\r\n\r\n"); + if (body) { + body += 4; + if (!strstr(dest_buf, "Transfer-Encoding: chunked")) { + parse_html(body); + browser_paint(); + last_render = total; + } + } + } } dest_buf[total] = 0; sys_tcp_close(); @@ -280,7 +299,7 @@ static void load_image(RenderElement *el) { *u = 0; } static char img_resp[RESP_BUF_SIZE]; - int resp_len = fetch_content(url, img_resp, sizeof(img_resp)); + int resp_len = fetch_content(url, img_resp, sizeof(img_resp), false); char *body = strstr(img_resp, "\r\n\r\n"); if (body) { body += 4; @@ -312,7 +331,7 @@ static void flush_line(bool centered) { el->y = cur_line_y; offset_x += el->w; if (el->tag == TAG_IMG && el->img_h + 10 > max_h) max_h = el->img_h + 10; - if ((el->tag == TAG_INPUT || el->tag == TAG_BUTTON) && 24 + 10 > max_h) max_h = 24 + 10; + if ((el->tag == TAG_INPUT || el->tag == TAG_BUTTON) && 20 + 10 > max_h) max_h = 20 + 10; } cur_line_y += max_h; cur_line_x = 10; @@ -402,13 +421,15 @@ static void parse_html(const char *html) { RenderElement *el = &elements[element_count++]; int idx = element_count - 1; for (int k=0; k<(int)sizeof(RenderElement); k++) ((char*)el)[k] = 0; - el->tag = TAG_INPUT; el->w = 160; el->h = 24; el->centered = is_centered; + el->tag = TAG_INPUT; el->w = 160; el->h = 20; el->centered = is_centered; char *val = str_istrstr(attr_buf, "value=\""); char *ph = str_istrstr(attr_buf, "placeholder=\""); char *type = str_istrstr(attr_buf, "type=\""); char *name = str_istrstr(attr_buf, "name=\""); el->form_id = current_form_id; + el->input_cursor = 0; + el->input_scroll = 0; int l; l = 0; while(current_form_action[l]) { el->form_action[l] = current_form_action[l]; l++; } el->form_action[l] = 0; @@ -476,23 +497,11 @@ static void parse_html(const char *html) { static void browser_paint(void) { ui_draw_rect(win_browser, 0, 0, WIN_W, WIN_H, COLOR_BG); - ui_draw_rect(win_browser, 0, 0, WIN_W, URL_BAR_H, COLOR_URL_BAR); - ui_draw_string(win_browser, 10, 8, url_input_buffer, COLOR_URL_TEXT); - if (focused_element == -1) { - ui_draw_rect(win_browser, 10 + url_cursor * 8, 22, 8, 2, COLOR_URL_TEXT); - } - // Scroll bar - ui_draw_rect(win_browser, WIN_W - SCROLL_BAR_W, URL_BAR_H, SCROLL_BAR_W, WIN_H - URL_BAR_H, COLOR_SCROLL_BG); - int thumb_h = (WIN_H - URL_BAR_H) * (WIN_H - URL_BAR_H) / (total_content_height > WIN_H ? total_content_height : WIN_H); - if (thumb_h < 20) thumb_h = 20; - int thumb_y = URL_BAR_H + (scroll_y * (WIN_H - URL_BAR_H - thumb_h)) / (total_content_height > WIN_H - URL_BAR_H ? total_content_height - (WIN_H - URL_BAR_H) : 1); - ui_draw_rect(win_browser, WIN_W - SCROLL_BAR_W + 2, thumb_y, SCROLL_BAR_W - 4, thumb_h, COLOR_SCROLL_BTN); - for (int i = 0; i < element_count; i++) { RenderElement *el = &elements[i]; int draw_y = el->y - scroll_y + URL_BAR_H; - if (draw_y < URL_BAR_H - 1000 || draw_y > WIN_H) continue; + if (draw_y < URL_BAR_H - 400 || draw_y > WIN_H) continue; if (el->tag == TAG_IMG) { if (el->img_pixels) ui_draw_image(win_browser, el->x, draw_y, el->img_w, el->img_h, el->img_pixels); else ui_draw_rect(win_browser, el->x, draw_y, 100, 80, 0xFFCCCCCC); @@ -503,10 +512,22 @@ static void browser_paint(void) { ui_draw_rect(win_browser, el->x, draw_y + el->h - 1, el->w, 1, border); ui_draw_rect(win_browser, el->x, draw_y, 1, el->h, border); ui_draw_rect(win_browser, el->x + el->w - 1, draw_y, 1, el->h, border); - ui_draw_string(win_browser, el->x + 5, draw_y + 4, el->attr_value, (focused_element == i) ? 0xFF000000 : 0xFF808080); + + char visible[64]; + int v_len = 0; + int max_v = (el->w - 10) / 8; + if (max_v > 63) max_v = 63; + for (int k = el->input_scroll; el->attr_value[k] && v_len < max_v; k++) { + visible[v_len++] = el->attr_value[k]; + } + visible[v_len] = 0; + ui_draw_string(win_browser, el->x + 5, draw_y + 2, visible, (focused_element == i) ? 0xFF000000 : 0xFF808080); + if (focused_element == i) { - int ilen = 0; while(el->attr_value[ilen]) ilen++; - ui_draw_rect(win_browser, el->x + 5 + ilen * 8, draw_y + 18, 8, 2, 0xFF000000); + int cursor_pos = el->input_cursor - el->input_scroll; + if (cursor_pos >= 0 && cursor_pos < max_v) { + ui_draw_rect(win_browser, el->x + 5 + cursor_pos * 8, draw_y + 16, 8, 2, 0xFF000000); + } } } else if (el->tag == TAG_BUTTON) { ui_draw_rect(win_browser, el->x, draw_y, el->w, el->h, 0xFFDDDDDD); @@ -520,11 +541,24 @@ static void browser_paint(void) { if (el->bold) ui_draw_string(win_browser, el->x + 1, draw_y, el->content, el->color); } } + + ui_draw_rect(win_browser, 0, 0, WIN_W, URL_BAR_H, COLOR_URL_BAR); + ui_draw_string(win_browser, 10, 8, url_input_buffer, COLOR_URL_TEXT); + if (focused_element == -1) { + ui_draw_rect(win_browser, 10 + url_cursor * 8, 22, 8, 2, COLOR_URL_TEXT); + } + + // Scroll bar + ui_draw_rect(win_browser, WIN_W - SCROLL_BAR_W, URL_BAR_H, SCROLL_BAR_W, WIN_H - URL_BAR_H, COLOR_SCROLL_BG); + int thumb_h = (WIN_H - URL_BAR_H) * (WIN_H - URL_BAR_H) / (total_content_height > WIN_H ? total_content_height : WIN_H); + if (thumb_h < 20) thumb_h = 20; + int thumb_y = URL_BAR_H + (scroll_y * (WIN_H - URL_BAR_H - thumb_h)) / (total_content_height > WIN_H - URL_BAR_H ? total_content_height - (WIN_H - URL_BAR_H) : 1); + ui_draw_rect(win_browser, WIN_W - SCROLL_BAR_W + 2, thumb_y, SCROLL_BAR_W - 4, thumb_h, COLOR_SCROLL_BTN); } static void navigate(const char *url) { static char main_resp[RESP_BUF_SIZE]; - int resp_len = fetch_content(url, main_resp, sizeof(main_resp)); + int resp_len = fetch_content(url, main_resp, sizeof(main_resp), true); if (resp_len <= 0) return; char *body = strstr(main_resp, "\r\n\r\n"); if (body) { @@ -544,7 +578,7 @@ static void net_init_if_needed(void) { } int main(int argc, char **argv) { - win_browser = ui_window_create("Boredweb", 50, 50, WIN_W, WIN_H); + win_browser = ui_window_create("Bored Web", 50, 50, WIN_W, WIN_H); net_init_if_needed(); if (argc > 1) { int k=0; while(argv[1][k]) { url_input_buffer[k] = argv[1][k]; k++; } url_input_buffer[k] = 0; url_cursor = k; } navigate(url_input_buffer); @@ -655,8 +689,20 @@ int main(int argc, char **argv) { char c = (char)ev.arg1; if (focused_element == -1) { if (c == 13 || c == 10) { navigate(url_input_buffer); scroll_y = 0; } - else if (c == 127 || c == 8) { if (url_cursor > 0) url_input_buffer[--url_cursor] = 0; } - else if (c >= 32 && c <= 126 && url_cursor < 511) { url_input_buffer[url_cursor++] = c; url_input_buffer[url_cursor] = 0; } + else if (c == 19) { if (url_cursor > 0) url_cursor--; } + else if (c == 20) { int len = 0; while(url_input_buffer[len]) len++; if (url_cursor < len) url_cursor++; } + else if (c == 127 || c == 8) { + if (url_cursor > 0) { + int len = 0; while(url_input_buffer[len]) len++; + for (int k=url_cursor-1; k= 32 && c <= 126 && url_cursor < 511) { + int len = 0; while(url_input_buffer[len]) len++; + for (int k=len; k>=url_cursor; k--) url_input_buffer[k+1] = url_input_buffer[k]; + url_input_buffer[url_cursor++] = c; + } } else { RenderElement *el = &elements[focused_element]; int len = 0; while(el->attr_value[len]) len++; @@ -701,8 +747,22 @@ int main(int argc, char **argv) { int j=0; while(search_url[j]) { url_input_buffer[j] = search_url[j]; j++; } url_input_buffer[j] = 0; url_cursor = j; navigate(url_input_buffer); scroll_y = 0; focused_element = -1; } - else if (c == 127 || c == 8) { if (len > 0) el->attr_value[--len] = 0; } - else if (c >= 32 && c <= 126 && len < 255) { el->attr_value[len++] = c; el->attr_value[len] = 0; } + else if (c == 19) { if (el->input_cursor > 0) el->input_cursor--; } + else if (c == 20) { if (el->input_cursor < len) el->input_cursor++; } + else if (c == 127 || c == 8) { + if (el->input_cursor > 0) { + for (int k=el->input_cursor-1; kattr_value[k] = el->attr_value[k+1]; + el->input_cursor--; + } + } + else if (c >= 32 && c <= 126 && len < 255) { + for (int k=len; k>=el->input_cursor; k--) el->attr_value[k+1] = el->attr_value[k]; + el->attr_value[el->input_cursor++] = c; + } + + int max_v = (el->w - 10) / 8; + if (el->input_cursor < el->input_scroll) el->input_scroll = el->input_cursor; + if (el->input_cursor >= el->input_scroll + max_v) el->input_scroll = el->input_cursor - max_v + 1; } if (c == 17) { scroll_y -= 40; }