Full Code of MaaSTaaR/539kernel for AI

master 82f8164194ce cached
93 files
103.0 KB
40.9k tokens
126 symbols
1 requests
Download .txt
Repository: MaaSTaaR/539kernel
Branch: master
Commit: 82f8164194ce
Files: 93
Total size: 103.0 KB

Directory structure:
gitextract_ir_g73hk/

├── README.md
├── evolution_by_versions/
│   ├── .gitignore
│   ├── 01_539kernel_bootloader/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   └── simple_kernel.asm
│   ├── 03_539kernel_progenitor/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   └── starter.asm
│   ├── 04_539kernel_version_t/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   ├── process.c
│   │   ├── process.h
│   │   ├── scheduler.c
│   │   ├── scheduler.h
│   │   ├── screen.c
│   │   ├── screen.h
│   │   └── starter.asm
│   ├── 05_539kernel_version_g/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── heap.c
│   │   ├── heap.h
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   ├── paging.c
│   │   ├── paging.h
│   │   ├── process.c
│   │   ├── process.h
│   │   ├── scheduler.c
│   │   ├── scheduler.h
│   │   ├── screen.c
│   │   ├── screen.h
│   │   └── starter.asm
│   └── 06_539kernel_version_ne/
│       ├── Makefile
│       ├── ata.c
│       ├── ata.h
│       ├── bochs
│       ├── bootstrap.asm
│       ├── filesystem.c
│       ├── filesystem.h
│       ├── gdt.asm
│       ├── heap.c
│       ├── heap.h
│       ├── idt.asm
│       ├── linker.ld
│       ├── main.c
│       ├── paging.c
│       ├── paging.h
│       ├── process.c
│       ├── process.h
│       ├── scheduler.c
│       ├── scheduler.h
│       ├── screen.c
│       ├── screen.h
│       ├── starter.asm
│       ├── str.c
│       └── str.h
└── src/
    ├── .gitignore
    ├── Makefile
    ├── README
    ├── ata.c
    ├── ata.h
    ├── bochs
    ├── bootstrap.asm
    ├── filesystem.c
    ├── filesystem.h
    ├── gdt.asm
    ├── heap.c
    ├── heap.h
    ├── idt.asm
    ├── linker.ld
    ├── main.c
    ├── paging.c
    ├── paging.h
    ├── process.c
    ├── process.h
    ├── scheduler.c
    ├── scheduler.h
    ├── screen.c
    ├── screen.h
    ├── simple_kernel.asm
    ├── starter.asm
    ├── str.c
    └── str.h

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
539kernel is a simple x86 32bit educational kernel which has been written especially for the book "**[A Journey in Creating an Operating System Kernel](https://539kernel.com)**" which is available freely on <https://539kernel.com>.

* `src/` contains the last version of 539kernel. 
* `evolution_by_versions/` contains the version of 539kernel while it's under development through the different chapters in the book.


================================================
FILE: evolution_by_versions/.gitignore
================================================

# Created by https://www.gitignore.io/api/c
# Edit at https://www.gitignore.io/?templates=c

### C ###
# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf
*.bin

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

# End of https://www.gitignore.io/api/c

*.img


================================================
FILE: evolution_by_versions/01_539kernel_bootloader/Makefile
================================================
ASM = nasm
BOOTSTRAP_FILE = bootstrap.asm 
KERNEL_FILE = simple_kernel.asm

build: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f bin $(KERNEL_FILE) -o kernel.o
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=kernel.o of=kernel.img bs=512
	qemu-system-x86_64 -s kernel.img

clean:
	rm -f *.o


================================================
FILE: evolution_by_versions/01_539kernel_bootloader/bootstrap.asm
================================================
start:
	mov ax, 07C0h
	mov ds, ax
	
	mov si, title_string
	call print_string
	
	mov si, message_string
	call print_string
	
	call load_kernel_from_disk
	jmp 0900h:0000
	
load_kernel_from_disk:
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h
	mov al, 01h
	mov ch, 0h
	mov cl, 02h
	mov dh, 0h
	mov dl, 80h
	mov bx, 0h
	int 13h
	
	jc kernel_load_error

    ret
    
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	jmp $
	
print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h
	
	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; Reading current cursor position
    mov ah, 03h
	mov bh, 0
	int 10h
	
    ; Move the cursor to the beginning
	mov ah, 02h
	mov dl, 0
	int 10h

	ret

title_string        db  'The Bootloader of 539kernel.', 0
message_string      db  'The kernel is loading...', 0
load_error_string   db  'The kernel cannot be loaded', 0

times 510-($-$$) db 0

dw 0xAA55


================================================
FILE: evolution_by_versions/01_539kernel_bootloader/simple_kernel.asm
================================================
start:
	mov ax, cs
	mov ds, ax

	; --- ;
	
	mov si, hello_string
	call print_string
	
	jmp $

print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je done
	
	int 10h
	
	jmp print_char

done:
	ret
	
hello_string db 'Hello World!, From Simple Assembly 539kernel!', 0


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/Makefile
================================================
ASM = nasm
CC = gcc
BOOTSTRAP_FILE = bootstrap.asm 
INIT_KERNEL_FILES = starter.asm
KERNEL_FILES = main.c
KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie
KERNEL_OBJECT = -o kernel.elf

build: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=5
	dd seek=6 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046
	qemu-system-x86_64 -s kernel.img


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/bootstrap.asm
================================================
start:
	mov ax, 07C0h
	mov ds, ax
	
	mov si, title_string
	call print_string
	
	mov si, message_string
	call print_string
	
	call load_kernel_from_disk
	jmp 0900h:0000
	
load_kernel_from_disk:
	mov ax, [curr_sector_to_load]
	sub ax, 2
	mov bx, 512d
	mul bx
	mov bx, ax
	
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h
	mov al, 1h
	mov ch, 0h
	mov cl, [curr_sector_to_load]
	mov dh, 0h
	mov dl, 80h
	int 13h
		
	jc kernel_load_error
	
	sub byte [number_of_sectors_to_load], 1
	add byte [curr_sector_to_load], 1
	cmp byte [number_of_sectors_to_load], 0
	
	jne load_kernel_from_disk
	
	ret
    
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	jmp $
	
print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h
	
	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; Reading current cursor position
    mov ah, 03h
	mov bh, 0
	int 10h
	
    ; Move the cursor to the beginning
	mov ah, 02h
	mov dl, 0
	int 10h

	ret

title_string        db  'The Bootloader of 539kernel.', 0
message_string      db  'The kernel is loading...', 0
load_error_string   db  'The kernel cannot be loaded', 0
number_of_sectors_to_load 	db 	10d
curr_sector_to_load 		db 	2d

times 510-($-$$) db 0

dw 0xAA55


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/gdt.asm
================================================
gdt:
	null_descriptor				: 	dw 0, 0, 0, 0
	kernel_code_descriptor		: 	dw 0xffff, 0x0000, 0x9a00, 0x00cf
	kernel_data_descriptor		: 	dw 0xffff, 0x0000, 0x9200, 0x00cf
	userspace_code_descriptor	: 	dw 0xffff, 0x0000, 0xfa00, 0x00cf
	userspace_data_descriptor	: 	dw 0xffff, 0x0000, 0xf200, 0x00cf

gdtr:
	gdt_size_in_bytes	: 	dw ( 5 * 8 )
	gdt_base_address	: 	dd gdt



================================================
FILE: evolution_by_versions/03_539kernel_progenitor/idt.asm
================================================
isr_0:
	cli
	push 0
	jmp isr_basic

isr_1:
	cli
	push 1
	jmp isr_basic
	
isr_2:
	cli
	push 2
	jmp isr_basic
	
isr_3:
	cli
	push 3
	jmp isr_basic
	
isr_4:
	cli
	push 4
	jmp isr_basic
	
isr_5:
	cli
	push 5
	jmp isr_basic
	
isr_6:
	cli
	push 6
	jmp isr_basic
	
isr_7:
	cli
	push 7
	jmp isr_basic
	
isr_8:
	cli
	push 8
	jmp isr_basic
	
isr_9:
	cli
	push 9
	jmp isr_basic
	
isr_10:
	cli
	push 10
	jmp isr_basic
	
isr_11:
	cli
	push 11
	jmp isr_basic
	
isr_12:
	cli
	push 12
	jmp isr_basic
	
isr_13:
	cli
	push 13
	jmp isr_basic
	
isr_14:
	cli
	push 14
	jmp isr_basic
	
isr_15:
	cli
	push 15
	jmp isr_basic
	
isr_16:
	cli
	push 16
	jmp isr_basic
	
isr_17:
	cli
	push 17
	jmp isr_basic
	
isr_18:
	cli
	push 18
	jmp isr_basic
	
isr_19:
	cli
	push 19
	jmp isr_basic
	
isr_20:
	cli
	push 20
	jmp isr_basic
	
isr_21:
	cli
	push 21
	jmp isr_basic

isr_22:
	cli
	push 22
	jmp isr_basic
	
isr_23:
	cli
	push 23
	jmp isr_basic
	
isr_24:
	cli
	push 24
	jmp isr_basic
	
isr_25:
	cli
	push 25
	jmp isr_basic
	
isr_26:
	cli
	push 26
	jmp isr_basic
	
isr_27:
	cli
	push 27
	jmp isr_basic
	
isr_28:
	cli
	push 28
	jmp isr_basic
	
isr_29:
	cli
	push 29
	jmp isr_basic
	
isr_30:
	cli
	push 30
	jmp isr_basic
	
isr_31:
	cli
	push 31
	jmp isr_basic
	
isr_32:
	cli
	push 32
	jmp irq_basic
	
isr_33:
	cli
	push 33
	jmp irq_basic
	
isr_34:
	cli
	push 34
	jmp irq_basic
	
isr_35:
	cli
	push 35
	jmp irq_basic
	
isr_36:
	cli
	push 36
	jmp irq_basic
	
isr_37:
	cli
	push 37
	jmp irq_basic

isr_38:
	cli
	push 38
	jmp irq_basic

isr_39:
	cli
	push 39
	jmp irq_basic

isr_40:
	cli
	push 40
	jmp irq_basic

isr_41:
	cli
	push 41
	jmp irq_basic

isr_42:
	cli
	push 42
	jmp irq_basic

isr_43:
	cli
	push 43
	jmp irq_basic

isr_44:
	cli
	push 44
	jmp irq_basic

isr_45:
	cli
	push 45
	jmp irq_basic

isr_46:
	cli
	push 46
	jmp irq_basic

isr_47:
	cli
	push 47
	jmp irq_basic
	
isr_48:
	cli
	push 48
	jmp irq_basic
	
isr_basic:
	call interrupt_handler
	
	pop eax
    
    sti
	iret
	
irq_basic:
	call interrupt_handler
	
	mov al, 0x20
	out 0x20, al
	
	cmp byte [esp], 40d
	jnge irq_basic_end
	
	mov al, 0xa0
	out 0x20, al
	
	irq_basic_end:
		pop eax
        
        sti
		iret
		
idt:
	dw isr_0, 8, 0x8e00, 0x0000
	dw isr_1, 8, 0x8e00, 0x0000
	dw isr_2, 8, 0x8e00, 0x0000
	dw isr_3, 8, 0x8e00, 0x0000
	dw isr_4, 8, 0x8e00, 0x0000
	dw isr_5, 8, 0x8e00, 0x0000
	dw isr_6, 8, 0x8e00, 0x0000
	dw isr_7, 8, 0x8e00, 0x0000
	dw isr_8, 8, 0x8e00, 0x0000
	dw isr_9, 8, 0x8e00, 0x0000
	dw isr_10, 8, 0x8e00, 0x0000
	dw isr_11, 8, 0x8e00, 0x0000
	dw isr_12, 8, 0x8e00, 0x0000
	dw isr_13, 8, 0x8e00, 0x0000
	dw isr_14, 8, 0x8e00, 0x0000
	dw isr_15, 8, 0x8e00, 0x0000
	dw isr_16, 8, 0x8e00, 0x0000
	dw isr_17, 8, 0x8e00, 0x0000
	dw isr_18, 8, 0x8e00, 0x0000
	dw isr_19, 8, 0x8e00, 0x0000
	dw isr_20, 8, 0x8e00, 0x0000
	dw isr_21, 8, 0x8e00, 0x0000
	dw isr_22, 8, 0x8e00, 0x0000
	dw isr_23, 8, 0x8e00, 0x0000
	dw isr_24, 8, 0x8e00, 0x0000
	dw isr_25, 8, 0x8e00, 0x0000
	dw isr_26, 8, 0x8e00, 0x0000
	dw isr_27, 8, 0x8e00, 0x0000
	dw isr_28, 8, 0x8e00, 0x0000
	dw isr_29, 8, 0x8e00, 0x0000
	dw isr_30, 8, 0x8e00, 0x0000
	dw isr_31, 8, 0x8e00, 0x0000
	dw isr_32, 8, 0x8e00, 0x0000
	dw isr_33, 8, 0x8e00, 0x0000
	dw isr_34, 8, 0x8e00, 0x0000
	dw isr_35, 8, 0x8e00, 0x0000
	dw isr_36, 8, 0x8e00, 0x0000
	dw isr_37, 8, 0x8e00, 0x0000
	dw isr_38, 8, 0x8e00, 0x0000
	dw isr_39, 8, 0x8e00, 0x0000
	dw isr_40, 8, 0x8e00, 0x0000
	dw isr_41, 8, 0x8e00, 0x0000
	dw isr_42, 8, 0x8e00, 0x0000
	dw isr_43, 8, 0x8e00, 0x0000
	dw isr_44, 8, 0x8e00, 0x0000
	dw isr_45, 8, 0x8e00, 0x0000
	dw isr_46, 8, 0x8e00, 0x0000
	dw isr_47, 8, 0x8e00, 0x0000
	dw isr_48, 8, 0x8e00, 0x0000
	
idtr:
	idt_size_in_bytes	: 	dw idtr - idt
	idt_base_address	: 	dd idt


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/linker.ld
================================================
/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */

SECTIONS
{
  .text 0x09000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
  }

  end = .; _end = .; __end = .;
} 


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/main.c
================================================
volatile unsigned char *video = 0xB8000;

int nextTextPos = 0;
int currLine = 0;

void print( char * );
void println();
void printi( int );

void kernel_main()
{
	print( "Welcome to 539kernel!" );
	println();
	print( "We are now in Protected-mode" );
	println();
	printi( 539 );
	println();
	
	while( 1 );
}

void interrupt_handler( int interrupt_number )
{
	println();
	print( "Interrupt Received " );
	printi( interrupt_number );
}

void print( char *str )
{
	int currCharLocationInVidMem, currColorLocationInVidMem;
	
	while ( *str != '\0' )
	{
        currCharLocationInVidMem = nextTextPos * 2;
		currColorLocationInVidMem = currCharLocationInVidMem + 1;
		
		video[ currCharLocationInVidMem ] = *str;
		video[ currColorLocationInVidMem ] = 15;
		
		nextTextPos++;
		
		str++;
	}
}

void println()
{
	nextTextPos = ++currLine * 80;
}

void printi( int number )
{
	char* digitToStr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
	
	if ( number >= 0 && number <= 9 )
	{
		print( digitToStr[ number ] );
		return;
	}
	else
	{
		int remaining = number % 10;
		number = number / 10;
		
		printi( number );
		printi( remaining );
	}
}


================================================
FILE: evolution_by_versions/03_539kernel_progenitor/starter.asm
================================================
bits 16
extern kernel_main
extern interrupt_handler

start:
	mov ax, cs
	mov ds, ax
		
	call load_gdt
	call init_video_mode
	call enter_protected_mode
    call setup_interrupts
	
	call 08h:start_kernel
	
load_gdt:
	cli
	lgdt [gdtr - start]
	
	ret
	
enter_protected_mode:
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	ret
	
init_video_mode:
	mov ah, 0h
	mov al, 03h
	int 10h
	
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	ret
	
setup_interrupts:
	call remap_pic
	call load_idt
	
	ret
	
remap_pic:
	mov al, 11h
	
	send_init_cmd_to_pic_master: 	
		out 0x20, al
		
	send_init_cmd_to_pic_slave: 	
		out 0xa0, al
		
	; ... ;
	
	make_irq_starts_from_intr_32_in_pic_master:		
		mov al, 32d
		out 0x21, al
	
	make_irq_starts_from_intr_40_in_pic_slave:
		mov al, 40d
		out 0xa1, al 
	
	; ... ;
	
	tell_pic_master_where_pic_slave_is_connected:
		mov al, 04h
		out 0x21, al
	
	tell_pic_slave_where_pic_master_is_connected:
		mov al, 02h
		out 0xa1, al
	
	; ... ;
	
	mov al, 01h
	
	tell_pic_master_the_arch_is_x86:
		out 0x21, al
	
	tell_pic_slave_the_arch_is_x86:
		out 0xa1, al
	
	; ... ;
	
	mov al, 0h
	
	make_pic_master_enables_all_irqs:
		out 0x21, al
	
	make_pic_slave_enables_all_irqs:
		out 0xa1, al
	
	; ... ;
	
	ret
	
load_idt:
	lidt [idtr - start]
	ret
	
bits 32
start_kernel:
	mov eax, 10h
	mov ds, eax
	mov ss, eax
    
	mov eax, 0h
	mov es, eax
	mov fs, eax
	mov gs, eax
	
	sti
	
	call kernel_main
	
%include "gdt.asm"
%include "idt.asm"


================================================
FILE: evolution_by_versions/04_539kernel_version_t/Makefile
================================================
ASM = nasm
CC = gcc
BOOTSTRAP_FILE = bootstrap.asm 
INIT_KERNEL_FILES = starter.asm
KERNEL_FILES = main.c
KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie
KERNEL_OBJECT = -o kernel.elf

build: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf
	$(CC) $(KERNEL_FLAGS) process.c -o process.elf
	$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=8
	dd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046
	qemu-system-x86_64 -s kernel.img


================================================
FILE: evolution_by_versions/04_539kernel_version_t/bootstrap.asm
================================================
start:
	mov ax, 07C0h
	mov ds, ax
	
	mov si, title_string
	call print_string
	
	mov si, message_string
	call print_string
	
	call load_kernel_from_disk
	jmp 0900h:0000
	
load_kernel_from_disk:
	mov ax, [curr_sector_to_load]
	sub ax, 2
	mov bx, 512d
	mul bx
	mov bx, ax
	
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h
	mov al, 1h
	mov ch, 0h
	mov cl, [curr_sector_to_load]
	mov dh, 0h
	mov dl, 80h
	int 13h
		
	jc kernel_load_error
	
	sub byte [number_of_sectors_to_load], 1
	add byte [curr_sector_to_load], 1
	cmp byte [number_of_sectors_to_load], 0
	
	jne load_kernel_from_disk
	
	ret
    
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	jmp $
	
print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h
	
	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; Reading current cursor position
    mov ah, 03h
	mov bh, 0
	int 10h
	
    ; Move the cursor to the beginning
	mov ah, 02h
	mov dl, 0
	int 10h

	ret

