#include "kernel.h" // This only runs once and from there on forth only interrupts will cause something to happen // e.g. displaying to screen and taking input from keyboard void _start() { // Initialize Global Variables and set up interrrupt handlers // These variables are a vulnerability to OS security if someone can adjust // the lower value in the kernel code (exploiting, for example, an Intel address hack) // than kernel memory and even kernel code can be overwritten // https://www.wired.com/story/intel-lab-istare-hack-chips/ // See libc/globals.h for KMEM_START and KMEM_END values // See libc/globals.h for UMEM_START and UMEM_END values kmem_addr = KMEM_START; kernel_mem_limit = KMEM_END; umem_addr = UMEM_START; user_mem_limit = UMEM_END; global_head = NULL; global_id = 0; isr_install(); irq_install(); kprint("Type something, it will go through the kernel\n" "Type HELP to list commands\n> "); } // An interrupt calls this function to parse what was typed in, this is, essentially, your // Command Line Interpreter for now. void user_input(char *input) { static u32 delete_id = 0; // static persistent variable for incrementing during test static node* umem_head = NULL; // static persistent head variable for contiguous block allocations if (strcmp(input, "END") == 0) { kprint("Stopping the CPU. Bye!\n"); asm volatile("hlt"); } else if (strncmp(input, "ADD", 3) == 0) { u32 base = 0x10000; u32 limit = 0x100; bool valid = true; if (sstrlen(input, 15) > 4) { char *args1 = input + 4; base = digit_conver(args1); int nDigits = digit_len(base); if (sstrlen(args1, 15) > nDigits + 1) { char *args2 = args1 + nDigits + 1; limit = digit_conver(args2); } if (base < 10000) { kprint("That memory address is reserved by the Kernel, addresses must be 10000+\n"); valid = false; } } if (valid) { umem_head = add_node( umem_head, base, limit-1, true, global_id++); } } else if (strcmp(input, "LIST") == 0) { kprint("***** FORWARD ****\n"); print_list( umem_head, true); kprint("***** REVERSE ****\n"); print_list( umem_head, false); } else if (strcmp(input, "SHORTLIST") == 0) { shortprint_list( umem_head, true); kprint("\n******************\n"); shortprint_list( umem_head, false); } else if (strcmp(input, "PAGE") == 0) { u32 phys_addr = 0; u32 page = umalloc(0x4200, 0, &phys_addr); kprint_hex( "Page: ", page, 10); kprint_hex(", physical address: ", phys_addr, 10); kprint("\n"); } else if (strcmp(input, "DELETE") == 0) { umem_head = remove_node_by_id( umem_head, delete_id++); } else if (strcmp(input, "INSERT") == 0) { node *new_node = create_node( 0x15000, 0x1100, true, global_id++); node *insert_point = find_id( umem_head, 3); umem_head = insert_node( umem_head, insert_point, new_node, true); new_node = create_node( 0x18000, 0x2100, true, global_id++); insert_point = find_id( umem_head, 5); umem_head = insert_node( umem_head, insert_point, new_node, false); } else if (strcmp(input, "SORTA") == 0) { umem_head = hacksort_list( umem_head, true); } else if (strcmp(input, "SORTD") == 0) { umem_head = hacksort_list( umem_head, false); } else if (strcmp(input, "SWAP") == 0) { node *n1 = find_id( umem_head, 1); node *n2 = find_id( umem_head, 5); node *n3 = find_id( umem_head, 3); node *n4 = find_id( umem_head, 7); swap_node_data( n1, n2); swap_node_data( n2, n3); swap_node_data( n3, n4); } else if (strcmp(input, "TEST") == 0) { char s1[10] = "ABCDFFGH\0"; char s2[10] = "ABCDEGH\0"; int x = strncmp( s1, s2, 5); kprint_hex( "STRNCMP: ", x, 16); kprint("\n"); x = sstrlen( s2, 10); kprint_hex( "SSTRLEN: ", x, 10); kprint("\n"); x = strlen( s2); kprint_hex( "STRLEN: ", x, 10); kprint("\n"); } else if (strcmp(input, "HELP") == 0) { kprint("Current Commands: ADD, LIST, SHORTLIST, PAGE, DELETE,\n"); kprint(" : END, INSERT, SORTA, SORTD, SWAP, TEST, HELP\n"); kprint(" Review the kernel.c source code to see what each command does.\n"); kprint(" These are hard coded and are just examples, modify as you see fit.\n"); kprint(" for example - TEST was just added so that I could test the strlen commands.\n"); } else if (strcmp(input, "HOLES") == 0) { node *holes = get_holes(umem_head); print_list( holes, false); } else if (strcmp(input, "RESULT") == 0) { node *holes = get_holes( umem_head); print_memory( umem_head, holes); } else if (strcmp(input, "START") == 0) { begin_output_example(); } else { kprint("You said: "); kprint(input); kprint("\n"); } kprint("> "); } int digit_len(unsigned digit) { if (digit >= 1000000000) return 10; if (digit >= 100000000) return 9; if (digit >= 10000000) return 8; if (digit >= 1000000) return 7; if (digit >= 100000) return 6; if (digit >= 10000) return 5; if (digit >= 1000) return 4; if (digit >= 100) return 3; if (digit >= 10) return 2; return 1; } int digit_conver(const char *hexString) { u32 result = 0; while (*hexString != '\0') { char hexChar = *hexString; if ((hexChar >= '0' && hexChar <= '9') || (hexChar >= 'A' && hexChar <= 'F')) { int digit = (hexChar >= '0' && hexChar <= '9') ? (hexChar - '0') : (10 + (hexChar - 'A')); result = result * 16 + digit; } else { break; } hexString++; } return result; } void print_memory(node *umem_head, node *hole_head) { u32 total_memory = 0x3FFFF; u32 free_memory = total_memory; int num_of_gaps = 0; int num_of_nodes = 0; while (umem_head != NULL) { num_of_nodes++; free_memory = free_memory - umem_head->limit_register; umem_head = umem_head->next; } while (hole_head != NULL) { num_of_gaps++; hole_head = hole_head->next; } u32 total_allocated = total_memory - free_memory; total_memory = (total_memory+1)/(0x400); char a[16]; int_to_ascii( total_memory-64, a, 16); kprint("\nTotal Physical Memory: "); kprint(a); kprint("kb\n"); free_memory = (free_memory+1)/(0x400); char b[16]; int_to_ascii( free_memory-64, b, 16); kprint("Total Free: "); kprint(b); kprint("kb\n"); total_allocated = (total_allocated+1)/(0x400); char c[16]; int_to_ascii( total_allocated, c, 16); kprint("Total Allocated: "); kprint(c); kprint("kb\n"); char d[16]; int_to_ascii( num_of_nodes, d, 16); kprint("Number of Allocations: "); kprint(d); kprint("\n"); char e[16]; int_to_ascii( num_of_gaps, e, 16); kprint("Number of Free Gaps: "); kprint(e); kprint("\n"); kprint("Start of Memory: 0x10000\nEnd of Memory: 0xFFFFF\n"); } node* get_holes(node* umem_head) { if (umem_head == NULL) { node *hole = NULL; hole = add_node(hole, 0x10000, 0x3FFFF, true, 0); return hole; } u32 hole_ids = 0; node *hole = NULL; if (umem_head->base_register-0x10000 != 0) { hole = add_node( hole, 0x10000, umem_head->base_register-0x10000-1, true, ++hole_ids); } while(umem_head != NULL) { if (umem_head->next != NULL) { node *next = umem_head->next; u32 total = umem_head->base_register+umem_head->limit_register; hole = add_node( hole, total, next->base_register-total-1, true, ++hole_ids); } else { hole = add_node( hole, umem_head->base_register+umem_head->limit_register-1, 0x3FFFF, true, ++hole_ids); } umem_head = umem_head->next; } return hole; } void begin_output_example() { static node* umem_head = NULL; // static persistent head variable for contiguous block allocations static node* holes_head = NULL; holes_head = get_holes(umem_head); // Display 1 kprint("Jonathan Turner - S02\n"); kprint("Current Allocation: \n"); print_memory(umem_head, holes_head); umem_head = add_node( umem_head, 0x10000, 0x3FF, true, 0); umem_head = add_node( umem_head, 0x11000, 0x1FF, true, 1); umem_head = add_node( umem_head, 0x12000, 0x3FF, true, 2); umem_head = add_node( umem_head, 0x15000, 0x7FF, true, 3); umem_head = add_node( umem_head, 0x22000, 0x1FFF, true, 4); // Display 2 print_memory(umem_head, holes_head); node* temp = umem_head->next; free_node(umem_head); umem_head = temp; umem_head->previous = NULL; print_memory(umem_head, holes_head); // print_list(umem_head, false); // print_list(get_holes(umem_head), false); // Display 3 temp = get_tail(umem_head); free_node(temp); print_memory(umem_head, holes_head); // print_list(umem_head, false); // print_list(get_holes(umem_head), false); // Display 4 umem_head = add_node( umem_head, 0x23000, 0x1FFF, true, 5); umem_head = add_node( umem_head, 0x25000, 0x3FFF, true, 6); print_memory(umem_head, holes_head); // print_list(umem_head, false); // print_list(get_holes(umem_head), false); // Display 5 temp = find_id(umem_head, 4); node* previous = temp->previous; previous->next = temp->next; free_node(temp); print_memory(umem_head, holes_head); // print_list(umem_head, false); // print_list(get_holes(umem_head), false); //Display 6 while (umem_head != NULL) { temp = umem_head->next; free_node(umem_head); umem_head = temp; } print_memory(umem_head, holes_head); // print_list(umem_head, false); // print_list(get_holes(umem_head), false); kprint("Jonathan Turner - S02"); }