diff --git a/.gitignore b/.gitignore
index 47bd505..a312394 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
*.iso
isodir
sysroot
+.vscode/
\ No newline at end of file
diff --git a/README.md b/README.md
index 42b6b8d..1a2846a 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,31 @@ Welcome to rockOS project, a hobby OS that aims to run rogue and nethack.
- GDT
- IDT
- PIC initialization
-- Semi-working keyboard driver
-- Paging initialization
+- PIT timer
+- Keyboard driver
+- Bitmap paging
+
+
+## Usage
+Just grab the latest ISO from the releases and run it on a virtual machine
+such as QEMU or Virtualbox, bare-metal not tested.
+
+## Build
+### Dependencies
+- a decent compiler such as gcc or clang
+- grub2 (if under GNU/Linux)
+- xorriso
+- make
+- tar (for compiling the toolchain)
+- wget/curl (for compiling the toolchain)
+
+If it is your first time building, you need to compile the toolchain first.
+For that, you just need to run build-toolchain.sh, which will download binutils,
+gcc, grub if youre on macOS, and then compile them to $HOME/opt/cross-i686 by default
+which can be changed from the prompt.
+
+After you compiled the toolchain and added $PREFIX/bin to your PATH as instructed by the script,
+you can run qemu.sh to compile and open the OS on QEMU or iso.sh to just generate the ISO.
## Credits
@@ -15,7 +38,7 @@ Welcome to rockOS project, a hobby OS that aims to run rogue and nethack.
## Acknowledgements
-- osdev.org community for huge documentation on osdev
+- osdev.org community for huge documentation on OS Development
- musl for libc implementation
diff --git a/build-toolchain.sh b/build-toolchain.sh
index 8e6aa0d..3a8f455 100755
--- a/build-toolchain.sh
+++ b/build-toolchain.sh
@@ -1,7 +1,8 @@
#!/bin/sh
#export PREFIX="$HOME/opt/cross-i686"
-echo "Welcome to rockOS toolchain compilation script, where would you like to install your toolchain?\nLeave blank for $HOME/opt/cross-i686"
+echo "Welcome to rockOS toolchain compilation script, where would you like to install your toolchain?"
+echo "Leave blank for $HOME/opt/cross-i686"
read PREFIX
@@ -9,6 +10,10 @@ if [ "$PREFIX" == "" ]; then
export PREFIX="$HOME/opt/cross-i686"
fi
+echo "This is the location you chose: $PREFIX"
+echo "Press Enter to continue"
+read continue
+
mkdir -p "$PREFIX"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"
diff --git a/kernel/include/rockos/paging.h b/kernel/include/rockos/paging.h
index ffc86d9..775b16b 100644
--- a/kernel/include/rockos/paging.h
+++ b/kernel/include/rockos/paging.h
@@ -16,10 +16,16 @@
* along with this program. If not, see .
*/
+#include
+
#ifndef _ROCKOS_PAGING_H
#define _ROCKOS_PAGING_H
#define PAGE_ENTRIES 1024
-#define PAGE_SIZE 4 * PAGE_ENTRIES
+#define PAGE_SIZE 4096
+
+uint32_t* get_page();
+void set_page_free(uint32_t*);
+uint32_t get_used_memsize();
#endif
\ No newline at end of file
diff --git a/kernel/rockos/kernel.c b/kernel/rockos/kernel.c
index ff34bd5..20979f7 100644
--- a/kernel/rockos/kernel.c
+++ b/kernel/rockos/kernel.c
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
void kernel_main(void) {
printf("Hello, kernel World!\n");
@@ -15,13 +16,34 @@ void kernel_main(void) {
printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2);
initialize_keyset();
- outb(0x70, (0x80 << 7) | 0x0); // Seconds
+ outb(0x70, 0x0); // Seconds
uint8_t sec = inb(0x71);
- outb(0x70, (0x80 << 7) | 0x02); // Minutes
+ outb(0x70, 0x02); // Minutes
uint8_t min = inb(0x71);
- outb(0x70, (0x80 << 7) | 0x04); // Hours
+ outb(0x70, 0x04); // Hours
uint8_t hour = inb(0x71);
- printf("Time: %x:%x:%x\n", hour, min, sec);
+ // BCD to binary conversion
+ sec = (sec & 0x0F) + ((sec / 16) * 10);
+ min = (min & 0x0F) + ((min / 16) * 10);
+ hour = ((hour & 0x0F) + (((hour & 0x70) / 16) * 10)) | (hour & 0x80);
+ printf("Time: %02d:%02d:%02d UTC+3\n", (hour + 3) % 24, min, sec);
+
+ uint32_t first = get_used_memsize();
+ uint32_t limit = 1024 * 8;
+ uint32_t* pages[limit];
+
+ for(uint32_t i = 0; i < limit; i++) {
+ pages[i] = get_page();
+ }
+ uint32_t middle = get_used_memsize();
+
+ for(uint32_t i = 0; i < limit; i++) {
+ set_page_free(pages[i]);
+ }
+ uint32_t last = get_used_memsize();
+
+ printf("Before Allocation: %d KiB\nAfter allocation: %d KiB\nAfter Clear: %d KiB\n", first, middle, last);
+ printf("Finished!\n");
unsigned char key;
for(;;) {
diff --git a/kernel/rockos/paging.c b/kernel/rockos/paging.c
index ae47352..b0f3f67 100644
--- a/kernel/rockos/paging.c
+++ b/kernel/rockos/paging.c
@@ -18,24 +18,80 @@ void enable_paging() {
);
}
+static uint32_t page_dir[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
+static uint32_t first_page_table[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
+
void paging_init() {
- uint32_t page_dir[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
for(int i = 0; i < PAGE_ENTRIES; i++) {
// Supervisor: only kernel-mode can access
// Write Enabled: Can be both read and written to
// Not Present: Page table not present
page_dir[i] = 0x00000002;
}
-
- uint32_t first_page_table[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
+
for(unsigned int i = 0; i < PAGE_ENTRIES; i++) {
// As the address is page aligned, it will leave 12 bits zeroed,
// which are used by the attributes.
- first_page_table[i] = (i * 0x1000) | 3; // attr: supervisor, r/w, present
+ first_page_table[i] = (i * 0x1000) | 0x103; // attr: supervisor, r/w, present, 9th bit set
}
page_dir[0] = ((unsigned int)first_page_table) | 3; //attr: supervisor, r/w, present
load_page_dir(page_dir);
enable_paging();
+}
+
+uint32_t* get_page() {
+ // Search directories for tables
+ for (int i = 0; i < PAGE_ENTRIES; ++i) {
+ // If table is found (if 2nd and 1st bit are set)
+ if((page_dir[i] & 0x3) == 0x3) {
+ // Cast table location
+ uint32_t *mytable = (uint32_t*)((page_dir[i] >> 12) << 12);
+ // Search table for pages
+ for(int j = 0; j < PAGE_ENTRIES; ++j) {
+ // If page is found (9th, 2nd, 1st bit set)
+ if((mytable[j] & 0x103) == 0x103) {
+ mytable[j] &= ~0x100; // Unset 9th bit
+ return &mytable[j];
+ }
+ } // No page found till last entry
+ // Check if next table is not initialized
+ if((page_dir[i+1] & 0x3) != 0x3) {
+ // The last page of previous table points to the next table
+ uint32_t *newtable = &mytable[2*PAGE_ENTRIES];
+ for(int k = 0; k < PAGE_ENTRIES; ++k) {
+ newtable[k] = (k * 0x1000) | 0x103; // attr: supervisor, r/w, present, 9th bit set
+ }
+ page_dir[i+1] = ((unsigned int)newtable) | 3; //attr: supervisor, r/w, present
+ }
+ }
+ }
+ return 0;
+}
+
+void set_page_free(uint32_t* addr) {
+ // Set 9th, 2nd and 1st bits
+ *(addr) |= 0x103;
+}
+
+uint32_t get_used_memsize() {
+ uint32_t used = 0;
+ // Iterate over page_dirs
+ for(int i = 0; i < PAGE_ENTRIES; ++i) {
+ // If a table is available
+ if((page_dir[i] & 3) == 3) {
+ // Cast the table
+ uint32_t* table = ((page_dir[i] >> 12) << 12);
+ // Iterate over table
+ for(int j = 0; j < PAGE_ENTRIES; ++j) {
+ // If a page is unavailable
+ if((table[j] & 0x103) != 0x103) {
+ // Then it is used
+ used += 4*4;
+ }
+ }
+ }
+ }
+ return used;
}
\ No newline at end of file