title_string        db  'The Bootloader of 539kernel.', 0
message_string      db  'The kernel is loading...', 0
load_error_string   db  'The kernel cannot be loaded', 0
number_of_sectors_to_load 	db 	10d
curr_sector_to_load 		db 	2d

times 510-($-$$) db 0

dw 0xAA55


================================================
FILE: evolution_by_versions/04_539kernel_version_t/gdt.asm
================================================
gdt:
	null_descriptor				: 	dw 0, 0, 0, 0
	kernel_code_descriptor		: 	dw 0xffff, 0x0000, 0x9a00, 0x00cf
	kernel_data_descriptor		: 	dw 0xffff, 0x0000, 0x9200, 0x00cf
	userspace_code_descriptor	: 	dw 0xffff, 0x0000, 0xfa00, 0x00cf
	userspace_data_descriptor	: 	dw 0xffff, 0x0000, 0xf200, 0x00cf
	tss_descriptor				: 	dw tss + 3, tss, 0x8900, 0x0000

gdtr:
	gdt_size_in_bytes	: 	dw ( 6 * 8 )
	gdt_base_address	: 	dd gdt



================================================
FILE: evolution_by_versions/04_539kernel_version_t/idt.asm
================================================
isr_0:
	cli
	push 0
	jmp isr_basic

isr_1:
	cli
	push 1
	jmp isr_basic
	
isr_2:
	cli
	push 2
	jmp isr_basic
	
isr_3:
	cli
	push 3
	jmp isr_basic
	
isr_4:
	cli
	push 4
	jmp isr_basic
	
isr_5:
	cli
	push 5
	jmp isr_basic
	
isr_6:
	cli
	push 6
	jmp isr_basic
	
isr_7:
	cli
	push 7
	jmp isr_basic
	
isr_8:
	cli
	push 8
	jmp isr_basic
	
isr_9:
	cli
	push 9
	jmp isr_basic
	
isr_10:
	cli
	push 10
	jmp isr_basic
	
isr_11:
	cli
	push 11
	jmp isr_basic
	
isr_12:
	cli
	push 12
	jmp isr_basic
	
isr_13:
	cli
	push 13
	jmp isr_basic
	
isr_14:
	cli
	push 14
	jmp isr_basic
	
isr_15:
	cli
	push 15
	jmp isr_basic
	
isr_16:
	cli
	push 16
	jmp isr_basic
	
isr_17:
	cli
	push 17
	jmp isr_basic
	
isr_18:
	cli
	push 18
	jmp isr_basic
	
isr_19:
	cli
	push 19
	jmp isr_basic
	
isr_20:
	cli
	push 20
	jmp isr_basic
	
isr_21:
	cli
	push 21
	jmp isr_basic

isr_22:
	cli
	push 22
	jmp isr_basic
	
isr_23:
	cli
	push 23
	jmp isr_basic
	
isr_24:
	cli
	push 24
	jmp isr_basic
	
isr_25:
	cli
	push 25
	jmp isr_basic
	
isr_26:
	cli
	push 26
	jmp isr_basic
	
isr_27:
	cli
	push 27
	jmp isr_basic
	
isr_28:
	cli
	push 28
	jmp isr_basic
	
isr_29:
	cli
	push 29
	jmp isr_basic
	
isr_30:
	cli
	push 30
	jmp isr_basic
	
isr_31:
	cli
	push 31
	jmp isr_basic
	
isr_32:
    ; Part 1
    
    cli ; Step 1
    
    pusha ; Step 2
    
    ; Step 3
    mov eax, [esp + 32]
    push eax  
    
    call scheduler ; Step 4
    
    ; ... ;
    
    ; Part 2
    
    ; Step 5
    mov al, 0x20
    out 0x20, al
    
    ; Step 6
    add esp, 40d
    push run_next_process
    
    iret ; Step 7
	
isr_33:
	cli
	push 33
	jmp irq_basic
	
isr_34:
	cli
	push 34
	jmp irq_basic
	
isr_35:
	cli
	push 35
	jmp irq_basic
	
isr_36:
	cli
	push 36
	jmp irq_basic
	
isr_37:
	cli
	push 37
	jmp irq_basic

isr_38:
	cli
	push 38
	jmp irq_basic

isr_39:
	cli
	push 39
	jmp irq_basic

isr_40:
	cli
	push 40
	jmp irq_basic

isr_41:
	cli
	push 41
	jmp irq_basic

isr_42:
	cli
	push 42
	jmp irq_basic

isr_43:
	cli
	push 43
	jmp irq_basic

isr_44:
	cli
	push 44
	jmp irq_basic

isr_45:
	cli
	push 45
	jmp irq_basic

isr_46:
	cli
	push 46
	jmp irq_basic

isr_47:
	cli
	push 47
	jmp irq_basic
	
isr_48:
	cli
	push 48
	jmp irq_basic
	
isr_basic:
	call interrupt_handler
	
	pop eax
    
    sti
	iret
	
irq_basic:
	call interrupt_handler
	
	mov al, 0x20
	out 0x20, al
	
	cmp byte [esp], 40d
	jnge irq_basic_end
	
	mov al, 0xa0
	out 0x20, al
	
	irq_basic_end:
		pop eax
        
        sti
		iret
		
idt:
	dw isr_0, 8, 0x8e00, 0x0000
	dw isr_1, 8, 0x8e00, 0x0000
	dw isr_2, 8, 0x8e00, 0x0000
	dw isr_3, 8, 0x8e00, 0x0000
	dw isr_4, 8, 0x8e00, 0x0000
	dw isr_5, 8, 0x8e00, 0x0000
	dw isr_6, 8, 0x8e00, 0x0000
	dw isr_7, 8, 0x8e00, 0x0000
	dw isr_8, 8, 0x8e00, 0x0000
	dw isr_9, 8, 0x8e00, 0x0000
	dw isr_10, 8, 0x8e00, 0x0000
	dw isr_11, 8, 0x8e00, 0x0000
	dw isr_12, 8, 0x8e00, 0x0000
	dw isr_13, 8, 0x8e00, 0x0000
	dw isr_14, 8, 0x8e00, 0x0000
	dw isr_15, 8, 0x8e00, 0x0000
	dw isr_16, 8, 0x8e00, 0x0000
	dw isr_17, 8, 0x8e00, 0x0000
	dw isr_18, 8, 0x8e00, 0x0000
	dw isr_19, 8, 0x8e00, 0x0000
	dw isr_20, 8, 0x8e00, 0x0000
	dw isr_21, 8, 0x8e00, 0x0000
	dw isr_22, 8, 0x8e00, 0x0000
	dw isr_23, 8, 0x8e00, 0x0000
	dw isr_24, 8, 0x8e00, 0x0000
	dw isr_25, 8, 0x8e00, 0x0000
	dw isr_26, 8, 0x8e00, 0x0000
	dw isr_27, 8, 0x8e00, 0x0000
	dw isr_28, 8, 0x8e00, 0x0000
	dw isr_29, 8, 0x8e00, 0x0000
	dw isr_30, 8, 0x8e00, 0x0000
	dw isr_31, 8, 0x8e00, 0x0000
	dw isr_32, 8, 0x8e00, 0x0000
	dw isr_33, 8, 0x8e00, 0x0000
	dw isr_34, 8, 0x8e00, 0x0000
	dw isr_35, 8, 0x8e00, 0x0000
	dw isr_36, 8, 0x8e00, 0x0000
	dw isr_37, 8, 0x8e00, 0x0000
	dw isr_38, 8, 0x8e00, 0x0000
	dw isr_39, 8, 0x8e00, 0x0000
	dw isr_40, 8, 0x8e00, 0x0000
	dw isr_41, 8, 0x8e00, 0x0000
	dw isr_42, 8, 0x8e00, 0x0000
	dw isr_43, 8, 0x8e00, 0x0000
	dw isr_44, 8, 0x8e00, 0x0000
	dw isr_45, 8, 0x8e00, 0x0000
	dw isr_46, 8, 0x8e00, 0x0000
	dw isr_47, 8, 0x8e00, 0x0000
	dw isr_48, 8, 0x8e00, 0x0000
	
idtr:
	idt_size_in_bytes	: 	dw idtr - idt
	idt_base_address	: 	dd idt


================================================
FILE: evolution_by_versions/04_539kernel_version_t/linker.ld
================================================
/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */

SECTIONS
{
  .text 0x09000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
  }

  end = .; _end = .; __end = .;
} 


================================================
FILE: evolution_by_versions/04_539kernel_version_t/main.c
================================================
#include "screen.h"
#include "scheduler.h"

void processA();
void processB();
void processC();
void processD();

void kernel_main()
{
	process_t p1, p2, p3, p4;
	
	screen_init();
	process_init();
	scheduler_init();
	
	print( "Welcome to 539kernel!" );
	println();
	print( "We are now in Protected-mode" );
	println();
	printi( 539 );
	println();
	
    process_create( &processA, &p1 );
    process_create( &processB, &p2 );
    process_create( &processC, &p3 );
    process_create( &processD, &p4 );
	
	while( 1 );
}

void interrupt_handler( int interrupt_number )
{
	println();
	print( "Interrupt Received " );
	printi( interrupt_number );
}

void processA()
{
    print( "Process A," );

    while ( 1 )
        asm( "mov $5390, %eax" );
}

void processB()
{
    print( "Process B," );

    while ( 1 )
        asm( "mov $5391, %eax" );
}

void processC()
{
    print( "Process C," );

    while ( 1 )
        asm( "mov $5392, %eax" );
}

void processD()
{
    print( "Process D," );

    while ( 1 )
        asm( "mov $5393, %eax" );
}


================================================
FILE: evolution_by_versions/04_539kernel_version_t/process.c
================================================
#include "process.h"

void process_init()
{
    processes_count = 0;
    curr_pid = 0;
}

void process_create( int *base_address, process_t *process )
{   
    process->pid = curr_pid++;
    
    process->context.eax = 0;
    process->context.ecx = 0;
    process->context.edx = 0;
    process->context.ebx = 0;
    process->context.esp = 0;
    process->context.ebp = 0;
    process->context.esi = 0;
    process->context.edi = 0;
    process->context.eip = base_address;
    
    process->state = READY;
    process->base_address = base_address;
    
    processes[ process->pid ] = process;
    
    processes_count++;
}


================================================
FILE: evolution_by_versions/04_539kernel_version_t/process.h
================================================
typedef enum process_state { READY, RUNNING } process_state_t;

typedef struct process_context
{
    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;
} process_context_t;

typedef struct process
{
    int pid;
    process_context_t context;
    process_state_t state;
    int *base_address;
} process_t;

process_t *processes[ 15 ];

int processes_count, curr_pid;

void process_init();
void process_create( int *, process_t * );


================================================
FILE: evolution_by_versions/04_539kernel_version_t/scheduler.c
================================================
#include "scheduler.h"

void scheduler_init()
{
    next_sch_pid = 0;
    curr_sch_pid = 0;
}

process_t *get_next_process()
{
    process_t *next_process = processes[ next_sch_pid ];
    
    curr_sch_pid = next_sch_pid;
    next_sch_pid++;
    next_sch_pid = next_sch_pid % processes_count;
    
    return next_process;
}

void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )
{
    process_t *curr_process;
    
    print( " EAX = " ); // For Testing Purpose
    printi( eax ); // For Testing Purpose
    
    // ... //
    
    // PART 1
    
    curr_process = processes[ curr_sch_pid ];
    next_process = get_next_process();
    
    // ... //
    
    // PART 2

    if ( curr_process->state == RUNNING )
    {
        curr_process->context.eax = eax;
        curr_process->context.ecx = ecx;
        curr_process->context.edx = edx;
        curr_process->context.ebx = ebx;
        curr_process->context.esp = esp;
        curr_process->context.ebp = ebp;
        curr_process->context.esi = esi;
        curr_process->context.edi = edi;
        curr_process->context.eip = eip;
    }
    
    curr_process->state = READY;
    
    // ... //
    
    // PART 3
    
    asm( "  mov %0, %%eax;  \
            mov %0, %%ecx;  \
            mov %0, %%edx;  \
            mov %0, %%ebx;  \
            mov %0, %%esi;  \
            mov %0, %%edi;" 
            : : "r" ( next_process->context.eax ), "r" ( next_process->context.ecx ), "r" ( next_process->context.edx ), "r" ( next_process->context.ebx ),
                "r" ( next_process->context.esi ), "r" ( next_process->context.edi ) );
    
    next_process->state = RUNNING;
}

void run_next_process()
{
    asm( "  sti;            \
            jmp *%0" : : "r" ( next_process->context.eip ) );
}


================================================
FILE: evolution_by_versions/04_539kernel_version_t/scheduler.h
================================================
#include "process.h"

int next_sch_pid, curr_sch_pid;

process_t *next_process;

void scheduler_init();
process_t *get_next_process();
void scheduler( int, int, int, int, int, int, int, int, int );
void run_next_process();


================================================
FILE: evolution_by_versions/04_539kernel_version_t/screen.c
================================================
#include "screen.h"

void screen_init()
{
    video = 0xB8000;
    nextTextPos = 0;
    currLine = 0;
}

void print( char *str )
{
	int currCharLocationInVidMem, currColorLocationInVidMem;
	
	while ( *str != '\0' )
	{
        currCharLocationInVidMem = nextTextPos * 2;
		currColorLocationInVidMem = currCharLocationInVidMem + 1;
		
		video[ currCharLocationInVidMem ] = *str;
		video[ currColorLocationInVidMem ] = 15;
		
		nextTextPos++;
		
		str++;
	}
}

void println()
{
	nextTextPos = ++currLine * 80;
}

void printi( int number )
{
	char* digitToStr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
	
	if ( number >= 0 && number <= 9 )
	{
		print( digitToStr[ number ] );
		return;
	}
	else
	{
		int remaining = number % 10;
		number = number / 10;
		
		printi( number );
		printi( remaining );
	}
}


================================================
FILE: evolution_by_versions/04_539kernel_version_t/screen.h
================================================
volatile unsigned char *video;

int nextTextPos;
int currLine;

void screen_init();
void print( char * );
void println();
void printi( int );


================================================
FILE: evolution_by_versions/04_539kernel_version_t/starter.asm
================================================
bits 16
extern kernel_main
extern interrupt_handler
extern scheduler
extern run_next_process

start:
	mov ax, cs
	mov ds, ax
		
	call load_gdt
	call init_video_mode
	call enter_protected_mode
    call setup_interrupts
    call load_task_register
	
	call 08h:start_kernel
	
load_gdt:
	cli
	lgdt [gdtr - start]
	
	ret
	
enter_protected_mode:
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	ret
	
init_video_mode:
	mov ah, 0h
	mov al, 03h
	int 10h
	
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	ret
	
setup_interrupts:
	call remap_pic
	call load_idt
	
	ret
	
remap_pic:
	mov al, 11h
	
	send_init_cmd_to_pic_master: 	
		out 0x20, al
		
	send_init_cmd_to_pic_slave: 	
		out 0xa0, al
		
	; ... ;
	
	make_irq_starts_from_intr_32_in_pic_master:		
		mov al, 32d
		out 0x21, al
	
	make_irq_starts_from_intr_40_in_pic_slave:
		mov al, 40d
		out 0xa1, al 
	
	; ... ;
	
	tell_pic_master_where_pic_slave_is_connected:
		mov al, 04h
		out 0x21, al
	
	tell_pic_slave_where_pic_master_is_connected:
		mov al, 02h
		out 0xa1, al
	
	; ... ;
	
	mov al, 01h
	
	tell_pic_master_the_arch_is_x86:
		out 0x21, al
	
	tell_pic_slave_the_arch_is_x86:
		out 0xa1, al
	
	; ... ;
	
	mov al, 0h
	
	make_pic_master_enables_all_irqs:
		out 0x21, al
	
	make_pic_slave_enables_all_irqs:
		out 0xa1, al
	
	; ... ;
	
	ret
	
load_idt:
	lidt [idtr - start]
	ret
	
load_task_register:
    mov ax, 40d
    ltr ax
    
    ret
	
bits 32
start_kernel:
	mov eax, 10h
	mov ds, eax
	mov ss, eax
    
	mov eax, 0h
	mov es, eax
	mov fs, eax
	mov gs, eax
	
	sti
	
	call kernel_main
	
%include "gdt.asm"
%include "idt.asm"

tss:
    dd 0


================================================
FILE: evolution_by_versions/05_539kernel_version_g/Makefile
================================================
ASM = nasm
CC = gcc
BOOTSTRAP_FILE = bootstrap.asm 
SIMPLE_KERNEL = simple_kernel.asm
INIT_KERNEL_FILES = starter.asm
KERNEL_FILES = main.c
KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie
KERNEL_OBJECT = -o kernel.elf

build: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf
	$(CC) $(KERNEL_FLAGS) process.c -o process.elf
	$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf
	$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf
	$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=8
	dd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046
	qemu-system-x86_64 -s kernel.img


================================================
FILE: evolution_by_versions/05_539kernel_version_g/bootstrap.asm
================================================
start:
	mov ax, 07C0h
	mov ds, ax
	
	mov si, title_string
	call print_string
	
	mov si, message_string
	call print_string
	
	call load_kernel_from_disk
	jmp 0900h:0000
	
load_kernel_from_disk:
	mov ax, [curr_sector_to_load]
	sub ax, 2
	mov bx, 512d
	mul bx
	mov bx, ax
	
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h
	mov al, 1h
	mov ch, 0h
	mov cl, [curr_sector_to_load]
	mov dh, 0h
	mov dl, 80h
	int 13h
		
	jc kernel_load_error
	
	sub byte [number_of_sectors_to_load], 1
	add byte [curr_sector_to_load], 1
	cmp byte [number_of_sectors_to_load], 0
	
	jne load_kernel_from_disk
	
	ret
    
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	jmp $
	
print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h
	
	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; Reading current cursor position
    mov ah, 03h
	mov bh, 0
	int 10h
	
    ; Move the cursor to the beginning
	mov ah, 02h
	mov dl, 0
	int 10h

	ret

title_string        db  'The Bootloader of 539kernel.', 0
message_string      db  'The kernel is loading...', 0
load_error_string   db  'The kernel cannot be loaded', 0
number_of_sectors_to_load 	db 	10d
curr_sector_to_load 		db 	2d

times 510-($-$$) db 0

dw 0xAA55


================================================
FILE: evolution_by_versions/05_539kernel_version_g/gdt.asm
================================================
gdt:
	null_descriptor				: 	dw 0, 0, 0, 0
	kernel_code_descriptor		: 	dw 0xffff, 0x0000, 0x9a00, 0x00cf
	kernel_data_descriptor		: 	dw 0xffff, 0x0000, 0x9200, 0x00cf
	userspace_code_descriptor	: 	dw 0xffff, 0x0000, 0xfa00, 0x00cf
	userspace_data_descriptor	: 	dw 0xffff, 0x0000, 0xf200, 0x00cf
	tss_descriptor				: 	dw tss + 3, tss, 0x8900, 0x0000

gdtr:
	gdt_size_in_bytes	: 	dw ( 6 * 8 )
	gdt_base_address	: 	dd gdt



================================================
FILE: evolution_by_versions/05_539kernel_version_g/heap.c
================================================
#include "heap.h"

void heap_init()
{
	heap_base = 0x100000;
}

int kalloc( int bytes )
{
	unsigned int new_object_address = heap_base;
	
	heap_base += bytes;
	
	return new_object_address;
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/heap.h
================================================
unsigned int heap_base;

void heap_init();
int kalloc( int );


================================================
FILE: evolution_by_versions/05_539kernel_version_g/idt.asm
================================================
isr_0:
	cli
	push 0
	jmp isr_basic

isr_1:
	cli
	push 1
	jmp isr_basic
	
isr_2:
	cli
	push 2
	jmp isr_basic
	
isr_3:
	cli
	push 3
	jmp isr_basic
	
isr_4:
	cli
	push 4
	jmp isr_basic
	
isr_5:
	cli
	push 5
	jmp isr_basic
	
isr_6:
	cli
	push 6
	jmp isr_basic
	
isr_7:
	cli
	push 7
	jmp isr_basic
	
isr_8:
	cli
	push 8
	jmp isr_basic
	
isr_9:
	cli
	push 9
	jmp isr_basic
	
isr_10:
	cli
	push 10
	jmp isr_basic
	
isr_11:
	cli
	push 11
	jmp isr_basic
	
isr_12:
	cli
	push 12
	jmp isr_basic
	
isr_13:
	cli
	push 13
	jmp isr_basic
	
isr_14:
	cli
	push 14
	jmp isr_basic
	
isr_15:
	cli
	push 15
	jmp isr_basic
	
isr_16:
	cli
	push 16
	jmp isr_basic
	
isr_17:
	cli
	push 17
	jmp isr_basic
	
isr_18:
	cli
	push 18
	jmp isr_basic
	
isr_19:
	cli
	push 19
	jmp isr_basic
	
isr_20:
	cli
	push 20
	jmp isr_basic
	
isr_21:
	cli
	push 21
	jmp isr_basic

isr_22:
	cli
	push 22
	jmp isr_basic
	
isr_23:
	cli
	push 23
	jmp isr_basic
	
isr_24:
	cli
	push 24
	jmp isr_basic
	
isr_25:
	cli
	push 25
	jmp isr_basic
	
isr_26:
	cli
	push 26
	jmp isr_basic
	
isr_27:
	cli
	push 27
	jmp isr_basic
	
isr_28:
	cli
	push 28
	jmp isr_basic
	
isr_29:
	cli
	push 29
	jmp isr_basic
	
isr_30:
	cli
	push 30
	jmp isr_basic
	
isr_31:
	cli
	push 31
	jmp isr_basic
	
isr_32:
    ; Part 1
    
    cli ; Step 1
    
    pusha ; Step 2
    
    ; Step 3
    mov eax, [esp + 32]
    push eax  
    
    call scheduler ; Step 4
    
    ; ... ;
    
    ; Part 2
    
    ; Step 5
    mov al, 0x20
    out 0x20, al
    
    ; Step 6
    add esp, 40d
    push run_next_process
    
    iret ; Step 7
	
isr_33:
	cli
	push 33
	jmp irq_basic
	
isr_34:
	cli
	push 34
	jmp irq_basic
	
isr_35:
	cli
	push 35
	jmp irq_basic
	
isr_36:
	cli
	push 36
	jmp irq_basic
	
isr_37:
	cli
	push 37
	jmp irq_basic

isr_38:
	cli
	push 38
	jmp irq_basic

isr_39:
	cli
	push 39
	jmp irq_basic

isr_40:
	cli
	push 40
	jmp irq_basic

isr_41:
	cli
	push 41
	jmp irq_basic

isr_42:
	cli
	push 42
	jmp irq_basic

isr_43:
	cli
	push 43
	jmp irq_basic

isr_44:
	cli
	push 44
	jmp irq_basic

isr_45:
	cli
	push 45
	jmp irq_basic

isr_46:
	cli
	push 46
	jmp irq_basic

isr_47:
	cli
	push 47
	jmp irq_basic
	
isr_48:
	cli
	push 48
	jmp irq_basic
	
isr_basic:
	call interrupt_handler
	
	pop eax
    
    sti
	iret
	
irq_basic:
	call interrupt_handler
	
	mov al, 0x20
	out 0x20, al
	
	cmp byte [esp], 40d
	jnge irq_basic_end
	
	mov al, 0xa0
	out 0x20, al
	
	irq_basic_end:
		pop eax
        
        sti
		iret
		
idt:
	dw isr_0, 8, 0x8e00, 0x0000
	dw isr_1, 8, 0x8e00, 0x0000
	dw isr_2, 8, 0x8e00, 0x0000
	dw isr_3, 8, 0x8e00, 0x0000
	dw isr_4, 8, 0x8e00, 0x0000
	dw isr_5, 8, 0x8e00, 0x0000
	dw isr_6, 8, 0x8e00, 0x0000
	dw isr_7, 8, 0x8e00, 0x0000
	dw isr_8, 8, 0x8e00, 0x0000
	dw isr_9, 8, 0x8e00, 0x0000
	dw isr_10, 8, 0x8e00, 0x0000
	dw isr_11, 8, 0x8e00, 0x0000
	dw isr_12, 8, 0x8e00, 0x0000
	dw isr_13, 8, 0x8e00, 0x0000
	dw isr_14, 8, 0x8e00, 0x0000
	dw isr_15, 8, 0x8e00, 0x0000
	dw isr_16, 8, 0x8e00, 0x0000
	dw isr_17, 8, 0x8e00, 0x0000
	dw isr_18, 8, 0x8e00, 0x0000
	dw isr_19, 8, 0x8e00, 0x0000
	dw isr_20, 8, 0x8e00, 0x0000
	dw isr_21, 8, 0x8e00, 0x0000
	dw isr_22, 8, 0x8e00, 0x0000
	dw isr_23, 8, 0x8e00, 0x0000
	dw isr_24, 8, 0x8e00, 0x0000
	dw isr_25, 8, 0x8e00, 0x0000
	dw isr_26, 8, 0x8e00, 0x0000
	dw isr_27, 8, 0x8e00, 0x0000
	dw isr_28, 8, 0x8e00, 0x0000
	dw isr_29, 8, 0x8e00, 0x0000
	dw isr_30, 8, 0x8e00, 0x0000
	dw isr_31, 8, 0x8e00, 0x0000
	dw isr_32, 8, 0x8e00, 0x0000
	dw isr_33, 8, 0x8e00, 0x0000
	dw isr_34, 8, 0x8e00, 0x0000
	dw isr_35, 8, 0x8e00, 0x0000
	dw isr_36, 8, 0x8e00, 0x0000
	dw isr_37, 8, 0x8e00, 0x0000
	dw isr_38, 8, 0x8e00, 0x0000
	dw isr_39, 8, 0x8e00, 0x0000
	dw isr_40, 8, 0x8e00, 0x0000
	dw isr_41, 8, 0x8e00, 0x0000
	dw isr_42, 8, 0x8e00, 0x0000
	dw isr_43, 8, 0x8e00, 0x0000
	dw isr_44, 8, 0x8e00, 0x0000
	dw isr_45, 8, 0x8e00, 0x0000
	dw isr_46, 8, 0x8e00, 0x0000
	dw isr_47, 8, 0x8e00, 0x0000
	dw isr_48, 8, 0x8e00, 0x0000
	
idtr:
	idt_size_in_bytes	: 	dw idtr - idt
	idt_base_address	: 	dd idt


================================================
FILE: evolution_by_versions/05_539kernel_version_g/linker.ld
================================================
/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */

SECTIONS
{
  .text 0x09000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
  }

  end = .; _end = .; __end = .;
} 


================================================
FILE: evolution_by_versions/05_539kernel_version_g/main.c
================================================
#include "screen.h"
#include "scheduler.h"
#include "heap.h"

void processA();
void processB();
void processC();
void processD();

void kernel_main()
{
	heap_init();
	paging_init();
	screen_init();
	process_init();
	scheduler_init();	
	
	print( "Welcome to 539kernel!" );
	println();
	print( "We are now in Protected-mode" );
	println();
	printi( 539 );
	println();
	
    process_create( &processA );
	process_create( &processB );
	process_create( &processC );
	process_create( &processD );
	
	while( 1 );
}

void interrupt_handler( int interrupt_number )
{
	println();
	print( "Interrupt Received " );
	printi( interrupt_number );
}

void processA()
{
    print( "Process A," );

    while ( 1 )
        asm( "mov $5390, %eax" );
}

void processB()
{
    print( "Process B," );

    while ( 1 )
        asm( "mov $5391, %eax" );
}

void processC()
{
    print( "Process C," );

    while ( 1 )
        asm( "mov $5392, %eax" );
}

void processD()
{
    print( "Process D," );

    while ( 1 )
        asm( "mov $5393, %eax" );
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/paging.c
================================================
#include "paging.h"

int create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )
{
	int entry = 0;
	
	entry |= present;
	entry |= writable << 1;
	entry |= privilege_level << 2;
	entry |= write_through_cache << 3;
	entry |= cache_enabled << 4;
	entry |= accessed << 5;
	entry |= dirty << 6;
	entry |= page_size << 7;
	
	return base_address | entry;
}

void paging_init()
{
    // PART 1:
    
	unsigned int curr_page_frame = 0;
	
	page_directory = kalloc( 4 * 1024 );
		
	for ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )
	{
		unsigned int *pagetable = kalloc( 4 * PTE_NUM );
		
		for ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )
			pagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );
		
		page_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );
	}
    
    // ... //
    
    // PART 2
    
	load_page_directory();
	enable_paging();
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/paging.h
================================================
#define PDE_NUM 3
#define PTE_NUM 1024

extern void load_page_directory();
extern void enable_paging();

unsigned int *page_directory;

void paging_init();
int create_page_entry( int, char, char, char, char, char, char, char, char );


================================================
FILE: evolution_by_versions/05_539kernel_version_g/process.c
================================================
#include "process.h"

void process_init()
{
    processes_count = 0;
    curr_pid = 0;
}

process_t *process_create( int *base_address )
{
	process_t *process = kalloc( sizeof( process_t ) );
	
    process->pid = curr_pid++;
    
    process->context.eax = 0;
    process->context.ecx = 0;
    process->context.edx = 0;
    process->context.ebx = 0;
    process->context.esp = 0;
    process->context.ebp = 0;
    process->context.esi = 0;
    process->context.edi = 0;
    process->context.eip = base_address;
    
    process->state = READY;
    process->base_address = base_address;
    
    processes[ process->pid ] = process;
    
    processes_count++;
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/process.h
================================================
typedef enum process_state { READY, RUNNING } process_state_t;

typedef struct process_context
{
    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;
} process_context_t;

typedef struct process
{
    int pid;
    process_context_t context;
    process_state_t state;
    int *base_address;
} process_t;

process_t *processes[ 15 ];

int processes_count, curr_pid;

void process_init();
process_t *process_create( int * );


================================================
FILE: evolution_by_versions/05_539kernel_version_g/scheduler.c
================================================
#include "scheduler.h"

void scheduler_init()
{
    next_sch_pid = 0;
    curr_sch_pid = 0;
}

process_t *get_next_process()
{
    process_t *next_process = processes[ next_sch_pid ];
    
    curr_sch_pid = next_sch_pid;
    next_sch_pid++;
    next_sch_pid = next_sch_pid % processes_count;
    
    return next_process;
}

void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )
{
    process_t *curr_process;
    
    print( " EAX = " ); // For Testing Purpose
    printi( eax ); // For Testing Purpose
    
    // ... //
    
    // PART 1
    
    curr_process = processes[ curr_sch_pid ];
    next_process = get_next_process();
    
    // ... //
    
    // PART 2

    if ( curr_process->state == RUNNING )
    {
        curr_process->context.eax = eax;
        curr_process->context.ecx = ecx;
        curr_process->context.edx = edx;
        curr_process->context.ebx = ebx;
        curr_process->context.esp = esp;
        curr_process->context.ebp = ebp;
        curr_process->context.esi = esi;
        curr_process->context.edi = edi;
        curr_process->context.eip = eip;
    }
    
    curr_process->state = READY;
    
    // ... //
    
    // PART 3
    
    asm( "  mov %0, %%eax;  \
            mov %0, %%ecx;  \
            mov %0, %%edx;  \
            mov %0, %%ebx;  \
            mov %0, %%esi;  \
            mov %0, %%edi;" 
            : : "r" ( next_process->context.eax ), "r" ( next_process->context.ecx ), "r" ( next_process->context.edx ), "r" ( next_process->context.ebx ),
                "r" ( next_process->context.esi ), "r" ( next_process->context.edi ) );
    
    next_process->state = RUNNING;
}

void run_next_process()
{
    asm( "  sti;            \
            jmp *%0" : : "r" ( next_process->context.eip ) );
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/scheduler.h
================================================
#include "process.h"

int next_sch_pid, curr_sch_pid;

process_t *next_process;

void scheduler_init();
process_t *get_next_process();
void scheduler( int, int, int, int, int, int, int, int, int );
void run_next_process();


================================================
FILE: evolution_by_versions/05_539kernel_version_g/screen.c
================================================
#include "screen.h"

void screen_init()
{
    video = 0xB8000;
    nextTextPos = 0;
    currLine = 0;
}

void print( char *str )
{
	int currCharLocationInVidMem, currColorLocationInVidMem;
	
	while ( *str != '\0' )
	{
        currCharLocationInVidMem = nextTextPos * 2;
		currColorLocationInVidMem = currCharLocationInVidMem + 1;
		
		video[ currCharLocationInVidMem ] = *str;
		video[ currColorLocationInVidMem ] = 15;
		
		nextTextPos++;
		
		str++;
	}
}

void println()
{
	nextTextPos = ++currLine * 80;
}

void printi( int number )
{
	char* digitToStr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
	
	if ( number >= 0 && number <= 9 )
	{
		print( digitToStr[ number ] );
		return;
	}
	else
	{
		int remaining = number % 10;
		number = number / 10;
		
		printi( number );
		printi( remaining );
	}
}


================================================
FILE: evolution_by_versions/05_539kernel_version_g/screen.h
================================================
volatile unsigned char *video;

int nextTextPos;
int currLine;

void screen_init();
void print( char * );
void println();
void printi( int );


================================================
FILE: evolution_by_versions/05_539kernel_version_g/starter.asm
================================================
bits 16
extern kernel_main
extern interrupt_handler
extern scheduler
extern run_next_process
extern page_directory

global load_page_directory
global enable_paging

start:
	mov ax, cs
	mov ds, ax
		
	call load_gdt
	call init_video_mode
	call enter_protected_mode
    call setup_interrupts
    call load_task_register
	
	call 08h:start_kernel
	
load_gdt:
	cli
	lgdt [gdtr - start]
	
	ret
	
enter_protected_mode:
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	ret
	
init_video_mode:
	mov ah, 0h
	mov al, 03h
	int 10h
	
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	ret
	
setup_interrupts:
	call remap_pic
	call load_idt
	
	ret
	
remap_pic:
	mov al, 11h
	
	send_init_cmd_to_pic_master: 	
		out 0x20, al
		
	send_init_cmd_to_pic_slave: 	
		out 0xa0, al
		
	; ... ;
	
	make_irq_starts_from_intr_32_in_pic_master:		
		mov al, 32d
		out 0x21, al
	
	make_irq_starts_from_intr_40_in_pic_slave:
		mov al, 40d
		out 0xa1, al 
	
	; ... ;
	
	tell_pic_master_where_pic_slave_is_connected:
		mov al, 04h
		out 0x21, al
	
	tell_pic_slave_where_pic_master_is_connected:
		mov al, 02h
		out 0xa1, al
	
	; ... ;
	
	mov al, 01h
	
	tell_pic_master_the_arch_is_x86:
		out 0x21, al
	
	tell_pic_slave_the_arch_is_x86:
		out 0xa1, al
	
	; ... ;
	
	mov al, 0h
	
	make_pic_master_enables_all_irqs:
		out 0x21, al
	
	make_pic_slave_enables_all_irqs:
		out 0xa1, al
	
	; ... ;
	
	ret
	
load_idt:
	lidt [idtr - start]
	ret
	
load_task_register:
    mov ax, 40d
    ltr ax
    
    ret
	
bits 32
load_page_directory:
	mov eax, [page_directory]
	mov cr3, eax
	
	ret
	
enable_paging:
	mov eax, cr0
	or eax, 80000000h
	mov cr0, eax
	
	ret
	
start_kernel:
	mov eax, 10h
	mov ds, eax
	mov ss, eax
    
	mov eax, 0h
	mov es, eax
	mov fs, eax
	mov gs, eax
	
	sti
	
	call kernel_main
	
%include "gdt.asm"
%include "idt.asm"

tss:
    dd 0


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/Makefile
================================================
ASM = nasm
CC = gcc
BOOTSTRAP_FILE = bootstrap.asm 
SIMPLE_KERNEL = simple_kernel.asm
INIT_KERNEL_FILES = starter.asm
KERNEL_FILES = main.c
KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie
KERNEL_OBJECT = -o kernel.elf

build: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf
	$(CC) $(KERNEL_FLAGS) process.c -o process.elf
	$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf
	$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf
	$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf
	$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf
	$(CC) $(KERNEL_FLAGS) str.c -o str.elf
	$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20
	dd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046
	bochs -f bochs
	#qemu-system-x86_64 -machine pc kernel.img


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/ata.c
================================================
#include "ata.h"

void wait_drive_until_ready()
{
	int status = 0;
	
	do
	{
		status = dev_read( BASE_PORT + 7 );
	} while ( ( status ^ 0x80 ) == 128 );
}

void *read_disk_chs( int sector )
{
	// Part 1
	
	dev_write( BASE_PORT + 6, 0x0a0 );
	dev_write( BASE_PORT + 2, 1 );
	dev_write( BASE_PORT + 3, sector );
	dev_write( BASE_PORT + 4, 0 );
	dev_write( BASE_PORT + 5, 0 );
	dev_write( BASE_PORT + 7, 0x20 );
	
    // ... //
    
    // Part 2
    wait_drive_until_ready();
	
    // ... //
    
	// Part 3
	
    short *buffer = kalloc( SECTOR_SIZE );
    
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		buffer[ currByte ] = dev_read( BASE_PORT );

	return buffer;
}

void *read_disk( int address )
{
	dev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) );
	dev_write( BASE_PORT + 2, 1 );
	dev_write( BASE_PORT + 3, address & 0x000000FF );
	dev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 );
	dev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 );
	dev_write( BASE_PORT + 7, 0x20 );
	
    // ... //
    
    wait_drive_until_ready();
	
    // ... //
    
    short *buffer = kalloc( SECTOR_SIZE );
    
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		buffer[ currByte ] = dev_read( BASE_PORT );

	return buffer;
}

void write_disk_chs( int sector, short *buffer )
{
	dev_write( BASE_PORT + 6, 0x0a0 );
	dev_write( BASE_PORT + 2, 1 );
	dev_write( BASE_PORT + 3, sector );
	dev_write( BASE_PORT + 4, 0 );
	dev_write( BASE_PORT + 5, 0 );
	dev_write( BASE_PORT + 7, 0x30 );
	
	wait_drive_until_ready();
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		dev_write_word( BASE_PORT, buffer[ currByte ] );
    
	wait_drive_until_ready();
}

void write_disk( int address, short *buffer )
{
	dev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) );
	dev_write( BASE_PORT + 2, 1 );
	dev_write( BASE_PORT + 3, address & 0x000000FF );
	dev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 );
	dev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 );
	dev_write( BASE_PORT + 7, 0x30 );
	
	wait_drive_until_ready();
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		dev_write_word( BASE_PORT, buffer[ currByte ] );
		
	wait_drive_until_ready();
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/ata.h
================================================
#define BASE_PORT 0x1F0
#define SECTOR_SIZE 512

void wait_drive_until_ready();

void *read_disk( int );
void write_disk( int, short * );

void *read_disk_chs( int );
void write_disk_chs( int, short * );


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/bochs
================================================
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1
config_interface: textconfig
display_library: x, options="gui_debug"
memory: host=32, guest=32
romimage: file="/usr/share/bochs/BIOS-bochs-latest"
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, mode=flat, translation=auto, path="kernel.img", cylinders=2, heads=16, spt=63, biosdetect=auto, model="Generic 1234"
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, avx=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, tbm=0, fma4=0, vmx=1, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1
cpuid: vendor_string="GenuineIntel"
cpuid: brand_string="              Intel(R) Pentium(R) 4 CPU        "


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/bootstrap.asm
================================================
start:
	mov ax, 07C0h
	mov ds, ax
	
	mov si, title_string
	call print_string
	
	mov si, message_string
	call print_string
	
	call load_kernel_from_disk
	jmp 0900h:0000
	
load_kernel_from_disk:
	mov ax, [curr_sector_to_load]
	sub ax, 2
	mov bx, 512d
	mul bx
	mov bx, ax
	
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h
	mov al, 1h
	mov ch, 0h
	mov cl, [curr_sector_to_load]
	mov dh, 0h
	mov dl, 80h
	int 13h
		
	jc kernel_load_error
	
	sub byte [number_of_sectors_to_load], 1
	add byte [curr_sector_to_load], 1
	cmp byte [number_of_sectors_to_load], 0
	
	jne load_kernel_from_disk
	
	ret
    
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	jmp $
	
print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h
	
	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; Reading current cursor position
    mov ah, 03h
	mov bh, 0
	int 10h
	
    ; Move the cursor to the beginning
	mov ah, 02h
	mov dl, 0
	int 10h

	ret

title_string        db  'The Bootloader of 539kernel.', 0
message_string      db  'The kernel is loading...', 0
load_error_string   db  'The kernel cannot be loaded', 0
number_of_sectors_to_load 	db 	15d
curr_sector_to_load 		db 	2d

times 510-($-$$) db 0

dw 0xAA55


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/filesystem.c
================================================
#include "filesystem.h"

void filesystem_init()
{
	base_block = read_disk( BASE_BLOCK_ADDRESS );
}

void create_file( char *filename, char *buffer )
{
	int metadata_lba = ( base_block->head == 0 ) ? BASE_BLOCK_ADDRESS + 1 : base_block->tail + 2;
	int file_lba = metadata_lba + 1;
	
	metadata_t *metadata = kalloc( sizeof( metadata_t ) );
	
	metadata->next_file_address = 0;
    
    int currIdx;
	
	for ( currIdx = 0; *filename != '\0' && currIdx < FILENAME_LENGTH - 1; currIdx++, filename++ )
		metadata->filename[ currIdx ] = *filename;
	
	metadata->filename[ currIdx ] = '\0';
	
	write_disk( metadata_lba, metadata );
	write_disk( file_lba, buffer );
	
	if ( base_block->head == 0 )
	{
		update_base_block( metadata_lba, metadata_lba );
	}
	else
	{	
		metadata_t *tail_metadata = load_metadata( base_block->tail );
		
		tail_metadata->next_file_address = metadata_lba;
		
		write_disk( base_block->tail, tail_metadata );		
		update_base_block( base_block->head, metadata_lba );
	}
}


char **list_files()
{
    // Part 1
    
	if ( base_block->head == 0 )
		return -1;
	
    // Part 2
    
	char **list;
	
	list = kalloc( get_files_number() * sizeof( char * ) );
	
    // Part 3
    
	metadata_t *curr_file = load_metadata( base_block->head );
	
	int idx = 0;
	
	while ( 1 )
	{
		list[ idx ] = curr_file->filename;

		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file = load_metadata( curr_file->next_file_address );
		
		idx++;
	}
	
	return list;
}



char *read_file( char *filename )
{
	int address = get_address_by_filename( filename );
	
	if ( address == 0 )
		return 0;

	char *buffer = read_disk( address + 1 );
	
	return buffer;
}



void delete_file( char *filename )
{	
    // Part 1
    
	int curr_file_address = get_address_by_filename( filename );
	
	if ( curr_file_address == 0 )
		return;
	
	metadata_t *curr_file_metadata = read_disk( curr_file_address );
	
    // Part 2
    
    if ( get_files_number() == 1 )
	{
		update_base_block( 0, 0 );
		
		return;
	}
    
    // Part 3
	if ( curr_file_address == base_block->head )
	{
		update_base_block( curr_file_metadata->next_file_address, base_block->tail );
	}
    // Part 4
	else
	{
		int prev_file_address = get_prev_file_address( curr_file_address );
		
		metadata_t *prev_file = load_metadata( prev_file_address );

		prev_file->next_file_address = curr_file_metadata->next_file_address;
		
		write_disk( prev_file_address, prev_file );
		
		if ( curr_file_address == base_block->tail )
			update_base_block( base_block->head, prev_file_address );
	}
}

// ... //

void update_base_block( int new_head, int new_tail )
{
	base_block->head = new_head;
	base_block->tail = new_tail;
	
	write_disk( BASE_BLOCK_ADDRESS, base_block );
}

metadata_t *load_metadata( int address )
{
	metadata_t *metadata = read_disk( address );
	
	return metadata;
}

int get_address_by_filename( char *filename )
{
	metadata_t *curr_file = load_metadata( base_block->head );
	int curr_file_address = base_block->head;
	
	int idx = 0;
	
	while ( 1 )
	{
		if ( strcmp( curr_file->filename, filename ) == 1 )
			return curr_file_address;
			
		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file_address = curr_file->next_file_address;
		curr_file = load_metadata( curr_file->next_file_address );		
	}
	
	return 0;
}

int get_prev_file_address( int address )
{
	metadata_t *prev_file = load_metadata( base_block->head );
	int prev_file_address = base_block->head;

	while ( 1 )
	{
		if ( prev_file->next_file_address == address )
			return prev_file_address;
		
		prev_file_address = prev_file->next_file_address;
		prev_file = load_metadata( prev_file->next_file_address );
	}
		
	return -1;
}

int get_files_number()
{
	if ( base_block->head == 0 )
		return 0;
	
	int files_number = 0;
	
	// ... //
	
	metadata_t *curr_file = load_metadata( base_block->head );
	
	while ( 1 )
	{
		files_number++;

		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file = load_metadata( curr_file->next_file_address );
	}
	
	return files_number;
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/filesystem.h
================================================
#define BASE_BLOCK_ADDRESS 100
#define FILENAME_LENGTH 256

typedef struct
{
	int head, tail;
} base_block_t;

typedef struct
{
	char filename[ FILENAME_LENGTH ];
	int next_file_address;
} metadata_t;

base_block_t *base_block;

void filesystem_init();
void create_file( char *, char * );
char **list_files();
char *read_file( char * );

// Auxiliary Functions
metadata_t *load_metadata( int );
int get_address_by_filename( char * );
int get_prev_file_address( int );
int get_files_number();


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/gdt.asm
================================================
gdt:
	null_descriptor				: 	dw 0, 0, 0, 0
	kernel_code_descriptor		: 	dw 0xffff, 0x0000, 0x9a00, 0x00cf
	kernel_data_descriptor		: 	dw 0xffff, 0x0000, 0x9200, 0x00cf
	userspace_code_descriptor	: 	dw 0xffff, 0x0000, 0xfa00, 0x00cf
	userspace_data_descriptor	: 	dw 0xffff, 0x0000, 0xf200, 0x00cf
	tss_descriptor				: 	dw tss + 3, tss, 0x8900, 0x0000

gdtr:
	gdt_size_in_bytes	: 	dw ( 6 * 8 )
	gdt_base_address	: 	dd gdt



================================================
FILE: evolution_by_versions/06_539kernel_version_ne/heap.c
================================================
#include "heap.h"

void heap_init()
{
	heap_base = 0x100000;
}

int kalloc( int bytes )
{
	unsigned int new_object_address = heap_base;
	
	heap_base += bytes;
	
	return new_object_address;
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/heap.h
================================================
unsigned int heap_base;

void heap_init();
int kalloc( int );


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/idt.asm
================================================
isr_0:
	cli
	push 0
	jmp isr_basic

isr_1:
	cli
	push 1
	jmp isr_basic
	
isr_2:
	cli
	push 2
	jmp isr_basic
	
isr_3:
	cli
	push 3
	jmp isr_basic
	
isr_4:
	cli
	push 4
	jmp isr_basic
	
isr_5:
	cli
	push 5
	jmp isr_basic
	
isr_6:
	cli
	push 6
	jmp isr_basic
	
isr_7:
	cli
	push 7
	jmp isr_basic
	
isr_8:
	cli
	push 8
	jmp isr_basic
	
isr_9:
	cli
	push 9
	jmp isr_basic
	
isr_10:
	cli
	push 10
	jmp isr_basic
	
isr_11:
	cli
	push 11
	jmp isr_basic
	
isr_12:
	cli
	push 12
	jmp isr_basic
	
isr_13:
	cli
	push 13
	jmp isr_basic
	
isr_14:
	cli
	push 14
	jmp isr_basic
	
isr_15:
	cli
	push 15
	jmp isr_basic
	
isr_16:
	cli
	push 16
	jmp isr_basic
	
isr_17:
	cli
	push 17
	jmp isr_basic
	
isr_18:
	cli
	push 18
	jmp isr_basic
	
isr_19:
	cli
	push 19
	jmp isr_basic
	
isr_20:
	cli
	push 20
	jmp isr_basic
	
isr_21:
	cli
	push 21
	jmp isr_basic

isr_22:
	cli
	push 22
	jmp isr_basic
	
isr_23:
	cli
	push 23
	jmp isr_basic
	
isr_24:
	cli
	push 24
	jmp isr_basic
	
isr_25:
	cli
	push 25
	jmp isr_basic
	
isr_26:
	cli
	push 26
	jmp isr_basic
	
isr_27:
	cli
	push 27
	jmp isr_basic
	
isr_28:
	cli
	push 28
	jmp isr_basic
	
isr_29:
	cli
	push 29
	jmp isr_basic
	
isr_30:
	cli
	push 30
	jmp isr_basic
	
isr_31:
	cli
	push 31
	jmp isr_basic
	
isr_32:
    ; Part 1
    
    cli ; Step 1
    
    pusha ; Step 2
    
    ; Step 3
    mov eax, [esp + 32]
    push eax  
    
    call scheduler ; Step 4
    
    ; ... ;
    
    ; Part 2
    
    ; Step 5
    mov al, 0x20
    out 0x20, al
    
    ; Step 6
    add esp, 40d
    push run_next_process
    
    iret ; Step 7
	
isr_33:
	cli
	push 33
	jmp irq_basic
	
isr_34:
	cli
	push 34
	jmp irq_basic
	
isr_35:
	cli
	push 35
	jmp irq_basic
	
isr_36:
	cli
	push 36
	jmp irq_basic
	
isr_37:
	cli
	push 37
	jmp irq_basic

isr_38:
	cli
	push 38
	jmp irq_basic

isr_39:
	cli
	push 39
	jmp irq_basic

isr_40:
	cli
	push 40
	jmp irq_basic

isr_41:
	cli
	push 41
	jmp irq_basic

isr_42:
	cli
	push 42
	jmp irq_basic

isr_43:
	cli
	push 43
	jmp irq_basic

isr_44:
	cli
	push 44
	jmp irq_basic

isr_45:
	cli
	push 45
	jmp irq_basic

isr_46:
	cli
	push 46
	jmp irq_basic

isr_47:
	cli
	push 47
	jmp irq_basic
	
isr_48:
	cli
	push 48
	jmp irq_basic
	
isr_basic:
	call interrupt_handler
	
	pop eax
    
    sti
	iret
	
irq_basic:
	call interrupt_handler
	
	mov al, 0x20
	out 0x20, al
	
	cmp byte [esp], 40d
	jnge irq_basic_end
	
	mov al, 0xa0
	out 0x20, al
	
	irq_basic_end:
		pop eax
        
        sti
		iret
		
idt:
	dw isr_0, 8, 0x8e00, 0x0000
	dw isr_1, 8, 0x8e00, 0x0000
	dw isr_2, 8, 0x8e00, 0x0000
	dw isr_3, 8, 0x8e00, 0x0000
	dw isr_4, 8, 0x8e00, 0x0000
	dw isr_5, 8, 0x8e00, 0x0000
	dw isr_6, 8, 0x8e00, 0x0000
	dw isr_7, 8, 0x8e00, 0x0000
	dw isr_8, 8, 0x8e00, 0x0000
	dw isr_9, 8, 0x8e00, 0x0000
	dw isr_10, 8, 0x8e00, 0x0000
	dw isr_11, 8, 0x8e00, 0x0000
	dw isr_12, 8, 0x8e00, 0x0000
	dw isr_13, 8, 0x8e00, 0x0000
	dw isr_14, 8, 0x8e00, 0x0000
	dw isr_15, 8, 0x8e00, 0x0000
	dw isr_16, 8, 0x8e00, 0x0000
	dw isr_17, 8, 0x8e00, 0x0000
	dw isr_18, 8, 0x8e00, 0x0000
	dw isr_19, 8, 0x8e00, 0x0000
	dw isr_20, 8, 0x8e00, 0x0000
	dw isr_21, 8, 0x8e00, 0x0000
	dw isr_22, 8, 0x8e00, 0x0000
	dw isr_23, 8, 0x8e00, 0x0000
	dw isr_24, 8, 0x8e00, 0x0000
	dw isr_25, 8, 0x8e00, 0x0000
	dw isr_26, 8, 0x8e00, 0x0000
	dw isr_27, 8, 0x8e00, 0x0000
	dw isr_28, 8, 0x8e00, 0x0000
	dw isr_29, 8, 0x8e00, 0x0000
	dw isr_30, 8, 0x8e00, 0x0000
	dw isr_31, 8, 0x8e00, 0x0000
	dw isr_32, 8, 0x8e00, 0x0000
	dw isr_33, 8, 0x8e00, 0x0000
	dw isr_34, 8, 0x8e00, 0x0000
	dw isr_35, 8, 0x8e00, 0x0000
	dw isr_36, 8, 0x8e00, 0x0000
	dw isr_37, 8, 0x8e00, 0x0000
	dw isr_38, 8, 0x8e00, 0x0000
	dw isr_39, 8, 0x8e00, 0x0000
	dw isr_40, 8, 0x8e00, 0x0000
	dw isr_41, 8, 0x8e00, 0x0000
	dw isr_42, 8, 0x8e00, 0x0000
	dw isr_43, 8, 0x8e00, 0x0000
	dw isr_44, 8, 0x8e00, 0x0000
	dw isr_45, 8, 0x8e00, 0x0000
	dw isr_46, 8, 0x8e00, 0x0000
	dw isr_47, 8, 0x8e00, 0x0000
	dw isr_48, 8, 0x8e00, 0x0000
	
idtr:
	idt_size_in_bytes	: 	dw idtr - idt
	idt_base_address	: 	dd idt


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/linker.ld
================================================
/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */

SECTIONS
{
  .text 0x09000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
  }

  end = .; _end = .; __end = .;
} 


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/main.c
================================================
#include "screen.h"
#include "scheduler.h"
#include "heap.h"

void processA();
void processB();
void processC();
void processD();

void print_fs();

void kernel_main()
{
	heap_init();
	paging_init();
	screen_init();
	process_init();
	scheduler_init();
	filesystem_init();
	
	print( "Welcome to 539kernel!" );
	println();
	print( "We are now in Protected-mode" );
	println();
	printi( 539 );
	println();
	
    process_create( &processA );
	process_create( &processB );
	process_create( &processC );
	process_create( &processD );
	
	// ... //
	
	char *data = kalloc( 512 );
	strcpy( data, "The content of the first file on 539filesystem" );	
	create_file( "first_file", data );
	
	// ... //
	
	char *data2 = kalloc( 512 );
	strcpy( data2, "SECOND FILE in 539filesystem" );
	create_file( "second_file", data2 );
	
	// ... //
	
	char *data3 = kalloc( 512 );
	strcpy( data3, "THIRD FILE in 539filesystem" );
	create_file( "third_file", data3 );
		
	// ... //
	
	print( read_file( "first_file" ) ); println();
	print( read_file( "second_file" ) ); println();
	print( read_file( "third_file" ) ); println();
	
	// ... //
	
	print_fs();
	delete_file( "first_file" );
	print_fs();

	// ... //
	
	while( 1 );
}

void print_fs()
{
	char **files = list_files();

	for ( int currIdx = 0; currIdx < get_files_number(); currIdx++ )
	{
		print( "File: " );
		print( files[ currIdx ] );
		println();
	}
	
	print( "==" );
	println();
}

void interrupt_handler( int interrupt_number )
{
	//println();
	//print( "Interrupt Received " );
	//printi( interrupt_number );
}

void processA()
{
    print( "Process A," );

    while ( 1 )
        asm( "mov $5390, %eax" );
}

void processB()
{
    print( "Process B," );

    while ( 1 )
        asm( "mov $5391, %eax" );
}

void processC()
{
    print( "Process C," );

    while ( 1 )
        asm( "mov $5392, %eax" );
}

void processD()
{
    print( "Process D," );

    while ( 1 )
        asm( "mov $5393, %eax" );
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/paging.c
================================================
#include "paging.h"

int create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )
{
	int entry = 0;
	
	entry |= present;
	entry |= writable << 1;
	entry |= privilege_level << 2;
	entry |= write_through_cache << 3;
	entry |= cache_enabled << 4;
	entry |= accessed << 5;
	entry |= dirty << 6;
	entry |= page_size << 7;
	
	return base_address | entry;
}

void paging_init()
{
    // PART 1:
    
	unsigned int curr_page_frame = 0;
	
	page_directory = kalloc( 4 * 1024 );
		
	for ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )
	{
		unsigned int *pagetable = kalloc( 4 * PTE_NUM );
		
		for ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )
			pagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );
		
		page_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );
	}
    
    // ... //
    
    // PART 2
    
	load_page_directory();
	enable_paging();
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/paging.h
================================================
#define PDE_NUM 3
#define PTE_NUM 1024

extern void load_page_directory();
extern void enable_paging();

unsigned int *page_directory;

void paging_init();
int create_page_entry( int, char, char, char, char, char, char, char, char );


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/process.c
================================================
#include "process.h"

void process_init()
{
    processes_count = 0;
    curr_pid = 0;
}

process_t *process_create( int *base_address )
{
	process_t *process = kalloc( sizeof( process_t ) );
	
    process->pid = curr_pid++;
    
    process->context.eax = 0;
    process->context.ecx = 0;
    process->context.edx = 0;
    process->context.ebx = 0;
    process->context.esp = 0;
    process->context.ebp = 0;
    process->context.esi = 0;
    process->context.edi = 0;
    process->context.eip = base_address;
    
    process->state = READY;
    process->base_address = base_address;
    
    processes[ process->pid ] = process;
    
    processes_count++;
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/process.h
================================================
typedef enum process_state { READY, RUNNING } process_state_t;

typedef struct process_context
{
    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;
} process_context_t;

typedef struct process
{
    int pid;
    process_context_t context;
    process_state_t state;
    int *base_address;
} process_t;

process_t *processes[ 15 ];

int processes_count, curr_pid;

void process_init();
process_t *process_create( int * );


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/scheduler.c
================================================
#include "scheduler.h"

void scheduler_init()
{
    next_sch_pid = 0;
    curr_sch_pid = 0;
}

process_t *get_next_process()
{
    process_t *next_process = processes[ next_sch_pid ];
    
    curr_sch_pid = next_sch_pid;
    next_sch_pid++;
    next_sch_pid = next_sch_pid % processes_count;
    
    return next_process;
}

void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )
{
    process_t *curr_process;
    
    print( " EAX = " ); // For Testing Purpose
    printi( eax ); // For Testing Purpose
    
    // ... //
    
    // PART 1
    
    curr_process = processes[ curr_sch_pid ];
    next_process = get_next_process();
    
    // ... //
    
    // PART 2

    if ( curr_process->state == RUNNING )
    {
        curr_process->context.eax = eax;
        curr_process->context.ecx = ecx;
        curr_process->context.edx = edx;
        curr_process->context.ebx = ebx;
        curr_process->context.esp = esp;
        curr_process->context.ebp = ebp;
        curr_process->context.esi = esi;
        curr_process->context.edi = edi;
        curr_process->context.eip = eip;
    }
    
    curr_process->state = READY;
    
    // ... //
    
    // PART 3
    
    asm( "  mov %0, %%eax;  \
            mov %0, %%ecx;  \
            mov %0, %%edx;  \
            mov %0, %%ebx;  \
            mov %0, %%esi;  \
            mov %0, %%edi;" 
            : : "r" ( next_process->context.eax ), "r" ( next_process->context.ecx ), "r" ( next_process->context.edx ), "r" ( next_process->context.ebx ),
                "r" ( next_process->context.esi ), "r" ( next_process->context.edi ) );
    
    next_process->state = RUNNING;
}

void run_next_process()
{
    asm( "  sti;            \
            jmp *%0" : : "r" ( next_process->context.eip ) );
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/scheduler.h
================================================
#include "process.h"

int next_sch_pid, curr_sch_pid;

process_t *next_process;

void scheduler_init();
process_t *get_next_process();
void scheduler( int, int, int, int, int, int, int, int, int );
void run_next_process();


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/screen.c
================================================
#include "screen.h"

void screen_init()
{
    video = 0xB8000;
    nextTextPos = 0;
    currLine = 0;
}

void print( char *str )
{
	int currCharLocationInVidMem, currColorLocationInVidMem;
	
	while ( *str != '\0' )
	{
        currCharLocationInVidMem = nextTextPos * 2;
		currColorLocationInVidMem = currCharLocationInVidMem + 1;
		
		video[ currCharLocationInVidMem ] = *str;
		video[ currColorLocationInVidMem ] = 15;
		
		nextTextPos++;
		
		str++;
	}
}

void println()
{
	nextTextPos = ++currLine * 80;
}

void printi( int number )
{
	char* digitToStr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
	
	if ( number >= 0 && number <= 9 )
	{
		print( digitToStr[ number ] );
		return;
	}
	else
	{
		int remaining = number % 10;
		number = number / 10;
		
		printi( number );
		printi( remaining );
	}
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/screen.h
================================================
volatile unsigned char *video;

int nextTextPos;
int currLine;

void screen_init();
void print( char * );
void println();
void printi( int );


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/starter.asm
================================================
bits 16
extern kernel_main
extern interrupt_handler
extern scheduler
extern run_next_process
extern page_directory

global load_page_directory
global enable_paging
global dev_write
global dev_write_word
global dev_read

start:
	mov ax, cs
	mov ds, ax
		
	call load_gdt
	call init_video_mode
	call enter_protected_mode
    call setup_interrupts
    call load_task_register
	
	call 08h:start_kernel
	
load_gdt:
	cli
	lgdt [gdtr - start]
	
	ret
	
enter_protected_mode:
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	ret
	
init_video_mode:
	mov ah, 0h
	mov al, 03h
	int 10h
	
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	ret
	
setup_interrupts:
	call remap_pic
	call load_idt
	
	ret
	
remap_pic:
	mov al, 11h
	
	send_init_cmd_to_pic_master: 	
		out 0x20, al
		
	send_init_cmd_to_pic_slave: 	
		out 0xa0, al
		
	; ... ;
	
	make_irq_starts_from_intr_32_in_pic_master:		
		mov al, 32d
		out 0x21, al
	
	make_irq_starts_from_intr_40_in_pic_slave:
		mov al, 40d
		out 0xa1, al 
	
	; ... ;
	
	tell_pic_master_where_pic_slave_is_connected:
		mov al, 04h
		out 0x21, al
	
	tell_pic_slave_where_pic_master_is_connected:
		mov al, 02h
		out 0xa1, al
	
	; ... ;
	
	mov al, 01h
	
	tell_pic_master_the_arch_is_x86:
		out 0x21, al
	
	tell_pic_slave_the_arch_is_x86:
		out 0xa1, al
	
	; ... ;
	
	mov al, 0h
	
	make_pic_master_enables_all_irqs:
		out 0x21, al
	
	make_pic_slave_enables_all_irqs:
		out 0xa1, al
	
	; ... ;
	
	ret
	
load_idt:
	lidt [idtr - start]
	ret
	
load_task_register:
    mov ax, 40d
    ltr ax
    
    ret
	
bits 32
load_page_directory:
	mov eax, [page_directory]
	mov cr3, eax
	
	ret
	
enable_paging:
	mov eax, cr0
	or eax, 80000000h
	mov cr0, eax
	
	ret
	
dev_write:
    ; Part 1
	push edx
	push eax
	
    ; Part 2
	xor edx, edx
	xor eax, eax
	
    ; Part 3
	mov dx, [esp + 12]
	mov al, [esp + 16]
	
    ; Part 4
	out dx, al 
	
    ; Part 5
	pop eax
	pop edx
	
	ret
	
dev_write_word:
	push edx
	push eax	
	
    xor edx, edx
	xor eax, eax
    
	mov dx, [esp + 12]
	mov ax, [esp + 16]
	
	out dx, ax 
	
	pop eax
	pop edx
	
	ret
	
dev_read:
	push edx
	
	xor edx, edx
	xor eax, eax
	
	mov dx, [esp + 8]
	
	in ax, dx
	
	pop edx
	
	ret
	
start_kernel:
	mov eax, 10h
	mov ds, eax
	mov ss, eax
    
	mov eax, 0h
	mov es, eax
	mov fs, eax
	mov gs, eax
	
	;sti
	
	call kernel_main
	
%include "gdt.asm"
%include "idt.asm"

tss:
    dd 0


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/str.c
================================================
#include "str.h"

void strcpy( char *dest, char *src )
{
	int idx = 0;
	
	while ( *src != '\0' )
	{
		dest[ idx ] = *src;
		
		src++;
		idx++;
	}
}

int strcmp( char *str1, char *str2 )
{
	while ( *str1 != '\0' )
	{
		if ( *str1 != *str2 )
			return 0;
		
		str1++;
		str2++;
	}
	
	if ( *str2 != '\0' )
		return 0;
	
	return 1;
}


================================================
FILE: evolution_by_versions/06_539kernel_version_ne/str.h
================================================
void strcpy( char *, char * );
int strcmp( char *, char * );


================================================
FILE: src/.gitignore
================================================

# Created by https://www.gitignore.io/api/c
# Edit at https://www.gitignore.io/?templates=c

### C ###
# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf
*.bin

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

# End of https://www.gitignore.io/api/c

*.img


================================================
FILE: src/Makefile
================================================
ASM = nasm
CC = gcc
BOOTSTRAP_FILE = bootstrap.asm 
SIMPLE_KERNEL = simple_kernel.asm
INIT_KERNEL_FILES = starter.asm
KERNEL_FILES = main.c

# -m32 means generate 32-bit code. See "Machine-Dependent Options" section in gcc man page for details. Under "x86 Options" section "-m flag".
#
# -Wall:
#			"This enables all the warnings about constructions that some
#           users consider questionable, and that are easy to avoid (or
#           modify to prevent the warning), even in conjunction with
#           macros.  This also enables some language-specific warnings
#           described in C++ Dialect Options and Objective-C and
#           Objective-C++ Dialect Options." 
# 			~ GCC man page
# 
# -c:
# 			"If any of these options is used [-c, -S, -E], then the linker is not run, and object file names should not be used as arguments."
# 			~ GCC man page
#
# -ffreestanding:
#			"Assert that compilation targets a freestanding environment.
#           This implies -fno-builtin.  A freestanding environment is one
#           in which the standard library may not exist, and program
#           startup may not necessarily be at "main".  The most obvious
#           example is an OS kernel.  This is equivalent to -fno-hosted."
# 			~ GCC man page
#
# -no-pie:
#			"Don't produce a dynamically linked position independent executable."
# 			~ GCC man page
#
# -g:
#			"To tell GCC to emit extra information for use by a debugger, in almost all cases you need only to add -g to your other options."
# 			~ GCC man page
#
# -std=
#			"Determine the language standard.   This option is currently only supported when compiling C or C++."
#			gnu99: "GNU dialect of ISO C99.  The name gnu9x is deprecated."
#			gnu18: "GNU dialect of ISO C17.  This is the default for C code."
# 			~ GCC man page
#-std=gnu99 # -c -Wall -no-pie -g -std=gnu99
KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie -fcommon -fno-stack-protector
#  -O1 -fno-pie 
KERNEL_OBJECT = -o kernel.elf

build:
	echo Please Choose Type

kernel: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf
	$(CC) $(KERNEL_FLAGS) process.c -o process.elf
	$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf
	$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf
	$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf
	$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf
	$(CC) $(KERNEL_FLAGS) str.c -o str.elf
	$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20
	dd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046
	bochs -f bochs
	#qemu-system-x86_64 -s kernel.img

debug: $(BOOTSTRAP_FILE) $(KERNEL_FILE)
	$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o
	$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o 
	$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)
	$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf
	$(CC) $(KERNEL_FLAGS) process.c -o process.elf
	$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf
	$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf
	$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf
	$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf
	$(CC) $(KERNEL_FLAGS) str.c -o str.elf
	$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf
	ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf
	objcopy -O binary 539kernel.elf 539kernel.bin
	dd if=bootstrap.o of=kernel.img
	dd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20
	dd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2045
	bochs -f bochs
	
rerun-debug:
	bochs -f bochs

rerun-kernel:
	qemu-system-x86_64 -s kernel.img

clean:
	rm -f *.o
	rm -f *.elf
	rm -f *.img
	rm -f *.bin


================================================
FILE: src/README
================================================
[MQH] 25 Nov 2019
Here is the final code of 539kernel. Any incremental steps, examples and excercises can be found in ../examples.


================================================
FILE: src/ata.c
================================================
#include "ata.h"

void wait_drive_until_ready()
{
	int status = 0;
	
	do
	{
		status = dev_read( BASE_PORT + 7 );
	} while ( ( status ^ 0x80 ) == 128 );
}

// LBA
void *read_disk( int address )
{
	dev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) ); // Drive 0. Bits 0-3 = Bits 24-27 of LBA
	dev_write( BASE_PORT + 2, 1 ); // Sector count
	dev_write( BASE_PORT + 3, address & 0x000000FF ); // LBA's 0-7 bits
	dev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 ); // LBA's 8-15 bits
	dev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 ); // LBA's 16-23 bits
	dev_write( BASE_PORT + 7, 0x20 ); // Command: Read with Retry
	
	// ... //
	
	wait_drive_until_ready();
	
	// ... //
	
	short *buffer = kalloc( SECTOR_SIZE );
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		buffer[ currByte ] = dev_read( BASE_PORT );
	
	return buffer;
}

// LBA
void write_disk( int address, short *buffer )
{
	dev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) ); // Drive 0. Bits 0-3 = Bits 24-27 of LBA
	dev_write( BASE_PORT + 2, 1 ); // Sector count
	dev_write( BASE_PORT + 3, address & 0x000000FF ); // LBA's 0-7 bits
	dev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 ); // LBA's 8-15 bits
	dev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 ); // LBA's 16-23 bits
	dev_write( BASE_PORT + 7, 0x30 ); // Command: Write with Retry
	
	wait_drive_until_ready();
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		dev_write_word( BASE_PORT, buffer[ currByte ] );
		
	wait_drive_until_ready();
}


void *read_disk_chs( int sector )
{
	dev_write( BASE_PORT + 6, 0x0a0 ); // Drive 0 and Head 0
	dev_write( BASE_PORT + 2, 1 ); // Sector count
	dev_write( BASE_PORT + 3, sector ); // Sector to read
	dev_write( BASE_PORT + 4, 0 ); // Cylinder - Low
	dev_write( BASE_PORT + 5, 0 ); // Cylinder - High
	dev_write( BASE_PORT + 7, 0x20 ); // Command: Read with Retry
	
	// ... //
	
	wait_drive_until_ready();
	
	// ... //
	
	short *buffer = kalloc( SECTOR_SIZE );
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		buffer[ currByte ] = dev_read( BASE_PORT );

	return buffer;
}

void write_disk_chs( int sector, short *buffer )
{
	dev_write( BASE_PORT + 6, 0x0a0 ); // Drive 0 and Head 0
	dev_write( BASE_PORT + 2, 1 ); // Sector count
	dev_write( BASE_PORT + 3, sector ); // Sector to read
	dev_write( BASE_PORT + 4, 0 ); // Cylinder - Low
	dev_write( BASE_PORT + 5, 0 ); // Cylinder - High
	dev_write( BASE_PORT + 7, 0x30 ); // Command: Write with Retry
	
	// ... //
	
	wait_drive_until_ready();
	
	// ... //
	
	for ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )
		dev_write_word( BASE_PORT, buffer[ currByte ] );
	
	// ... //
	
	wait_drive_until_ready();
}




================================================
FILE: src/ata.h
================================================
#define BASE_PORT 0x1F0
#define SECTOR_SIZE 512

void wait_drive_until_ready();

void *read_disk( int );
void write_disk( int, short * );

void *read_disk_chs( int );
void write_disk_chs( int, short * );


================================================
FILE: src/bochs
================================================
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1
config_interface: textconfig
display_library: x, options="gui_debug"
memory: host=32, guest=32
romimage: file="/usr/share/bochs/BIOS-bochs-latest"
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: disk
floppy_bootsig_check: disabled=0
# no floppya
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, mode=flat, translation=auto, path="kernel.img", cylinders=2, heads=16, spt=63, biosdetect=auto, model="Generic 1234"
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0
ata3: enabled=0
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, avx=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, tbm=0, fma4=0, vmx=1, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1
cpuid: vendor_string="GenuineIntel"
cpuid: brand_string="              Intel(R) Pentium(R) 4 CPU        "

print_timestamps: enabled=0
debugger_log: -
magic_break: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
# no loader
log: -
logprefix: %t%e%d
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap=
user_shortcut: keys=none
mouse: enabled=0, type=ps2, toggle=ctrl+mbutton
parport1: enabled=1, file=""
parport2: enabled=0
com1: enabled=1, mode=null, dev=""
com2: enabled=0
com3: enabled=0
com4: enabled=0


================================================
FILE: src/bootstrap.asm
================================================
start:
	; [MQH] 3 Sep 2019
	; When a the boot sector is loaded by BIOS. It will be loaded on the location 07C0h in the memory.
	; What we do here is setting the register "ds" to the value "07C0" which is the same of the memory address we are on now.
	; Our variable "hello_string" will be loaded as a part of the bootloader, when we use it in the line "mov si, hello_string"
	; we're actually loading the memory address of the first character, let's assume that this memory address is (1000). Because
	; it is considered as a "data" by the processor. This offset (the memory address of "hello_string") will be added to the data segment
	; selector which resides in the register "ds". According to "Protected Mode Software Architecture", the initial value of "ds" is 0000h,
	; so, if we keep "ds" as it is, the CPU is going to load the data from the memory 00001000, BUT we are actually on 07C0, so the data
	; segment selector should be 07C0h so we can get the correct address of "hello_string" which is 07C01000 and not 00001000.
	; For backward compatibility, when the bootloader starts, the execution environment will be in "Real Mode", 16-bit.
	mov ax, 07C0h
	mov ds, ax
		
	; ... ;
	
	; == Printing == ;
	
	mov si, title_string
	call print_string ; "CALL" is used instead of "JMP" because we would like to return to the next instruction after "print_string" finishes.
	
	mov si, message_string
	call print_string
	
	; ... ;
	
	; === Loading the Kernel === ;
	
	call load_kernel_from_disk
	
	; If the loading has been performed correctly. Jump to the kernel's code which resides on 0900h:0000 according
	; to ES:BX values before calling (int 13h).
	;
	; There is a difference between "JMP" and "CALL" inctructions. The first one doesn't store returning information
	; in the stack while the later does. Because we are not going to return from kernel to the bootloader, we don't
	; need to store return information.
	
	jmp 0900h:0000

; ... ;
; ... ;

load_kernel_from_disk:	
	; [MQH] 26 Nov 2019
	; BIOS provides disk services through intrrupt 13h. The value of the register "ah" decides which disk service that we are requesting from BIOS.
	
	; The Disk Service "02h" loads sectors to the memory. The memory location that we would like to load our kernel in should be decided
	; before calling "int 13h". There are two parts of this location. The first part (segment selector) resides in the register "ES" while 
	; the other part (offset) resides in the register "BX".
	;
	; x86 Segment Registers:    CS: for code segment. 
	;                           DS, ES, FS, and GS: for 4 data segments.
	;                           SS: for stack segment.
	; They are 16-bit registers that hold "segment selectors"
	mov ax, [curr_sector_to_load]
	sub ax, 2
	mov bx, 512d
	mul bx
	mov bx, ax
	
	mov ax, 0900h
	mov es, ax
	
	mov ah, 02h     ; Requesting the service of reading disk sectors
	mov al, 1h    	; Number of sectors to read (How many sectors to read?)
	mov ch, 0h      ; Track number
	mov cl, [curr_sector_to_load]     ; Sector number
	mov dh, 0h      ; Head number
	mov dl, 80h     ; Drive to read from. (0 = Floppy. 80h = Drive #0. 81h = Drive #1)
	int 13h         ; BIOS Disk Services
	
	
	; The instruction "jc" jumps to a memory location when CF = 1 (jc = jump if carry).
	; CF (or carry flag) is the first bit of EFLAG register in x86. The BIOS service (13h,02h)
	; clear CF (that is, put 0 in CF) when everything is fine. But if there is some error
	; it's going to set CF (that is, put 1 in CF). Error code will be in "ah".
	;
	; If any error happens in loading our kernel. The bootloader is going to jump to the label "kernel_load_error".
	jc kernel_load_error
	
	sub byte [number_of_sectors_to_load], 1
	add byte [curr_sector_to_load], 1
	cmp byte [number_of_sectors_to_load], 0
	
	jne load_kernel_from_disk
	
	ret

; When the bootloader fails to load the kernel. A nice message is printted for the user.
kernel_load_error:
	mov si, load_error_string
	call print_string
	
	; "$" is a special expression in NASM. It means the starting memory address (or assembly position?) of current instruction, that means
	; the following instruction is going to loop forever. 
	jmp $

; ... ;
; ... ;

; [MQH] 3 Sep 2019
; BIOS provides video services through intrrupt 10h. The value of the register "ah" decides which video service that we are requesting from BIOS.
; Those BIOS services are only available on Real Mode (https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode)
;
; ah = 0Eh means that we wish to print a character in TTY mode.
; For an example of using service "0Eh" to print "Hello" character by character, please refer to "../examples/bootstrap/1/".
	
print_string:
	mov ah, 0Eh

print_char:
    ; [MQH] 26 Nov 2019
	; It's known that a byte = 8 bits. In x86 there are more two units: a "word" = 16 bits and "doubleword" = 32 bits. Some x86 instructions have multiple variants that work
	; with a specific aforementioned unit. "lods" is an example of these instructions, there is "lodsb" which works with a byte, "lodsw" which works with a word and "lodsd" which
	; works with doubleword.
	;
	; The instruction "lods" uses the value which is stored in register "si" (when using lodsb or loadsw) or register "esi" (when using lodsw) and assume that this
	; value as memory location. Then according to the used unit a (b)yte (8-bits), (w)ord (16-bits) or (d)oubleword (32-bit) will be read from the memory location DS:(E)SI
	; and store these bits in al, ax or eax according to the size of read data.
	lodsb
	
	cmp al, 0
	je printing_finished
	
	int 10h

	jmp print_char

printing_finished:
    mov al, 10d ; Print new line
    int 10h
    
    ; [MQH] NEW 25 June 2021
    ; Move the cursor to the beginning
    mov ah, 03h
	mov bh, 0
	int 10h
	
	mov ah, 02h
	mov dl, 0
	int 10h
    
    ; print_string is a procedure (or function), therefore we should return. It is called by using "CALL" instead of "JMP".
	ret

; ... ;

; [MQH] 9 Dec 2019
; "DB" is one of pseudo-instructions which is provided by NASM. A source line in NASM follows the following format
; label: instruction operands ; comment
; The label is optional and even the colon after the label is optional.
; "DB" is used to declare initialized data. The "B" in "DB" means byte.
; the part ", 0" means that the last byte will be 0. In some way resembles
; nul character in C strings.
;
; Put the string in the output of this assembly file. Byte by byte, and the address of
; this string will be in the label, so we can reach the string inside the assembly source code.
title_string        		db  'The Bootloader of 539kernel.', 0
message_string      		db  'The kernel is loading...', 0
load_error_string   		db  'The kernel cannot be loaded', 0
number_of_sectors_to_load 	db 	15d ; 255 sectors = 127.5KB ; [MQH] NEW 4 July 2021
curr_sector_to_load 		db 	2d

; [MQH] 9 Dec 2019
; "TIMES" is an NASM pseudo-instruction which repeats an instruction a number of specific times.
; The first operand of "TIMES" is the number of repetitions.
; As we mentioned before "$" means the starting address (or assembly position?) of current instruction.
; "$$" is another special expression which means the starting address (or assembly position?) of current section.
; So, we know that the size of bootstrap should be 512 byte. Two bytes are represent the magic code in the last line
; so 510 bytes remains for us. Our code starts from position $$ and we reached position $. Therefore, $ - $$ gives
; us the size of our code. So, 510 - ( $ - $$ ) gives us the remaining size of the 512 bytes and fills it with zeros
; by using "DB".
times 510-($-$$) db 0

; Put the magic code of bootloader in the end of assembly file's output. "W" means word.
dw 0xAA55


================================================
FILE: src/filesystem.c
================================================
#include "filesystem.h"

void filesystem_init()
{
	base_block = read_disk( BASE_BLOCK_ADDRESS );
}

void update_base_block( int new_head, int new_tail )
{
	base_block->head = new_head;
	base_block->tail = new_tail;
	
	write_disk( BASE_BLOCK_ADDRESS, base_block );
}

metadata_t *load_metadata( int address )
{
	metadata_t *metadata = read_disk( address );
	
	return metadata;
}

int get_files_number()
{
	if ( base_block->head == 0 )
		return 0;
	
	int files_number = 0;
	
	// ... //
	
	metadata_t *curr_file = load_metadata( base_block->head );
	
	while ( 1 )
	{
		files_number++;

		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file = load_metadata( curr_file->next_file_address );
	}
	
	return files_number;
}

void create_file( char *filename, char *buffer )
{
	int metadata_lba = ( base_block->head == 0 ) ? BASE_BLOCK_ADDRESS + 1 : base_block->tail + 2;
	int file_lba = metadata_lba + 1;
	
	metadata_t *metadata = kalloc( sizeof( metadata_t ) );
	
	metadata->next_file_address = 0;
	
	// ... //
	
	int currIdx;
	
	for ( currIdx = 0; *filename != '\0' && currIdx < FILENAME_LENGTH - 1; currIdx++, filename++ )
		metadata->filename[ currIdx ] = *filename;
	
	metadata->filename[ currIdx ] = '\0';
	
	// ... //
	
	write_disk( metadata_lba, metadata );
	write_disk( file_lba, buffer );
	
	// ... //
	
	if ( base_block->head == 0 )
	{
		update_base_block( metadata_lba, metadata_lba );
	}
	else
	{
		metadata_t *tail_metadata = load_metadata( base_block->tail );
		
		tail_metadata->next_file_address = metadata_lba;
		
		write_disk( base_block->tail, tail_metadata );		
		update_base_block( base_block->head, metadata_lba );
	}
}

char **list_files()
{
	if ( base_block->head == 0 )
		return -1;
	
	char **list;
	
	list = kalloc( get_files_number() * sizeof( char * ) );
		
	metadata_t *curr_file = load_metadata( base_block->head );
	
	int idx = 0;
	
	while ( 1 )
	{
		list[ idx ] = curr_file->filename;

		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file = load_metadata( curr_file->next_file_address );
		
		idx++;
	}
	
	return list;
}

int get_address_by_filename( char *filename )
{
	metadata_t *curr_file = load_metadata( base_block->head );
	int curr_file_address = base_block->head;
	
	int idx = 0;
	
	while ( 1 )
	{
		if ( strcmp( curr_file->filename, filename ) == 1 )
			return curr_file_address;
			
		if ( curr_file->next_file_address == 0 )
			break;
		
		curr_file_address = curr_file->next_file_address;
		curr_file = load_metadata( curr_file->next_file_address );		
	}
	
	return 0;
}

char *read_file( char *filename )
{
	int address = get_address_by_filename( filename );
	
	if ( address == 0 )
		return 0;
	
	printi( address );
	
	char *buffer = read_disk( address + 1 );
	
	return buffer;
}

int get_prev_file_address( int address )
{
	metadata_t *prev_file = load_metadata( base_block->head );
	int prev_file_address = base_block->head;

	while ( 1 )
	{
		if ( prev_file->next_file_address == address )
			return prev_file_address;
		
		prev_file_address = prev_file->next_file_address;
		prev_file = load_metadata( prev_file->next_file_address );
	}
		
	return -1;
}

void delete_file( char *filename )
{
	int curr_file_address = get_address_by_filename( filename );
	
	if ( curr_file_address == 0 )
		return;
		
	// ... //
	
	if ( get_files_number() == 1 )
	{
		update_base_block( 0, 0 );
		
		return;
	}
			
	metadata_t *curr_file_metadata = read_disk( curr_file_address );
	
	if ( curr_file_address == base_block->head )
	{
		update_base_block( curr_file_metadata->next_file_address, base_block->tail );
	}
	else
	{
		int prev_file_address = get_prev_file_address( curr_file_address );
		
		metadata_t *prev_file = load_metadata( prev_file_address );

		prev_file->next_file_address = curr_file_metadata->next_file_address;
		
		write_disk( prev_file_address, prev_file );
		
		if ( curr_file_address == base_block->tail )
			update_base_block( base_block->head, prev_file_address );
	}
}


================================================
FILE: src/filesystem.h
================================================
#define BASE_BLOCK_ADDRESS 100
#define FILENAME_LENGTH 256

typedef struct
{
	int head, tail;
} base_block_t;

typedef struct
{
	char filename[ FILENAME_LENGTH ];
	int next_file_address;
} metadata_t;

base_block_t *base_block;

void filesystem_init();
void create_file( char *, char * );
char **list_files();
char *read_file( char * );

// Auxiliary Functions
metadata_t *load_metadata( int );
int get_address_by_filename( char * );
int get_prev_file_address( int );
int get_files_number();


================================================
FILE: src/gdt.asm
================================================
; The values of the decriptors from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel)
gdt:
	null_descriptor				: 	dw 0, 0, 0, 0
	kernel_code_descriptor		: 	dw 0xffff, 0x0000, 0x9a00, 0x00cf
	kernel_data_descriptor		: 	dw 0xffff, 0x0000, 0x9200, 0x00cf
	userspace_code_descriptor	: 	dw 0xffff, 0x0000, 0xfa00, 0x00cf
	userspace_data_descriptor	: 	dw 0xffff, 0x0000, 0xf200, 0x00cf
	; DON'T FORGET TO CHANGE THE SIZE OF THE GDT
	; TODO: I think the limit isn't correct
	tss_descriptor				:	dw tss + 3, tss, 0x8900, 0x0000

gdtr:
	gdt_size_in_bytes	: 	dw ( 6 * 8 ) ;= 28h
	gdt_base_address	: 	dd gdt



================================================
FILE: src/heap.c
================================================
#include "heap.h"

void heap_init()
{
	heap_base = 0x100000;
}

int kalloc( int bytes )
{
	// Note: Not necessarily page-aligned
	
	unsigned int new_object_address = heap_base;
	
	heap_base += bytes;
	
	return new_object_address;
}


================================================
FILE: src/heap.h
================================================
unsigned int heap_base;

void heap_init();
int kalloc( int );


================================================
FILE: src/idt.asm
================================================
isr_0:
	cli
	push 0
	jmp isr_basic

isr_1:
	cli
	push 1
	jmp isr_basic
	
isr_2:
	cli
	push 2
	jmp isr_basic
	
isr_3:
	cli
	push 3
	jmp isr_basic
	
isr_4:
	cli
	push 4
	jmp isr_basic
	
isr_5:
	cli
	push 5
	jmp isr_basic
	
isr_6:
	cli
	push 6
	jmp isr_basic
	
isr_7:
	cli
	push 7
	jmp isr_basic
	
isr_8:
	cli
	push 8
	jmp isr_basic
	
isr_9:
	cli
	push 9
	jmp isr_basic
	
isr_10:
	cli
	push 10
	jmp isr_basic
	
isr_11:
	cli
	push 11
	jmp isr_basic
	
isr_12:
	cli
	push 12
	jmp isr_basic
	
isr_13:
	cli
	push 13
	jmp isr_basic
	
isr_14:
	cli
	push 14
	jmp isr_basic
	
isr_15:
	cli
	push 15
	jmp isr_basic
	
isr_16:
	cli
	push 16
	jmp isr_basic
	
isr_17:
	cli
	push 17
	jmp isr_basic
	
isr_18:
	cli
	push 18
	jmp isr_basic
	
isr_19:
	cli
	push 19
	jmp isr_basic
	
isr_20:
	cli
	push 20
	jmp isr_basic
	
isr_21:
	cli
	push 21
	jmp isr_basic

isr_22:
	cli
	push 22
	jmp isr_basic
	
isr_23:
	cli
	push 23
	jmp isr_basic
	
isr_24:
	cli
	push 24
	jmp isr_basic
	
isr_25:
	cli
	push 25
	jmp isr_basic
	
isr_26:
	cli
	push 26
	jmp isr_basic
	
isr_27:
	cli
	push 27
	jmp isr_basic
	
isr_28:
	cli
	push 28
	jmp isr_basic
	
isr_29:
	cli
	push 29
	jmp isr_basic
	
isr_30:
	cli
	push 30
	jmp isr_basic
	
isr_31:
	cli
	push 31
	jmp isr_basic
	
; System Timer
isr_32:
	
	cli
	
	pusha ; Store the context of current process
	
	mov eax, [esp + 32] ; EIP before interrupt. Could be the EIP of the current process
	push eax  
	
	call scheduler
	
	mov al, 0x20
	out 0x20, al
	
	add esp, 40d ; Remove return address from stack, EIP and all general purpose registers of previous process.
	push run_next_process

	iret
	
isr_33:
	cli
	push 33
	jmp irq_basic
	
isr_34:
	cli
	push 34
	jmp irq_basic
	
isr_35:
	cli
	push 35
	jmp irq_basic
	
isr_36:
	cli
	push 36
	jmp irq_basic
	
isr_37:
	cli
	push 37
	jmp irq_basic

isr_38:
	cli
	push 38
	jmp irq_basic

isr_39:
	cli
	push 39
	jmp irq_basic

isr_40:
	cli
	push 40
	jmp irq_basic

isr_41:
	cli
	push 41
	jmp irq_basic

isr_42:
	cli
	push 42
	jmp irq_basic

isr_43:
	cli
	push 43
	jmp irq_basic

isr_44:
	cli
	push 44
	jmp irq_basic

isr_45:
	cli
	push 45
	jmp irq_basic

isr_46:
	cli
	push 46
	jmp irq_basic

isr_47:
	cli
	push 47
	jmp irq_basic
	
isr_48:
	cli
	push 48
	jmp irq_basic

isr_basic:
;	cli
	call interrupt_handler
	
	pop eax
	sti
	iret
	
irq_basic:
;	cli
	call interrupt_handler
	
	mov al, 0x20
	out 0x20, al
	
	cmp byte [esp], 40d ; Interrupt number
	jnge irq_basic_end
	
	mov al, 0xa0
	out 0x20, al
	
	irq_basic_end:
		pop eax
		sti
		iret
	
; The value of the flags from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel)
idt:
	dw isr_0, 8, 0x8e00, 0x0000
	dw isr_1, 8, 0x8e00, 0x0000
	dw isr_2, 8, 0x8e00, 0x0000
	dw isr_3, 8, 0x8e00, 0x0000
	dw isr_4, 8, 0x8e00, 0x0000
	dw isr_5, 8, 0x8e00, 0x0000
	dw isr_6, 8, 0x8e00, 0x0000
	dw isr_7, 8, 0x8e00, 0x0000
	dw isr_8, 8, 0x8e00, 0x0000
	dw isr_9, 8, 0x8e00, 0x0000
	dw isr_10, 8, 0x8e00, 0x0000
	dw isr_11, 8, 0x8e00, 0x0000
	dw isr_12, 8, 0x8e00, 0x0000
	dw isr_13, 8, 0x8e00, 0x0000
	dw isr_14, 8, 0x8e00, 0x0000
	dw isr_15, 8, 0x8e00, 0x0000
	dw isr_16, 8, 0x8e00, 0x0000
	dw isr_17, 8, 0x8e00, 0x0000
	dw isr_18, 8, 0x8e00, 0x0000
	dw isr_19, 8, 0x8e00, 0x0000
	dw isr_20, 8, 0x8e00, 0x0000
	dw isr_21, 8, 0x8e00, 0x0000
	dw isr_22, 8, 0x8e00, 0x0000
	dw isr_23, 8, 0x8e00, 0x0000
	dw isr_24, 8, 0x8e00, 0x0000
	dw isr_25, 8, 0x8e00, 0x0000
	dw isr_26, 8, 0x8e00, 0x0000
	dw isr_27, 8, 0x8e00, 0x0000
	dw isr_28, 8, 0x8e00, 0x0000
	dw isr_29, 8, 0x8e00, 0x0000
	dw isr_30, 8, 0x8e00, 0x0000
	dw isr_31, 8, 0x8e00, 0x0000
	dw isr_32, 8, 0x8e00, 0x0000
	dw isr_33, 8, 0x8e00, 0x0000
	dw isr_34, 8, 0x8e00, 0x0000
	dw isr_35, 8, 0x8e00, 0x0000
	dw isr_36, 8, 0x8e00, 0x0000
	dw isr_37, 8, 0x8e00, 0x0000
	dw isr_38, 8, 0x8e00, 0x0000
	dw isr_39, 8, 0x8e00, 0x0000
	dw isr_40, 8, 0x8e00, 0x0000
	dw isr_41, 8, 0x8e00, 0x0000
	dw isr_42, 8, 0x8e00, 0x0000
	dw isr_43, 8, 0x8e00, 0x0000
	dw isr_44, 8, 0x8e00, 0x0000
	dw isr_45, 8, 0x8e00, 0x0000
	dw isr_46, 8, 0x8e00, 0x0000
	dw isr_47, 8, 0x8e00, 0x0000
	dw isr_48, 8, 0x8e00, 0x0000
	
idtr:
	idt_size_in_bytes	: 	dw idtr - idt
	idt_base_address	: 	dd idt


================================================
FILE: src/linker.ld
================================================
/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */

SECTIONS
{
  .text 0x09000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
    /*. = ALIGN(4096);*/
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
     /*. = ALIGN(4096);*/
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    /*. = ALIGN(4096);*/
  }

  end = .; _end = .; __end = .;
} 


================================================
FILE: src/main.c
================================================
#include "heap.h"
#include "paging.h"
#include "screen.h"
#include "scheduler.h"
#include "ata.h"
#include "filesystem.h"
#include "str.h"

void processA();
void processB();
void processC();
void processD();

void print_fs()
{
	char **files = list_files();

	for ( int currIdx = 0; currIdx < get_files_number(); currIdx++ )
	{
		print( "File: " );
		print( files[ currIdx ] );
		println();
	}
	
	print( "==" );
	println();
}

void kernel_main()
{	
	heap_init();
	paging_init();	
	screen_init();
	process_init();
	scheduler_init();
	filesystem_init();
	
	// ... //
	
	print( "Welcome to 539kernel!" );
	println();
	print( "We are now in Protected-mode" );
	println();
	printi( 539 );
	println();
	
	// ... //
	
	char *data = kalloc( 512 );
	strcpy( data, "The content of the first file on 539filesystem" );	
	create_file( "first_file", data );
	
	// ... //
	
	char *data2 = kalloc( 512 );
	strcpy( data2, "SECOND FILE in 539filesystem" );
	create_file( "second_file", data2 );
	
	// ... //
	
	char *data3 = kalloc( 512 );
	strcpy( data3, "THIRD FILE in 539filesystem" );
	create_file( "third_file", data3 );
	
	// ... //
	
	char *data4 = kalloc( 512 );
	strcpy( data4, "FOURTH FILE in 539filesystem" );
	create_file( "fourth_file", data4 );
	
	// ... //
	
	//print_fs();
	
	//delete_file( "first_file" );
	//print_fs();
	
	//delete_file( "second_file" );
	//print_fs();
	
	//delete_file( "third_file" );
	//print_fs();
	
	//delete_file( "fourth_file" );
	//print_fs();
	

	
	
	// ... //
	
	print( read_file( "first_file" ) ); println();
	print( read_file( "second_file" ) ); println();
	print( read_file( "third_file" ) ); println();
	print( read_file( "fourth_file" ) ); println();
	
	// ... //
	

	
	/*void *data = //read_disk_chs( 1 ); 
				read_disk( 100 );
	
	printi( data );*/
	
	
	/*
	char *data = kalloc( 512 );
	
	for ( int currIdx = 0; currIdx < 512; currIdx++ )
		data[ currIdx ] = 'X';
	
	data[ 511 ] = 'D';
	
	write_disk( 0, data );

	char *data2 = kalloc( 512 );
	
	for ( int currIdx = 0; currIdx < 512; currIdx++ )
		data2[ currIdx ] = 'Y';
	
	data2[ 511 ] = 'D';
		
	write_disk( 1, data2 );
	
	char *data3 = kalloc( 512 );
	
	for ( int currIdx = 0; currIdx < 512; currIdx++ )
		data3[ currIdx ] = 'Z';
	
	data3[ 511 ] = 'D';
		
	write_disk( 2, data3 );
	
	read_disk( 0 );
	read_disk( 1 );
	read_disk( 2 );
	*/
	
	
//	write_disk_chs( 1, data );
	/*
	println();
	print( "=============" );
	*/
	/*process_create( &processA );
	process_create( &processB );
	process_create( &processC );
	process_create( &processD );
	
	asm( "sti" );*/
	
	while( 1 );
}

void interrupt_handler( int interrupt_number )
{
	print( "Interrupt Received " );
	printi( interrupt_number );
	println();
}

void processA()
{
	print( "Process A," );

	while ( 1 )
		asm( "mov $5390, %eax" );
}

void processB()
{
	print( "Process B," );

	while ( 1 )
		asm( "mov $5391, %eax" );
}

void processC()
{
	print( "Process C," );

	while ( 1 )
		asm( "mov $5392, %eax" );
}

void processD()
{
	print( "Process D," );

	while ( 1 )
		asm( "mov $5393, %eax" );
}


================================================
FILE: src/paging.c
================================================
#include "paging.h"

void paging_init()
{
	// Initializing Kernel's Page Directory (1 to 1 mapping)
	
	unsigned int curr_page_frame = 0;
	
	// We allocate 4 * 1024 bytes here, whatever the size of
	// the page directory, to make sure that the page tables
	// that are coming next are in page aligned-addresses.
	page_directory = kalloc( 4 * 1024 );
		
	for ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )
	{
		unsigned int *pagetable = kalloc( 4 * PTE_NUM );
		
		for ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )
			pagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );
		
		page_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );
	}

	// ... //
	
	load_page_directory();
	enable_paging();
}

int create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )
{
	int entry = 0;
	
	entry |= present;
	entry |= writable << 1;
	entry |= privilege_level << 2;
	entry |= write_through_cache << 3;
	entry |= cache_enabled << 4;
	entry |= accessed << 5;
	entry |= dirty << 6;
	entry |= page_size << 7;
	
	return base_address | entry;
}




================================================
FILE: src/paging.h
================================================
#define PDE_NUM 3
#define PTE_NUM 1024

extern void load_page_directory();
extern void enable_paging();

unsigned int *page_directory;

void paging_init();
int create_page_entry( int, char, char, char, char, char, char, char, char );


================================================
FILE: src/process.c
================================================
#include "process.h"

void process_init()
{
	processes_count = 0;
	curr_pid = 0;
}

process_t *process_create( int *base_address )
{
	process_t *process = kalloc( sizeof( process_t ) );
	
	process->pid = curr_pid++;
	
	process->context.eax = 0;
	process->context.ecx = 0;
	process->context.edx = 0;
	process->context.ebx = 0;
	process->context.esp = 0;
	process->context.ebp = 0;
	process->context.esi = 0;
	process->context.edi = 0;
	process->context.eip = base_address;
	
	process->state = READY;
	process->base_address = base_address;
	
	processes[ process->pid ] = process;
	
	processes_count++;
	
	return process;
}




================================================
FILE: src/process.h
================================================
typedef enum process_state { READY, RUNNING } process_state_t;

typedef struct process_context
{
	int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;
} process_context_t;

typedef struct process
{
	int pid;
	process_context_t context;
	process_state_t state;
	int *base_address;
} process_t;

process_t *processes[ 15 ]; // TODO: Dynamic
int processes_count, curr_pid;

void process_init();
process_t *process_create( int * );


================================================
FILE: src/scheduler.c
================================================
#include "scheduler.h"

void scheduler_init()
{
	next_sch_pid = 0;
	curr_sch_pid = 0;
}

process_t *get_next_process()
{
	process_t *next_process = processes[ next_sch_pid ];
	
	curr_sch_pid = next_sch_pid;
	next_sch_pid++;
	next_sch_pid = next_sch_pid % processes_count;
	
	return next_process;
}

void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )
{
	process_t *curr_process;
	
	print( " EAX = " );
	printi( eax );

	curr_process = processes[ curr_sch_pid ];
	next_process = get_next_process();
		
	// Copy Current Process Context to The Memory
	if ( curr_process->state == RUNNING )
	{
		curr_process->context.eax = eax;
		curr_process->context.ecx = ecx;
		curr_process->context.edx = edx;
		curr_process->context.ebx = ebx;
		curr_process->context.esp = esp;
		curr_process->context.ebp = ebp;
		curr_process->context.esi = esi;
		curr_process->context.edi = edi;
		curr_process->context.eip = eip;
	}
	
	curr_process->state = READY;
	
	// ... //
	
	// Copy Next Process Context to The Processor
	// TODO: In Memory-Management Version. Copy ESP and EBP
	asm( "	mov %0, %%eax;	\
			mov %0, %%ecx;	\
			mov %0, %%edx;	\
			mov %0, %%ebx;	\
			mov %0, %%esi;	\
			mov %0, %%edi;" 
			: : "r" ( next_process->context.eax ), "r" ( next_process->context.ecx ), "r" ( next_process->context.edx ), "r" ( next_process->context.ebx ),
				"r" ( next_process->context.esi ), "r" ( next_process->context.edi ) );
	
	next_process->state = RUNNING;
}

void run_next_process()
{
	// No code should reside here at all. Otherwise,
	// we will not be sure that the context of the process
	// to run will be correct.
	
	asm( "	sti;			\
	 		jmp *%0" : : "r" ( next_process->context.eip ) );
}


================================================
FILE: src/scheduler.h
================================================
#include "process.h"

int next_sch_pid, curr_sch_pid;

process_t *next_process;

void scheduler_init();
process_t *get_next_process();
void scheduler( int, int, int, int, int, int, int, int, int );
void run_next_process();


================================================
FILE: src/screen.c
================================================
#include "screen.h"

void screen_init()
{
	// VGA Text Mode = 0xB8000
	// VGA Graphics Mode = 0xA0000
	video = 0xB8000;
	nextTextPos = 0;
	currLine = 0;
}

void print( char *str )
{
	int currCharLocationInVidMem, currColorLocationInVidMem;
	
	while ( *str != '\0' )
	{
		currCharLocationInVidMem = nextTextPos * 2;
		currColorLocationInVidMem = currCharLocationInVidMem + 1;
		
		video[ currCharLocationInVidMem ] = *str;
		video[ currColorLocationInVidMem ] = 15;
		
		nextTextPos++;
		
		str++;
	}
}

void println()
{
	if ( currLine > 23 )
	{
		cls();
		return;
	}
	
	nextTextPos = ++currLine * 80;
}

void printi( int number )
{
	char* digitToStr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
	
	if ( number >= 0 && number <= 9 )
	{
		print( digitToStr[ number ] );
		return;
	}
	else
	{
		int remaining = number % 10;
		number = number / 10;
		
		printi( number );
		printi( remaining );
	}
}

void cls()
{
	for ( int currPos = 0; currPos < 3999; currPos = currPos + 2 )
	{
		video[ currPos ] = 0;
		video[ currPos + 1 ] = 0;
	}
	
	nextTextPos = 0;
	currLine = 0;
	
}



================================================
FILE: src/screen.h
================================================
volatile unsigned char *video;

int nextTextPos;
int currLine;

void screen_init();
void print( char * );
void println();
void printi( int );
void cls();


================================================
FILE: src/simple_kernel.asm
================================================
start:
	mov ax, cs
	mov ds, ax
	
	; --- ;
	
	mov si, hello_string
	call print_string
	
	jmp $

print_string:
	mov ah, 0Eh

print_char:
	lodsb
	
	cmp al, 0
	je done
	
	int 10h
	
	jmp print_char

done:
	ret
	
hello_string db 'Hello World!, From Simple Assembly 539kernel!', 0


================================================
FILE: src/starter.asm
================================================
bits 16
extern kernel_main
extern interrupt_handler
extern scheduler
extern run_next_process
extern page_directory

global load_page_directory
global enable_paging

global dev_write
global dev_write_word
global dev_read

start:
	mov ax, cs
	mov ds, ax
		
	; --- ;
	
	call load_gdt
	call init_video_mode
	call enter_protected_mode
	call setup_interrupts
	call load_task_register
	
	; --- ;
	
	call 08h:start_kernel
	
load_gdt:
	cli
	lgdt [gdtr - start]
	
	ret
	
setup_interrupts:
	call remap_pic
	call load_idt
	
	ret
	
init_video_mode:
	;; Set Video Mode
	mov ah, 0h
	mov al, 03h ; 03h For Text Mode. 13h For Graphics Mode.
	int 10h
	
	;; Disable Text Cursor
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	ret

enter_protected_mode:
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	ret
	
remap_pic:
	mov al, 11h
	
	send_init_cmd_to_pic_master: 	
		out 0x20, al
		
	send_init_cmd_to_pic_slave: 	
		out 0xa0, al
		
	; ... ;
	
	make_irq_starts_from_intr_32_in_pic_master:		
		mov al, 32d
		out 0x21, al
	
	make_irq_starts_from_intr_40_in_pic_slave:
		mov al, 40d
		out 0xa1, al 
	
	; ... ;
	
	tell_pic_master_where_pic_slave_is_connected:
		mov al, 04h
		out 0x21, al
	
	tell_pic_slave_where_pic_master_is_connected:
		mov al, 02h
		out 0xa1, al
	
	; ... ;
	
	mov al, 01h
	
	tell_pic_master_the_arch_is_x86:
		out 0x21, al
	
	tell_pic_slave_the_arch_is_x86:
		out 0xa1, al
	
	; ... ;
	
	mov al, 0h
	
	make_pic_master_enables_all_irqs:
		out 0x21, al
	
	make_pic_slave_enables_all_irqs:
		out 0xa1, al
	
	; ... ;
	
	ret

load_idt:
	lidt [idtr - start]
	ret
	
load_task_register:
	mov ax, 40d
	ltr ax
	
	ret
	
bits 32
load_page_directory:
	mov eax, [page_directory]
	mov cr3, eax
	
	ret
	
enable_paging:
	mov eax, cr0
	or eax, 80000000h
	mov cr0, eax
	
	ret
	
; --- ;

; dev_write( int port, int cmd );
dev_write:
	push edx
	push eax
	
	xor edx, edx
	xor eax, eax
	
	mov dx, [esp + 12]
	mov al, [esp + 16]
	
	out dx, al 
	
	pop eax
	pop edx
	
	ret
	
dev_write_word:
	push edx
	push eax
	
	xor edx, edx
	xor eax, eax
	
	mov dx, [esp + 12]
	mov ax, [esp + 16]
	
	out dx, ax 
	
	pop eax
	pop edx
	
	ret

; dev_read( int port );
dev_read:
	push edx
	
	xor edx, edx
	xor eax, eax
	
	mov dx, [esp + 8]
	
	in ax, dx
	
	;jmp $
	
	pop edx
	
	ret

start_kernel:
	mov eax, 10h
	mov ds, eax
	mov ss, eax
	mov es, eax
	
	mov eax, 0h
	mov fs, eax
	mov gs, eax
	
	;sti ; TODO: I think we need to enable it. Does the multitasking work? 13 Nov 2022. Check if we enabled interrupts elsewhere?
	
	call kernel_main
	
%include "gdt.asm"
%include "idt.asm"

tss:
	dd 0


================================================
FILE: src/str.c
================================================
#include "str.h"

void strcpy( char *dest, char *src )
{
	int idx = 0;
	
	while ( *src != '\0' )
	{
		dest[ idx ] = *src;
		
		src++;
		idx++;
	}
}

int strcmp( char *str1, char *str2 )
{
	while ( *str1 != '\0' )
	{
		if ( *str1 != *str2 )
			return 0;
		
		str1++;
		str2++;
	}
	
	if ( *str2 != '\0' )
		return 0;
	
	return 1;
}


================================================
FILE: src/str.h
================================================
void strcpy( char *, char * );
int strcmp( char *, char * );
Download .txt
gitextract_ir_g73hk/

├── README.md
├── evolution_by_versions/
│   ├── .gitignore
│   ├── 01_539kernel_bootloader/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   └── simple_kernel.asm
│   ├── 03_539kernel_progenitor/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   └── starter.asm
│   ├── 04_539kernel_version_t/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   ├── process.c
│   │   ├── process.h
│   │   ├── scheduler.c
│   │   ├── scheduler.h
│   │   ├── screen.c
│   │   ├── screen.h
│   │   └── starter.asm
│   ├── 05_539kernel_version_g/
│   │   ├── Makefile
│   │   ├── bootstrap.asm
│   │   ├── gdt.asm
│   │   ├── heap.c
│   │   ├── heap.h
│   │   ├── idt.asm
│   │   ├── linker.ld
│   │   ├── main.c
│   │   ├── paging.c
│   │   ├── paging.h
│   │   ├── process.c
│   │   ├── process.h
│   │   ├── scheduler.c
│   │   ├── scheduler.h
│   │   ├── screen.c
│   │   ├── screen.h
│   │   └── starter.asm
│   └── 06_539kernel_version_ne/
│       ├── Makefile
│       ├── ata.c
│       ├── ata.h
│       ├── bochs
│       ├── bootstrap.asm
│       ├── filesystem.c
│       ├── filesystem.h
│       ├── gdt.asm
│       ├── heap.c
│       ├── heap.h
│       ├── idt.asm
│       ├── linker.ld
│       ├── main.c
│       ├── paging.c
│       ├── paging.h
│       ├── process.c
│       ├── process.h
│       ├── scheduler.c
│       ├── scheduler.h
│       ├── screen.c
│       ├── screen.h
│       ├── starter.asm
│       ├── str.c
│       └── str.h
└── src/
    ├── .gitignore
    ├── Makefile
    ├── README
    ├── ata.c
    ├── ata.h
    ├── bochs
    ├── bootstrap.asm
    ├── filesystem.c
    ├── filesystem.h
    ├── gdt.asm
    ├── heap.c
    ├── heap.h
    ├── idt.asm
    ├── linker.ld
    ├── main.c
    ├── paging.c
    ├── paging.h
    ├── process.c
    ├── process.h
    ├── scheduler.c
    ├── scheduler.h
    ├── screen.c
    ├── screen.h
    ├── simple_kernel.asm
    ├── starter.asm
    ├── str.c
    └── str.h
Download .txt
SYMBOL INDEX (126 symbols across 35 files)

FILE: evolution_by_versions/03_539kernel_progenitor/main.c
  function kernel_main (line 10) | void kernel_main()
  function interrupt_handler (line 22) | void interrupt_handler( int interrupt_number )
  function print (line 29) | void print( char *str )
  function println (line 47) | void println()
  function printi (line 52) | void printi( int number )

FILE: evolution_by_versions/04_539kernel_version_t/main.c
  function kernel_main (line 9) | void kernel_main()
  function interrupt_handler (line 32) | void interrupt_handler( int interrupt_number )
  function processA (line 39) | void processA()
  function processB (line 47) | void processB()
  function processC (line 55) | void processC()
  function processD (line 63) | void processD()

FILE: evolution_by_versions/04_539kernel_version_t/process.c
  function process_init (line 3) | void process_init()
  function process_create (line 9) | void process_create( int *base_address, process_t *process )

FILE: evolution_by_versions/04_539kernel_version_t/process.h
  type process_state_t (line 1) | typedef enum process_state { READY, RUNNING } process_state_t;
  type process_context_t (line 3) | typedef struct process_context
  type process_t (line 8) | typedef struct process

FILE: evolution_by_versions/04_539kernel_version_t/scheduler.c
  function scheduler_init (line 3) | void scheduler_init()
  function process_t (line 9) | process_t *get_next_process()
  function scheduler (line 20) | void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, in...
  function run_next_process (line 69) | void run_next_process()

FILE: evolution_by_versions/04_539kernel_version_t/screen.c
  function screen_init (line 3) | void screen_init()
  function print (line 10) | void print( char *str )
  function println (line 28) | void println()
  function printi (line 33) | void printi( int number )

FILE: evolution_by_versions/05_539kernel_version_g/heap.c
  function heap_init (line 3) | void heap_init()
  function kalloc (line 8) | int kalloc( int bytes )

FILE: evolution_by_versions/05_539kernel_version_g/main.c
  function kernel_main (line 10) | void kernel_main()
  function interrupt_handler (line 33) | void interrupt_handler( int interrupt_number )
  function processA (line 40) | void processA()
  function processB (line 48) | void processB()
  function processC (line 56) | void processC()
  function processD (line 64) | void processD()

FILE: evolution_by_versions/05_539kernel_version_g/paging.c
  function create_page_entry (line 3) | int create_page_entry( int base_address, char present, char writable, ch...
  function paging_init (line 19) | void paging_init()

FILE: evolution_by_versions/05_539kernel_version_g/process.c
  function process_init (line 3) | void process_init()
  function process_t (line 9) | process_t *process_create( int *base_address )

FILE: evolution_by_versions/05_539kernel_version_g/process.h
  type process_state_t (line 1) | typedef enum process_state { READY, RUNNING } process_state_t;
  type process_context_t (line 3) | typedef struct process_context
  type process_t (line 8) | typedef struct process

FILE: evolution_by_versions/05_539kernel_version_g/scheduler.c
  function scheduler_init (line 3) | void scheduler_init()
  function process_t (line 9) | process_t *get_next_process()
  function scheduler (line 20) | void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, in...
  function run_next_process (line 69) | void run_next_process()

FILE: evolution_by_versions/05_539kernel_version_g/screen.c
  function screen_init (line 3) | void screen_init()
  function print (line 10) | void print( char *str )
  function println (line 28) | void println()
  function printi (line 33) | void printi( int number )

FILE: evolution_by_versions/06_539kernel_version_ne/ata.c
  function wait_drive_until_ready (line 3) | void wait_drive_until_ready()
  function write_disk_chs (line 64) | void write_disk_chs( int sector, short *buffer )
  function write_disk (line 81) | void write_disk( int address, short *buffer )

FILE: evolution_by_versions/06_539kernel_version_ne/filesystem.c
  function filesystem_init (line 3) | void filesystem_init()
  function create_file (line 8) | void create_file( char *filename, char *buffer )
  function delete_file (line 93) | void delete_file( char *filename )
  function update_base_block (line 136) | void update_base_block( int new_head, int new_tail )
  function metadata_t (line 144) | metadata_t *load_metadata( int address )
  function get_address_by_filename (line 151) | int get_address_by_filename( char *filename )
  function get_prev_file_address (line 173) | int get_prev_file_address( int address )
  function get_files_number (line 190) | int get_files_number()

FILE: evolution_by_versions/06_539kernel_version_ne/filesystem.h
  type base_block_t (line 4) | typedef struct
  type metadata_t (line 9) | typedef struct

FILE: evolution_by_versions/06_539kernel_version_ne/heap.c
  function heap_init (line 3) | void heap_init()
  function kalloc (line 8) | int kalloc( int bytes )

FILE: evolution_by_versions/06_539kernel_version_ne/main.c
  function kernel_main (line 12) | void kernel_main()
  function print_fs (line 68) | void print_fs()
  function interrupt_handler (line 83) | void interrupt_handler( int interrupt_number )
  function processA (line 90) | void processA()
  function processB (line 98) | void processB()
  function processC (line 106) | void processC()
  function processD (line 114) | void processD()

FILE: evolution_by_versions/06_539kernel_version_ne/paging.c
  function create_page_entry (line 3) | int create_page_entry( int base_address, char present, char writable, ch...
  function paging_init (line 19) | void paging_init()

FILE: evolution_by_versions/06_539kernel_version_ne/process.c
  function process_init (line 3) | void process_init()
  function process_t (line 9) | process_t *process_create( int *base_address )

FILE: evolution_by_versions/06_539kernel_version_ne/process.h
  type process_state_t (line 1) | typedef enum process_state { READY, RUNNING } process_state_t;
  type process_context_t (line 3) | typedef struct process_context
  type process_t (line 8) | typedef struct process

FILE: evolution_by_versions/06_539kernel_version_ne/scheduler.c
  function scheduler_init (line 3) | void scheduler_init()
  function process_t (line 9) | process_t *get_next_process()
  function scheduler (line 20) | void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, in...
  function run_next_process (line 69) | void run_next_process()

FILE: evolution_by_versions/06_539kernel_version_ne/screen.c
  function screen_init (line 3) | void screen_init()
  function print (line 10) | void print( char *str )
  function println (line 28) | void println()
  function printi (line 33) | void printi( int number )

FILE: evolution_by_versions/06_539kernel_version_ne/str.c
  function strcpy (line 3) | void strcpy( char *dest, char *src )
  function strcmp (line 16) | int strcmp( char *str1, char *str2 )

FILE: src/ata.c
  function wait_drive_until_ready (line 3) | void wait_drive_until_ready()
  function write_disk (line 38) | void write_disk( int address, short *buffer )
  function write_disk_chs (line 79) | void write_disk_chs( int sector, short *buffer )

FILE: src/filesystem.c
  function filesystem_init (line 3) | void filesystem_init()
  function update_base_block (line 8) | void update_base_block( int new_head, int new_tail )
  function metadata_t (line 16) | metadata_t *load_metadata( int address )
  function get_files_number (line 23) | int get_files_number()
  function create_file (line 47) | void create_file( char *filename, char *buffer )
  function get_address_by_filename (line 115) | int get_address_by_filename( char *filename )
  function get_prev_file_address (line 151) | int get_prev_file_address( int address )
  function delete_file (line 168) | void delete_file( char *filename )

FILE: src/filesystem.h
  type base_block_t (line 4) | typedef struct
  type metadata_t (line 9) | typedef struct

FILE: src/heap.c
  function heap_init (line 3) | void heap_init()
  function kalloc (line 8) | int kalloc( int bytes )

FILE: src/main.c
  function print_fs (line 14) | void print_fs()
  function kernel_main (line 29) | void kernel_main()
  function interrupt_handler (line 156) | void interrupt_handler( int interrupt_number )
  function processA (line 163) | void processA()
  function processB (line 171) | void processB()
  function processC (line 179) | void processC()
  function processD (line 187) | void processD()

FILE: src/paging.c
  function paging_init (line 3) | void paging_init()
  function create_page_entry (line 30) | int create_page_entry( int base_address, char present, char writable, ch...

FILE: src/process.c
  function process_init (line 3) | void process_init()
  function process_t (line 9) | process_t *process_create( int *base_address )

FILE: src/process.h
  type process_state_t (line 1) | typedef enum process_state { READY, RUNNING } process_state_t;
  type process_context_t (line 3) | typedef struct process_context
  type process_t (line 8) | typedef struct process

FILE: src/scheduler.c
  function scheduler_init (line 3) | void scheduler_init()
  function process_t (line 9) | process_t *get_next_process()
  function scheduler (line 20) | void scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, in...
  function run_next_process (line 62) | void run_next_process()

FILE: src/screen.c
  function screen_init (line 3) | void screen_init()
  function print (line 12) | void print( char *str )
  function println (line 30) | void println()
  function printi (line 41) | void printi( int number )
  function cls (line 60) | void cls()

FILE: src/str.c
  function strcpy (line 3) | void strcpy( char *dest, char *src )
  function strcmp (line 16) | int strcmp( char *str1, char *str2 )
Condensed preview — 93 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (123K chars).
[
  {
    "path": "README.md",
    "chars": 417,
    "preview": "539kernel is a simple x86 32bit educational kernel which has been written especially for the book \"**[A Journey in Creat"
  },
  {
    "path": "evolution_by_versions/.gitignore",
    "chars": 588,
    "preview": "\n# Created by https://www.gitignore.io/api/c\n# Edit at https://www.gitignore.io/?templates=c\n\n### C ###\n# Prerequisites\n"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/Makefile",
    "chars": 346,
    "preview": "ASM = nasm\nBOOTSTRAP_FILE = bootstrap.asm \nKERNEL_FILE = simple_kernel.asm\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(A"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/bootstrap.asm",
    "chars": 972,
    "preview": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_strin"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/simple_kernel.asm",
    "chars": 273,
    "preview": "start:\n\tmov ax, cs\n\tmov ds, ax\n\n\t; --- ;\n\t\n\tmov si, hello_string\n\tcall print_string\n\t\n\tjmp $\n\nprint_string:\n\tmov ah, 0Eh"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/Makefile",
    "chars": 730,
    "preview": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS ="
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/bootstrap.asm",
    "chars": 1266,
    "preview": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_strin"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/gdt.asm",
    "chars": 365,
    "preview": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_des"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/idt.asm",
    "chars": 3680,
    "preview": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcl"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/linker.ld",
    "chars": 362,
    "preview": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/main.c",
    "chars": 1145,
    "preview": "volatile unsigned char *video = 0xB8000;\n\nint nextTextPos = 0;\nint currLine = 0;\n\nvoid print( char * );\nvoid println();\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/starter.asm",
    "chars": 1430,
    "preview": "bits 16\nextern kernel_main\nextern interrupt_handler\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\tcall load_gdt\n\tcall init_video_m"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/Makefile",
    "chars": 913,
    "preview": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS ="
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/bootstrap.asm",
    "chars": 1266,
    "preview": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_strin"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/gdt.asm",
    "chars": 419,
    "preview": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_des"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/idt.asm",
    "chars": 3971,
    "preview": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcl"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/linker.ld",
    "chars": 362,
    "preview": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/main.c",
    "chars": 1039,
    "preview": "#include \"screen.h\"\n#include \"scheduler.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid processD();\n\nvoid ke"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/process.c",
    "chars": 624,
    "preview": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nvoid process_create( int *base"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/process.h",
    "chars": 430,
    "preview": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, "
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/scheduler.c",
    "chars": 1806,
    "preview": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_proce"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/scheduler.h",
    "chars": 223,
    "preview": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/screen.c",
    "chars": 815,
    "preview": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( cha"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/screen.h",
    "chars": 142,
    "preview": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println()"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/starter.asm",
    "chars": 1576,
    "preview": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\n\nstart:\n\tmov ax, cs\n\tmov ds"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/Makefile",
    "chars": 1055,
    "preview": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKE"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/bootstrap.asm",
    "chars": 1266,
    "preview": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_strin"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/gdt.asm",
    "chars": 419,
    "preview": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_des"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/heap.c",
    "chars": 191,
    "preview": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\tunsigned int new_object_addre"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/heap.h",
    "chars": 62,
    "preview": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/idt.asm",
    "chars": 3971,
    "preview": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcl"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/linker.ld",
    "chars": 362,
    "preview": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/main.c",
    "chars": 1030,
    "preview": "#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"heap.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid pr"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/paging.c",
    "chars": 1053,
    "preview": "#include \"paging.h\"\n\nint create_page_entry( int base_address, char present, char writable, char privilege_level, char ca"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/paging.h",
    "chars": 234,
    "preview": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *p"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/process.c",
    "chars": 662,
    "preview": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nprocess_t *process_create( int"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/process.h",
    "chars": 423,
    "preview": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, "
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/scheduler.c",
    "chars": 1806,
    "preview": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_proce"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/scheduler.h",
    "chars": 223,
    "preview": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/screen.c",
    "chars": 815,
    "preview": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( cha"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/screen.h",
    "chars": 142,
    "preview": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println()"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/starter.asm",
    "chars": 1789,
    "preview": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglob"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/Makefile",
    "chars": 1248,
    "preview": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKE"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/ata.c",
    "chars": 2287,
    "preview": "#include \"ata.h\"\n\nvoid wait_drive_until_ready()\n{\n\tint status = 0;\n\t\n\tdo\n\t{\n\t\tstatus = dev_read( BASE_PORT + 7 );\n\t} whi"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/ata.h",
    "chars": 204,
    "preview": "#define BASE_PORT 0x1F0\n#define SECTOR_SIZE 512\n\nvoid wait_drive_until_ready();\n\nvoid *read_disk( int );\nvoid write_disk"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/bochs",
    "chars": 1064,
    "preview": "plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1\nconfig_interface"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/bootstrap.asm",
    "chars": 1266,
    "preview": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_strin"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/filesystem.c",
    "chars": 4023,
    "preview": "#include \"filesystem.h\"\n\nvoid filesystem_init()\n{\n\tbase_block = read_disk( BASE_BLOCK_ADDRESS );\n}\n\nvoid create_file( ch"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/filesystem.h",
    "chars": 492,
    "preview": "#define BASE_BLOCK_ADDRESS 100\n#define FILENAME_LENGTH 256\n\ntypedef struct\n{\n\tint head, tail;\n} base_block_t;\n\ntypedef s"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/gdt.asm",
    "chars": 419,
    "preview": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_des"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/heap.c",
    "chars": 191,
    "preview": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\tunsigned int new_object_addre"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/heap.h",
    "chars": 62,
    "preview": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/idt.asm",
    "chars": 3971,
    "preview": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcl"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/linker.ld",
    "chars": 362,
    "preview": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/main.c",
    "chars": 1946,
    "preview": "#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"heap.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid pr"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/paging.c",
    "chars": 1053,
    "preview": "#include \"paging.h\"\n\nint create_page_entry( int base_address, char present, char writable, char privilege_level, char ca"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/paging.h",
    "chars": 234,
    "preview": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *p"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/process.c",
    "chars": 662,
    "preview": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nprocess_t *process_create( int"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/process.h",
    "chars": 423,
    "preview": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, "
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/scheduler.c",
    "chars": 1806,
    "preview": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_proce"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/scheduler.h",
    "chars": 223,
    "preview": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/screen.c",
    "chars": 815,
    "preview": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( cha"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/screen.h",
    "chars": 142,
    "preview": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println()"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/starter.asm",
    "chars": 2320,
    "preview": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglob"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/str.c",
    "chars": 330,
    "preview": "#include \"str.h\"\n\nvoid strcpy( char *dest, char *src )\n{\n\tint idx = 0;\n\t\n\twhile ( *src != '\\0' )\n\t{\n\t\tdest[ idx ] = *src"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/str.h",
    "chars": 61,
    "preview": "void strcpy( char *, char * );\nint strcmp( char *, char * );\n"
  },
  {
    "path": "src/.gitignore",
    "chars": 588,
    "preview": "\n# Created by https://www.gitignore.io/api/c\n# Edit at https://www.gitignore.io/?templates=c\n\n### C ###\n# Prerequisites\n"
  },
  {
    "path": "src/Makefile",
    "chars": 4116,
    "preview": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKE"
  },
  {
    "path": "src/README",
    "chars": 131,
    "preview": "[MQH] 25 Nov 2019\nHere is the final code of 539kernel. Any incremental steps, examples and excercises can be found in .."
  },
  {
    "path": "src/ata.c",
    "chars": 2787,
    "preview": "#include \"ata.h\"\n\nvoid wait_drive_until_ready()\n{\n\tint status = 0;\n\t\n\tdo\n\t{\n\t\tstatus = dev_read( BASE_PORT + 7 );\n\t} whi"
  },
  {
    "path": "src/ata.h",
    "chars": 204,
    "preview": "#define BASE_PORT 0x1F0\n#define SECTOR_SIZE 512\n\nvoid wait_drive_until_ready();\n\nvoid *read_disk( int );\nvoid write_disk"
  },
  {
    "path": "src/bochs",
    "chars": 1813,
    "preview": "# configuration file generated by Bochs\nplugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1"
  },
  {
    "path": "src/bootstrap.asm",
    "chars": 7745,
    "preview": "start:\n\t; [MQH] 3 Sep 2019\n\t; When a the boot sector is loaded by BIOS. It will be loaded on the location 07C0h in the m"
  },
  {
    "path": "src/filesystem.c",
    "chars": 3949,
    "preview": "#include \"filesystem.h\"\n\nvoid filesystem_init()\n{\n\tbase_block = read_disk( BASE_BLOCK_ADDRESS );\n}\n\nvoid update_base_blo"
  },
  {
    "path": "src/filesystem.h",
    "chars": 492,
    "preview": "#define BASE_BLOCK_ADDRESS 100\n#define FILENAME_LENGTH 256\n\ntypedef struct\n{\n\tint head, tail;\n} base_block_t;\n\ntypedef s"
  },
  {
    "path": "src/gdt.asm",
    "chars": 613,
    "preview": "; The values of the decriptors from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel)\ngdt:\n\tnull_descript"
  },
  {
    "path": "src/heap.c",
    "chars": 232,
    "preview": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\t// Note: Not necessarily page"
  },
  {
    "path": "src/heap.h",
    "chars": 62,
    "preview": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "src/idt.asm",
    "chars": 4110,
    "preview": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcl"
  },
  {
    "path": "src/linker.ld",
    "chars": 438,
    "preview": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {"
  },
  {
    "path": "src/main.c",
    "chars": 3038,
    "preview": "#include \"heap.h\"\n#include \"paging.h\"\n#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"ata.h\"\n#include \"filesystem.h"
  },
  {
    "path": "src/paging.c",
    "chars": 1238,
    "preview": "#include \"paging.h\"\n\nvoid paging_init()\n{\n\t// Initializing Kernel's Page Directory (1 to 1 mapping)\n\t\n\tunsigned int curr"
  },
  {
    "path": "src/paging.h",
    "chars": 234,
    "preview": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *p"
  },
  {
    "path": "src/process.c",
    "chars": 623,
    "preview": "#include \"process.h\"\n\nvoid process_init()\n{\n\tprocesses_count = 0;\n\tcurr_pid = 0;\n}\n\nprocess_t *process_create( int *base"
  },
  {
    "path": "src/process.h",
    "chars": 424,
    "preview": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n\tint eax, ecx, edx, ebx"
  },
  {
    "path": "src/scheduler.c",
    "chars": 1725,
    "preview": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n\tnext_sch_pid = 0;\n\tcurr_sch_pid = 0;\n}\n\nprocess_t *get_next_process()\n{"
  },
  {
    "path": "src/scheduler.h",
    "chars": 223,
    "preview": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_n"
  },
  {
    "path": "src/screen.c",
    "chars": 1085,
    "preview": "#include \"screen.h\"\n\nvoid screen_init()\n{\n\t// VGA Text Mode = 0xB8000\n\t// VGA Graphics Mode = 0xA0000\n\tvideo = 0xB8000;\n"
  },
  {
    "path": "src/screen.h",
    "chars": 154,
    "preview": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println()"
  },
  {
    "path": "src/simple_kernel.asm",
    "chars": 274,
    "preview": "start:\n\tmov ax, cs\n\tmov ds, ax\n\t\n\t; --- ;\n\t\n\tmov si, hello_string\n\tcall print_string\n\t\n\tjmp $\n\nprint_string:\n\tmov ah, 0E"
  },
  {
    "path": "src/starter.asm",
    "chars": 2528,
    "preview": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglob"
  },
  {
    "path": "src/str.c",
    "chars": 330,
    "preview": "#include \"str.h\"\n\nvoid strcpy( char *dest, char *src )\n{\n\tint idx = 0;\n\t\n\twhile ( *src != '\\0' )\n\t{\n\t\tdest[ idx ] = *src"
  },
  {
    "path": "src/str.h",
    "chars": 61,
    "preview": "void strcpy( char *, char * );\nint strcmp( char *, char * );\n"
  }
]

About this extraction

This page contains the full source code of the MaaSTaaR/539kernel GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 93 files (103.0 KB), approximately 40.9k tokens, and a symbol index with 126 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!