diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8c7ccb5 --- /dev/null +++ b/Makefile @@ -0,0 +1,93 @@ +CXX=clang +LINK=gcc +SOURCEDIR = src +OUTPUTDIR = bin +TESTDIR = test +CFLAGS := -fno-stack-protector -march=i386 -m32 -O0 -g -Iinclude -std=gnu99 -nostdlib -nostdinc -fno-builtin \ + -ffreestanding -Wall +ASMFLAGS = -g -felf +LDFLAGS = -march=i386 -O0 -m32 -ffreestanding -nostdlib -g -T linker.ld +SOURCES_C=$(shell find $(SOURCEDIR) -name \*.c) +SOURCES_ASM=$(shell find $(SOURCEDIR) -name \*.s) +BINARIES_NON=$(SOURCES_C:$(SOURCEDIR)%.c=$(OUTPUTDIR)%.c.o) \ + $(SOURCES_ASM:$(SOURCEDIR)%.s=$(OUTPUTDIR)%.s.o) +FILTER=$(OUTPUTDIR)/arch/boot/boot.s.o +BINARIES=$(filter-out $(FILTER), $(BINARIES_NON)) +FILTER_TEST=$(OUTPUTDIR)/arch/basic/kernel.c.o +BINARIES_TEST=$(filter-out $(FILTER_TEST), $(BINARIES_NON)) +TESTS2 = $(wildcard $(TESTDIR)/test-*.c) +TESTS = $(TESTS2:$(TESTDIR)/%.c=%) + +all: prepare compile + +compile: $(BINARIES_NON) + @echo "Linking kernel..." + @$(LINK) $(LDFLAGS) -o bin/myos.bin \ + $(BINARIES) + @objcopy $(OUTPUTDIR)/myos.bin $(OUTPUTDIR)/myos.sym + +iso: all + @mkdir -p isodir + @mkdir -p isodir/boot + @cp $(OUTPUTDIR)/myos.bin isodir/boot/myos.bin + @cp $(OUTPUTDIR)/myos.bin isodir/efi.img + @mkdir -p isodir/boot/grub + @cp iso/grub.cfg isodir/boot/grub/grub.cfg + @grub-mkrescue -o $(OUTPUTDIR)/myos.iso isodir > /dev/null 2>&1 + +$(OUTPUTDIR)/%.s.o: $(SOURCEDIR)/%.s + @echo "ASM $<" + @mkdir -p $(shell dirname $@) + @nasm $(ASMFLAGS) $< -o $@ + +$(OUTPUTDIR)/%.c.o: $(SOURCEDIR)/%.c + @echo "CC $<" + @mkdir -p $(shell dirname $@) + @$(CXX) $(CFLAGS) -c $< -o $@ + +$(TESTDIR)/%.c.o: $(TESTDIR)/%.c + @echo "CC $<" + @mkdir -p $(shell dirname $@) + @$(CXX) $(CFLAGS) -c $< -o $@ + + +test-%: compile-test-% + @echo "running qemu..." + - @timeout 15 qemu-system-i386 -serial file:log.txt -kernel bin/myos.bin + - @grep "ALL TESTS PASSED" log.txt + +compile-test-%: $(BINARIES_TEST) $(TESTDIR)/test-%.c.o + @echo "Testing $@" + @echo $(BINARIES_TEST) + @echo "Linking kernel..." + @$(CXX) -O0 -ffreestanding -nostdlib -g -T linker.ld -o bin/myos.bin \ + $(filter-out $(OUTPUTDIR)/arch/boot/boot.s.o, $^) + +test: $(TESTS) + +compile-test: $(addprefix compile-, $(TESTS)) + +.PHONY: prepare clean qemu test compile-test + +prepare: + @echo "Preparing output directory..." + @mkdir -p bin + +clean: + @echo "Cleaning output directory..." + @rm -rf bin isodir + @find test -name *.o -delete + +qemu: + @echo "running qemu..." + @qemu-system-i386 -drive file=data.img,index=0,media=disk,if=ide -initrd tools/generator/initrd.img -d cpu_reset -serial stdio -kernel bin/myos.bin 2>&1 | tee log.txt + +qemuquiet: + @echo "running qemu..." + @qemu-system-i386 -hda data.img -nographic -initrd tools/generator/initrd.img -d cpu_reset -serial stdio -kernel bin/myos.bin 2>&1 | tee log.txt + + + +debug: + @echo "running qemu..." + @qemu-system-i386 -hda data.img -gdb tcp::1234 -S -initrd tools/generator/initrd.img -d cpu_reset -serial stdio -kernel bin/myos.bin 2>&1 | tee log.txt diff --git a/README b/README new file mode 100644 index 0000000..5d1f78e --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +Prosty system operacyjny protected mode unixowaty. +Tworzony w celach edukacyjnych, domyślnie ma mieć architekturę mikrokernela. diff --git a/TODOS.txt b/TODOS.txt new file mode 100644 index 0000000..d7156f4 --- /dev/null +++ b/TODOS.txt @@ -0,0 +1 @@ +assert na kfree wywala się ponieważ błędne są markery dla 2. adresu ? diff --git a/bochs.cfg b/bochs.cfg new file mode 100644 index 0000000..9c59cc0 --- /dev/null +++ b/bochs.cfg @@ -0,0 +1,47 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1 +config_interface: textconfig +display_library: x +memory: host=32, guest=32 +romimage: file="/usr/share/bochs/BIOS-bochs-latest" +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: floppy, cdrom +floppy_bootsig_check: disabled=0 +# no floppya +# no floppyb +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=cdrom, path="bin/myos.iso", status=inserted, model="Generic 1234", biosdetect=auto +ata0-slave: type=none +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=0 +ata3: enabled=0 +pci: enabled=1, chipset=i440fx +vga: extension=vbe, update_freq=5 +cpu: count=1:1:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor" +cpuid: mmx=1, apic=xapic, simd=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0 +cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, fma4=0 +cpuid: tbm=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, smep=0, smap=0, mwait=1 +print_timestamps: 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 +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none +mouse: type=ps2, enabled=0, toggle=ctrl+mbutton +speaker: enabled=1, mode=system +parport1: enabled=1, file=none +parport2: enabled=0 +com1: enabled=1, mode=null +com2: enabled=0 +com3: enabled=0 +com4: enabled=0 diff --git a/contributors.txt b/contributors.txt new file mode 100644 index 0000000..de0acb3 --- /dev/null +++ b/contributors.txt @@ -0,0 +1 @@ +Tomasz Półgrabia \ No newline at end of file diff --git a/include/acpi/acpi2.h b/include/acpi/acpi2.h new file mode 100644 index 0000000..cade7d7 --- /dev/null +++ b/include/acpi/acpi2.h @@ -0,0 +1,41 @@ +#ifndef __ACPI2__H +#define __ACPI2__H + +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int dword; + +struct RSDPtr { + byte Signature[8]; + byte CheckSum; + byte OemID[6]; + byte Revision; + dword *RsdtAddress; +}; + +struct FACP { + byte Signature[4]; + dword Length; + byte unneeded1[40 - 0]; + dword *DSDT; + byte unneeded2[48 - 44]; + dword *SMI_CMD; + byte ACPI_ENABLE; + byte ACPI_DISABLE; + byte unneeded3[64 - 54]; + dword *PM1a_CNT_BLK; + dword *PM1b_CNT_BLK; + byte unneeded4[89 - 72]; + byte PM1_CNT_LEN; +}; + +int initAcpi(void); +int acpiEnable(void); +void acpiPowerOff(); + +#endif diff --git a/include/basic.h b/include/basic.h new file mode 100644 index 0000000..d66cf05 --- /dev/null +++ b/include/basic.h @@ -0,0 +1,17 @@ +#ifndef __BASIC_H__ +#define __BASIC_H__ + +#include + +extern void sti(); +extern void cli(); +extern void io_wait(); +extern u32int kernel_start(); +extern u32int kernel_end(); +extern u32int kernel_full_end(); +extern void hlt(); +extern u32int base_pointer(); +extern int interrupt_work(); + + +#endif diff --git a/include/console.h b/include/console.h new file mode 100644 index 0000000..b31f3eb --- /dev/null +++ b/include/console.h @@ -0,0 +1,27 @@ +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ + +#include + +#define VGA_ADDRESS 0xB8000 +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 +#define COLOURS 0x0F +#define PRINTABLE(c) (c >= ' ') + +#include + +extern volatile unsigned short int *scr; +extern int curx,cury; +extern unsigned short int EmptySpace; + +int scroll(); +int putchar(unsigned char c); +int puts(unsigned char *str); +int vga_clear(); +int vga_init(); +int snprintf(char *buffer, int length, char *format,...); +int printf(const char *format, ...) __attribute__((cdecl)); +int log(const char *format,...); + +#endif diff --git a/include/frame.h b/include/frame.h new file mode 100644 index 0000000..99dbe92 --- /dev/null +++ b/include/frame.h @@ -0,0 +1,19 @@ +#ifndef __FRAME_H__ +#define __FRAME_H__ + +#include +#include +#include +#include + +void set_frame(u32int frame_addr); +void clear_frame(u32int frame_addr); +u32int test_frame(u32int frame_addr); +u32int first_frame(); +void alloc_frame(page_t *p, int is_kernel, int is_writable); +void ident_alloc_frame(page_t *p, int is_kernel, int is_writable, u32int addr); +void free_frame(page_t *p); +u32int frames_allocated(); +void dump_frames(); + +#endif diff --git a/include/fs.h b/include/fs.h new file mode 100644 index 0000000..49f025e --- /dev/null +++ b/include/fs.h @@ -0,0 +1,8 @@ +#ifndef __FS_H__ +#define __FS_H__ + +void read_ata_hd(unsigned int chs, unsigned int nr_sectors, unsigned char *buf); +void reset_ata_hd(); +int check_ata_hd(); + +#endif diff --git a/include/fs/initrd.h b/include/fs/initrd.h new file mode 100644 index 0000000..e18e3aa --- /dev/null +++ b/include/fs/initrd.h @@ -0,0 +1,43 @@ +#ifndef __FS_INITRD_H__ +#define __FS_INITRD_H__ + +#include +#include +#include +#define INITRD_NAME_LENGTH 128 +#define INITRD_MAGIC 0xdeadbeaf + + +typedef struct initrd_header { + u32int magic; + char name[INITRD_NAME_LENGTH]; + u32int offset; + u32int length; +} __attribute__ ((aligned (16))) initrd_header_t; + +fs_node_t *initrd_init(u32int addr); + +u32int read_initrd(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer); + +u32int write_initrd(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer); + +void open_initrd(fs_node_t *node, + u8int read, + u8int write); + +void close_initrd(fs_node_t *node); + +struct dirent *readdir_initrd(fs_node_t *node, + u32int index); + +fs_node_t *finddir_initrd(fs_node_t *node, + char *name); + + +#endif diff --git a/include/fs/vfs.h b/include/fs/vfs.h new file mode 100644 index 0000000..56e5c44 --- /dev/null +++ b/include/fs/vfs.h @@ -0,0 +1,85 @@ +#ifndef __FS_VFS__ +#define __FS_VFS__ + +#include +#include + +#define VFS_FILENAME_MAX_LENGTH 128 + +#define FS_FILE 0x01 +#define FS_DIRECTORY 0x02 +#define FS_CHARDEVICE 0x03 +#define FS_BLOCKDEVICE 0x04 +#define FS_PIPE 0x05 +#define FS_SYMLINK 0x06 +#define FS_MOUNTPOINT 0x08 + +struct fs_node; + +typedef u32int (*read_type_t)(struct fs_node *, + u32int, + u32int, + u8int *); + +typedef u32int (*write_type_t)(struct fs_node *, + u32int, + u32int, + u8int *); + +typedef void (*open_type_t)(struct fs_node *); +typedef void (*close_type_t)(struct fs_node *); + +typedef struct dirent *(*readdir_type_t)(struct fs_node *, + u32int); + +typedef struct fs_node *(*finddir_type_t)(struct fs_node *, + char *name); + + + +typedef struct fs_node { + char name[VFS_FILENAME_MAX_LENGTH]; + u32int mask; // permission mask + u32int uid; + u32int gid; + u32int flags; + u32int inode; + u32int length; + u32int impl; // impl defined number + read_type_t read; + write_type_t write; + open_type_t open; + close_type_t close; + readdir_type_t readdir; + finddir_type_t finddir; + struct fs_node *ptr; // used by mountpoints and symlinks +} fs_node_t; + +typedef struct dirent { + char name[VFS_FILENAME_MAX_LENGTH]; + u32int ino; +} dirent_t; + +u32int read_fs(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer); + +u32int write_fs(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer); + +void open_fs(fs_node_t *node, + u8int read, + u8int write); + +void close_fs(fs_node_t *node); + +struct dirent *readdir_fs(fs_node_t *node, + u32int index); + +fs_node_t *finddir_fs(fs_node_t *node, + char *name); + +#endif diff --git a/include/gdt.h b/include/gdt.h new file mode 100644 index 0000000..b39dee0 --- /dev/null +++ b/include/gdt.h @@ -0,0 +1,33 @@ +#ifndef __GDT_H__ +#define __GDT_H__ + +struct gdt_entry { + + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_hight; + +} __attribute__ ((packed)); + +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__ ((packed)); + +extern int gdt_flush(); +extern struct gdt_entry gdt[3]; +extern struct gdt_ptr gp; + +int gdt_set_gate(int num, + unsigned long base, + unsigned long limit, + unsigned char access, + unsigned char gran); + +int gdt_install(); + + +#endif diff --git a/include/generic.h b/include/generic.h new file mode 100644 index 0000000..5f292e1 --- /dev/null +++ b/include/generic.h @@ -0,0 +1,18 @@ +#ifndef __GENERIC_H__ +#define __GENERIC_H__ + +#include + +#define UNUSED(x) (void)(x) +#define NULL (void *)0 + +#define PANIC(x) log("[%s(%s):%d]: ASSERTION '%s' FAILED", __FILE__, __FUNCTION__, __LINE__, x); \ + printf("[%s(%s):%d]: ASSERTION '%s' FAILED", __FILE__, __FUNCTION__, __LINE__, x); for(;;) hlt(); +#define ASSERT(x) do { if (!(x)) { PANIC("ASSERTION FAILED"); } } while(0) +#define INDEX_FROM_BIT(a) (a/(8*4)) +#define OFFSET_FROM_BIT(a) (a%(8*4)) +#define ALIGN_DOWN(x) (x/0x1000)*0x1000 + + + +#endif diff --git a/include/heap.h b/include/heap.h new file mode 100644 index 0000000..8257c77 --- /dev/null +++ b/include/heap.h @@ -0,0 +1,63 @@ +#ifndef __HEAP_H__ +#define __HEAP_H__ + +#include +#include +#include +#include + +#define HEAP_MARKER 0xdeadbeaf +#define MAX_BLOCKS 0x10000 +#define ALIGNMENT_SIZE 0x1000 +#define ALIGN_UP(x) (((x - 1) / ALIGNMENT_SIZE + 1)*ALIGNMENT_SIZE) + +typedef struct block_header { + u32int marker1; + u32int start; + u32int size; // rozmiar z headerem i footerem + u32int id; + unsigned char aligned; + unsigned char kernel; + unsigned char rw; // rw - 1, r - 0 + unsigned char block; // 1 - block, 0 - hole + u32int marker2; +} block_header_t; + +typedef struct block_footer { + u32int marker1; + u32int header; + u32int marker2; +} block_footer_t; + +typedef struct heap { + u32int marker1; + block_header_t *blocks[MAX_BLOCKS]; + u32int max_id; + u32int min_address; + u32int max_address; + u32int limit_max; + u32int marker2; +} heap_t; + +extern heap_t kernel_heap; + +void *kmalloc(u32int size); +void kfree(void *addr); + +void *kmalloc_a(u32int size); + +void init_heap(heap_t *heap, u32int min_address, u32int max_address, + u32int limit_max, u32int kernel, u32int rw); + +void destroy_heap(heap_t *heap); +int sanity_check(heap_t *heap); +void span_items(heap_t *heap); + +void *kalloc_int(u32int size, u32int aligned, u32int kernel, u32int rw, + heap_t *heap); + +void kfree_int(void *addr, heap_t *heap); +void insert_block_array(heap_t *heap, block_header_t *header, u32int max_id); +void dump_heap(heap_t *heap); + +#endif diff --git a/include/idt.h b/include/idt.h new file mode 100644 index 0000000..716ba75 --- /dev/null +++ b/include/idt.h @@ -0,0 +1,28 @@ +#ifndef __IDT_H__ +#define __IDT_H__ + +#include + +struct idt_entry { + unsigned short base_lo; + unsigned short sel; + unsigned char always0; + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +extern int idt_load(); + +int idt_set_gate(unsigned char num, + unsigned long base, + unsigned short sel, + unsigned char flags); + +int idt_install(); + +#endif diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..bff1024 --- /dev/null +++ b/include/io.h @@ -0,0 +1,14 @@ +#ifndef __IO_H__ +#define __IO_H__ + +#include + +extern void outb(u16int port, u8int data); + +extern u8int inb(u16int port); + +extern void outw(u16int port, u16int data); + +extern u16int inw(u16int port); + +#endif diff --git a/include/irq.h b/include/irq.h new file mode 100644 index 0000000..66b21fd --- /dev/null +++ b/include/irq.h @@ -0,0 +1,30 @@ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +#include +#include +#include + +extern void irq0(); +extern void irq1(); +extern void irq2(); +extern void irq3(); +extern void irq4(); +extern void irq5(); +extern void irq6(); +extern void irq7(); +extern void irq8(); +extern void irq9(); +extern void irq10(); +extern void irq11(); +extern void irq12(); +extern void irq13(); +extern void irq14(); +extern void irq15(); + +extern void *irq_routines[16]; + +int irq_install_handler(int irq, int (*handler)(struct regs *r)); +int irq_uninstall_handler(int irq); +int irq_install(); +#endif diff --git a/include/isr.h b/include/isr.h new file mode 100644 index 0000000..19270c8 --- /dev/null +++ b/include/isr.h @@ -0,0 +1,20 @@ +#ifndef __ISR_H__ +#define __ISR_H__ + +#include +#include +#include + +struct regs { + unsigned int gs, fs, es, ds; + unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; + unsigned int int_no, err_code; + unsigned int eip, cs, eflags, useresp, ss; +}; + +typedef struct regs res_t; + + +int isrs_install(); + +#endif diff --git a/include/kbd.h b/include/kbd.h new file mode 100644 index 0000000..ceb06b6 --- /dev/null +++ b/include/kbd.h @@ -0,0 +1,15 @@ +#ifndef __KBD_H__ +#define __KBD_H__ + +#include +#include +#include +#include +#include + +extern unsigned char kbdus[128]; + +int keyboard_handler(struct regs *r); +int kbd_install(); + +#endif diff --git a/include/mem.h b/include/mem.h new file mode 100644 index 0000000..443edd1 --- /dev/null +++ b/include/mem.h @@ -0,0 +1,14 @@ +#ifndef __MEM_H__ +#define __MEM_H__ + +#include +#include +#include + +extern u32int end; +extern void disablePaging(); +extern multiboot_info_t *m; +extern u32int mem_lower; +extern u32int mem_upper; + +#endif diff --git a/include/minunit.h b/include/minunit.h new file mode 100644 index 0000000..eb23305 --- /dev/null +++ b/include/minunit.h @@ -0,0 +1,47 @@ +/* file: minunit.h */ +#define INTERNAL_ERROR "INTERNAL ERROR. CHECK FOR BUFFER LENGTH." +#define TRUNCATED_ERROR "RESULT TRUNCATED. INCREASE TEMP BUFFER LIMIT" + +#define mu_assert(message, test) do { if (!(test)) { \ + if (snprintf(temp, temp_limit, "[%s(%s):%d]: %s\n", __FILE__, \ + __FUNCTION__, __LINE__, message) >= temp_limit) { \ + return TRUNCATED_ERROR; \ + } \ + return(temp); \ + }} while (0) + +#define mu_run_test(test) do { char *message = test(); tests_run++; \ + if (message) { \ + if(!handle(message)) { \ + return INTERNAL_ERROR; \ + } \ + } \ + else tests_succeeded++; } while (0) + + extern char *temp; + extern int temp_limit; + extern int mu_sprintf(char *buffer, int size, const char *fmt, ...); + extern unsigned int limit; + extern char *buffer; + extern unsigned int pos; + extern int tests_run; + extern int tests_succeeded; + + extern int mu_strlen(const char *); + extern void *mu_memcpy(void *, const void*, unsigned int); + + int handle(char *msg) { + unsigned int n = (unsigned int)mu_strlen(msg); + if (pos >= limit) { + return 0; + } + + if (limit-pos < n) { + return 0; + } + + mu_memcpy(buffer+pos, msg, n); + pos += n; + + return 1; + } diff --git a/include/multiboot.h b/include/multiboot.h new file mode 100644 index 0000000..3a46c1f --- /dev/null +++ b/include/multiboot.h @@ -0,0 +1,226 @@ + /* multiboot.h - Multiboot header file. */ + /* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + #define CHECK_FLAG(flags,bit) ((flags) & (1 << bit)) + + #ifndef MULTIBOOT_HEADER + #define MULTIBOOT_HEADER 1 + + /* How many bytes from the start of the file we search for the header. */ + #define MULTIBOOT_SEARCH 8192 + + /* The magic field should contain this. */ + #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + + /* This should be in %eax. */ + #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + + /* The bits in the required part of flags field we don't support. */ + #define MULTIBOOT_UNSUPPORTED 0x0000fffc + + /* Alignment of multiboot modules. */ + #define MULTIBOOT_MOD_ALIGN 0x00001000 + + /* Alignment of the multiboot info structure. */ + #define MULTIBOOT_INFO_ALIGN 0x00000004 + + /* Flags set in the 'flags' member of the multiboot header. */ + + /* Align all boot modules on i386 page (4KB) boundaries. */ + #define MULTIBOOT_PAGE_ALIGN 0x00000001 + + /* Must pass memory information to OS. */ + #define MULTIBOOT_MEMORY_INFO 0x00000002 + + /* Must pass video information to OS. */ + #define MULTIBOOT_VIDEO_MODE 0x00000004 + + /* This flag indicates the use of the address fields in the header. */ + #define MULTIBOOT_AOUT_KLUDGE 0x00010000 + + /* Flags to be set in the 'flags' member of the multiboot info structure. */ + + /* is there basic lower/upper memory information? */ + #define MULTIBOOT_INFO_MEMORY 0x00000001 + /* is there a boot device set? */ + #define MULTIBOOT_INFO_BOOTDEV 0x00000002 + /* is the command-line defined? */ + #define MULTIBOOT_INFO_CMDLINE 0x00000004 + /* are there modules to do something with? */ + #define MULTIBOOT_INFO_MODS 0x00000008 + + /* These next two are mutually exclusive */ + + /* is there a symbol table loaded? */ + #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 + /* is there an ELF section header table? */ + #define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + + /* is there a full memory map? */ + #define MULTIBOOT_INFO_MEM_MAP 0x00000040 + + /* Is there drive info? */ + #define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + + /* Is there a config table? */ + #define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + + /* Is there a boot loader name? */ + #define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + + /* Is there a APM table? */ + #define MULTIBOOT_INFO_APM_TABLE 0x00000400 + + /* Is there video information? */ + #define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 + + #ifndef ASM_FILE + + typedef unsigned short multiboot_uint16_t; + typedef unsigned int multiboot_uint32_t; + typedef unsigned long long multiboot_uint64_t; + + struct multiboot_header + { + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; + }; + + /* The symbol table for a.out. */ + struct multiboot_aout_symbol_table + { + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; + }; + typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + + /* The section header table for ELF. */ + struct multiboot_elf_section_header_table + { + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; + }; + typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + + struct multiboot_info + { + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + }; + typedef struct multiboot_info multiboot_info_t; + + struct multiboot_mmap_entry + { + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; + #define MULTIBOOT_MEMORY_AVAILABLE 1 + #define MULTIBOOT_MEMORY_RESERVED 2 + multiboot_uint32_t type; + } __attribute__((packed)); + typedef struct multiboot_mmap_entry multiboot_memory_map_t; + + struct multiboot_mod_list + { + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; + }; + typedef struct multiboot_mod_list multiboot_module_t; + + #endif /* ! ASM_FILE */ + + #endif /* ! MULTIBOOT_HEADER */ + diff --git a/include/page.h b/include/page.h new file mode 100644 index 0000000..12f647b --- /dev/null +++ b/include/page.h @@ -0,0 +1,36 @@ +#ifndef __PAGE_H__ +#define __PAGE_H__ + +#include + +typedef struct page { + u32int present : 1; // strona jest obecna w pamięci + u32int rw : 1; // odczyt / zapis jeśli 1, inaczej tylko odczyt + u32int user : 1; // user-space jeśli 1, inaczej kernel-space + u32int accessed : 1; // flaga ustawiana przez cpu - czy była użytkowana + u32int dirty : 1; // flaga ustawiana przez cpu - czy była zapisywana + u32int unused : 7; // nieużywane + u32int frame : 20; // adres framki (przesuniętego o 12 bitów) +} page_t; + +typedef struct page_table { + page_t pages[1024]; +} page_table_t; + +typedef struct page_directory { + /** + * Tablica wskaźników do tablic stron. + */ + page_table_t *table[1024]; + /** + * Tablica wskaźników do tablic stron, ale fizycznych lokalizacji + * w celu załadowania ich do rejestru CR3. + */ + u32int tablesPhysical[1024]; + /** + * Fizyczny adres tabliy tablesPhysical. + */ + u32int physicalAddr; +} page_directory_t; + +#endif diff --git a/include/paging.h b/include/paging.h new file mode 100644 index 0000000..3569d12 --- /dev/null +++ b/include/paging.h @@ -0,0 +1,36 @@ +#ifndef __PAGING_H__ +#define __PAGING_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +u32int c_log_phys(u32int logical); +void initialise_paging2(); +void switch_page_directory(page_directory_t *new); +page_t *get_page(u32int address, int make, page_directory_t *dir); +int page_fault(struct regs *r); + +extern page_directory_t *current_directory; +extern page_directory_t *kernel_directory; +u32int* init_paging3(); +extern u32int page_directory[1024] __attribute__((aligned(4096))); +extern u32int first_page_table[1024] __attribute__((aligned(4096))); +extern void loadPageDirectory(unsigned int*); +extern void enablePaging(); +extern void disablePaging2(); +extern void set_cr0(u32int); +extern u32int get_cr0(); +extern void set_cr3(u32int); +extern u32int get_cr3(); + + +#endif diff --git a/include/pit.h b/include/pit.h new file mode 100644 index 0000000..7c2106a --- /dev/null +++ b/include/pit.h @@ -0,0 +1,13 @@ +#ifndef __PIT_H__ +#define __PIT_H__ + +#include +#include +#include +#include + +int timer_phase(int hz); +int timer_handler(struct regs *r); +int timer_install(); +int sleep(double sec); +#endif diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 0000000..c5591bd --- /dev/null +++ b/include/serial.h @@ -0,0 +1,16 @@ +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +#include +#include + +#define PORT 0x3F8 + +void init_serial(); +int serial_received(); +char read_serial(); +int is_transmit_empty(); +void write_serial(char a); +void write_serial_string(char *s); + +#endif diff --git a/include/strings.h b/include/strings.h new file mode 100644 index 0000000..e247ee4 --- /dev/null +++ b/include/strings.h @@ -0,0 +1,25 @@ +#ifndef __STRINGS_H__ +#define __STRINGS_H__ + +#include +#include + +void *memcpy(void *dest, + const void *src, + int count); + +void *memset(void *dest, + unsigned char val, + int count); + +void *memcpy2(void *dest, + const void *src, + int length, + int count); + +u32int memcmp(void *m1, void *m2, u32int l); + +int itoa(void *buf, int base, int d); +void dump(void *, u32int size); + +#endif diff --git a/include/system.h b/include/system.h new file mode 100644 index 0000000..4951391 --- /dev/null +++ b/include/system.h @@ -0,0 +1,23 @@ +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/include/task/copy.h b/include/task/copy.h new file mode 100644 index 0000000..507ca69 --- /dev/null +++ b/include/task/copy.h @@ -0,0 +1,11 @@ +#ifndef __TASK_COPY__ +#define __TASK_COPY__ + +#include +#include +#include + +page_directory_t *clone_directory(page_directory_t *src); +page_table_t *clone_table(page_table_t *src, u32int *phys); + +#endif diff --git a/include/task/fork.h b/include/task/fork.h new file mode 100644 index 0000000..ae1a888 --- /dev/null +++ b/include/task/fork.h @@ -0,0 +1,4 @@ +#ifndef __TASK_FORK__ +#define __TASK_FORK__ + +#endif diff --git a/include/task/process.h b/include/task/process.h new file mode 100644 index 0000000..efec8ab --- /dev/null +++ b/include/task/process.h @@ -0,0 +1,6 @@ +#ifndef __TASK_PROCESS_H__ +#define __TASK_PROCESS_H__ + +void copy_page_physical(u32int src, u32int dest); + +#endif diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..d2977fc --- /dev/null +++ b/include/types.h @@ -0,0 +1,9 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +typedef unsigned int u32int; +typedef unsigned short int u16int; +typedef unsigned char u8int; +typedef unsigned long long int u64int; + +#endif diff --git a/iso/grub.cfg b/iso/grub.cfg new file mode 100644 index 0000000..b2f8404 --- /dev/null +++ b/iso/grub.cfg @@ -0,0 +1,3 @@ +menuentry "myos" { + multiboot /boot/myos.bin +} diff --git a/isodir/boot/grub/grub.cfg b/isodir/boot/grub/grub.cfg new file mode 100644 index 0000000..b2f8404 --- /dev/null +++ b/isodir/boot/grub/grub.cfg @@ -0,0 +1,3 @@ +menuentry "myos" { + multiboot /boot/myos.bin +} diff --git a/isodir/boot/myos.bin b/isodir/boot/myos.bin new file mode 100644 index 0000000..b4f9a92 Binary files /dev/null and b/isodir/boot/myos.bin differ diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..b111d28 --- /dev/null +++ b/linker.ld @@ -0,0 +1,28 @@ +ENTRY(_start) +STARTUP(bin/arch/boot/boot.s.o) + +SECTIONS +{ + . = 1M; + + .text BLOCK(4K) : ALIGN(4K){ + *(.multiboot) + *(.text) + } + .rodata BLOCK(4K) : ALIGN(4K) { + *(.rodata) + } + .data BLOCK(4K) : ALIGN(4K) { + *(.data) + } + .bss BLOCK(4K) : ALIGN(4K) { + *(COMMON) + *(.bss) + } + .note.gnu.build-id BLOCK(4K) : ALIGN(4K) { + *(.note.gnu.build-id) + } + + end = .; _end = .; __end = .; + +} diff --git a/src/arch/acpi/acpi2.c b/src/arch/acpi/acpi2.c new file mode 100644 index 0000000..dceab94 --- /dev/null +++ b/src/arch/acpi/acpi2.c @@ -0,0 +1,240 @@ +#include + +dword *SMI_CMD; +byte ACPI_ENABLE; +byte ACPI_DISABLE; +dword *PM1a_CNT; +dword *PM1b_CNT; +word SLP_TYPa; +word SLP_TYPb; +word SLP_EN; +word SCI_EN; +byte PM1_CNT_LEN; + +// check if the given address has a valid header + +unsigned int *acpiCheckRSDPtr(unsigned int *ptr) { + char *sig = "RSD PTR "; + struct RSDPtr *rsdp = (struct RSDPtr*) ptr; + byte *bptr; + byte check; + int i; + + if (memcmp(sig, rsdp, 8) == 0) { + // check checksum rsdpd + bptr = (byte *) ptr; + for (i = 0; i < sizeof(struct RSDPtr); i++) { + check += *bptr; + bptr++; + } + + // found valid rsdpd + + if (check == 0) { + if (rsdp->Revision == 0) { + log("Acpi 1\n"); + } else { + log("Acpi 2\n"); + } + + return (unsigned int*)rsdp->RsdtAddress; + } + } + return NULL; +} + +unsigned int *acpiGetRSDPtr(void) { + unsigned int *addr; + unsigned int *rsdp; + + // search below the 1mb mark for rsdp signature + + for (addr = (unsigned int *) 0x000E0000; + (int) addr < 0x00100000; + addr += 0x10 / sizeof(addr)) { + rsdp = acpiCheckRSDPtr(addr); + if (rsdp != NULL) { + return rsdp; + } + + } + + // at the address 0x40:0x0E is the RM segment of the ebda + int ebda = *((short *) 0x40e); // get pointer + ebda = ebda * 0x10 & 0x000FFFFF; + // transform segment into the linear address + + // search the extended bios data area for the root + // system description pointer + + for (addr = (unsigned int *)ebda; + (int)addr < ebda + 1024; + addr += 0x10 / sizeof(addr)) { + rsdp = acpiCheckRSDPtr(addr); + if (rsdp != NULL) { + return rsdp; + } + } + + return NULL; +} + +// checks for a given header and validates checksum + +int acpiCheckHeader(unsigned int *ptr, char *sig) { + if (memcmp(ptr, sig, 4) == 0) { + char *checkPtr = (char *) ptr; + int len = *(ptr + 1); + char check = 0; + while (0 < len--) { + check += *checkPtr; + checkPtr++; + } + + if (check == 0) { + return 0; + } + } + + return -1; +} + +int acpiEnable(void) { + // check if acpi is enabled + if ((inw((unsigned int) PM1a_CNT) & SCI_EN) == 0) { + // check if acpi can be enabled + if (SMI_CMD != 0 && ACPI_ENABLE != 0) { + outb((unsigned int)SMI_CMD, ACPI_ENABLE); + // send apci enable command + // give 3 seconds time to enable acpi + int i; + for (i = 0; i < 300; i++) { + if ((inw((unsigned int)PM1a_CNT) & SCI_EN) == 1) { + break; + } + sleep(10); + } + + if (PM1b_CNT != 0) { + for(; i < 300; i++) { + if ((inw((unsigned int)PM1b_CNT) & SCI_EN) == 1) { + break; + } + sleep(10); + } + } + + if (i < 300) { + log("Enabled acpi\n"); + return 0; + } else { + log("Couldn't enable acpi\n"); + return -1; + } + } else { + log("No known way to enable acpi\n"); + return -1; + } + } else { + log("Acpi was alread enabled\n"); + return 0; + } +} + +int initAcpi(void) { + unsigned int *ptr = acpiGetRSDPtr(); + + // check if address is correct (if acpi is available on the pc). + if (ptr != NULL && acpiCheckHeader(ptr, "RSDT") == 0) { + // the RSDT contains an unknown number of pointers to acpi tables + int entrys = *(ptr + 1); + entrys = (entrys - 36) / 4; + ptr += 36 / 4; // skip header information + + while (0 < entrys--) { + // check if the desired table is reached + if (acpiCheckHeader((unsigned int *) *ptr, "FACP") == 0) { + entrys = -2; + struct FACP *facp = (struct FACP *) *ptr; + + if (acpiCheckHeader((unsigned int *) facp->DSDT, "DSDT") == 0) { + // search the \_S5 package in DSDT + char *S5addr = (char *) facp->DSDT + 36; // skip header + int dsdtLength = *(facp->DSDT+1) - 36; + while (0 < dsdtLength--) { + if (memcmp(S5addr, "_S5_", 4) == 0) { + break; + } + S5addr++; + } + + // check if \_S5 was found + + if (dsdtLength > 0) { + // check for valid AML structurei + if ( ( *(S5addr-1) == 0x08 + || ( *(S5addr-2) == 0x08 + && *(S5addr-1) == '\\') ) + && *(S5addr+4) == 0x12 ) { + S5addr += 5; + S5addr += ((*S5addr & 0xC0) >> 6) + 2; + // calculate PkgLength size + if (*S5addr == 0x0A) { + S5addr++; // skip byte prefix + } + + SLP_TYPa = *(S5addr) << 10; + S5addr++; + + if (*S5addr == 0x0A) { + S5addr++; + } + + SLP_TYPb = *(S5addr) << 10; + + SMI_CMD = facp->SMI_CMD; + ACPI_ENABLE = facp->ACPI_ENABLE; + ACPI_DISABLE = facp->ACPI_DISABLE; + + PM1a_CNT = facp->PM1a_CNT_BLK; + PM1b_CNT = facp->PM1b_CNT_BLK; + PM1_CNT_LEN = facp->PM1_CNT_LEN; + + SLP_EN = 1 << 13; + SCI_EN = 1; + + return 0; + } else { + log("\\_S5 parse error\n"); + } + + } else { + log("\\_S5 parse error\n"); + } + } else { + log("DSDT invalid\n"); + } + } + ptr++; + } + log("no valid FACP present\n"); + } else { + log("No acpi\n"); + } + return -1; +} + +void acpiPowerOff(void) { + // SCI_EN is set to 1 if acpi shutdown is possible + if (SCI_EN == 0) { + return; + } + + // send the shutdown command + outw((unsigned int) PM1a_CNT, SLP_TYPa | SLP_EN); + if (PM1b_CNT != 0) { + outw((unsigned int) PM1b_CNT, SLP_TYPb | SLP_EN); + } + + log("acpi poweroff failed\n"); +} diff --git a/src/arch/asm/basic.s b/src/arch/asm/basic.s new file mode 100644 index 0000000..c88d2c4 --- /dev/null +++ b/src/arch/asm/basic.s @@ -0,0 +1,213 @@ +section .text + +extern gp +extern idtp + +global outb +global outw +global inb +global inw +global gdt_flush +global idt_load +global sti +global cli +global io_wait +global disablePic +global remap + +global kernel_start +global kernel_end +global kernel_full_end +global crash +global hlt +global disablePaging +global shutdown +global base_pointer +global interrupt_work + +extern _start +extern stack +extern stack_end + +outb: + push ebp + mov ebp, esp + + push edx + push eax + + mov dx, [ebp+8] ; port + mov al, [ebp+12] ; dane ; TODO gcc zwyczajnie unsigned short zaokrągla do 4 + ; dlaczego to robi, nie wiem ??? + out dx, al + + pop eax + pop edx + + pop ebp + ret + +outw: + push ebp + mov ebp, esp + + push edx + push eax + + mov dx, [ebp+8] + mov ax, [ebp+12] + + out dx, ax + + pop eax + pop edx + + pop ebp + ret + +inb: + push ebp + mov ebp, esp + + push edx + + mov dx, [ebp+8] ; port + xor eax,eax + + in al, dx + + pop edx + + pop ebp + ret + +inw: + push ebp + mov ebp, esp + + push edx + + mov dx, [ebp+8] ; port + xor eax,eax + + in ax, dx + + pop edx + + pop ebp + ret + + +gdt_flush: + lgdt [gp] + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:gdt_flush2 + +gdt_flush2: + ret + +idt_load: + lidt [idtp] + ret + +sti: + sti + ret + +cli: + cli + ret + +io_wait: + jmp wait1 +wait1: + jmp wait2 +wait2: + ret + +disablePic: + mov al, 0xff + out 0xa1, al + out 0x21, al + ret + +remap: + mov al, 0x11 + out 0x20, al ;restart PIC1 + out 0xA0, al ;restart PIC2 + + mov al, 0x20 + out 0x21, al ;PIC1 now starts at 32 + mov al, 0x28 + out 0xA1, al ;PIC2 now starts at 40 + + mov al, 0x04 + out 0x21, al ;setup cascading + mov al, 0x02 + out 0xA1, al + + mov al, 0x01 + out 0x21, al + out 0xA1, al ;done! + ret + +kernel_start: + mov eax, _start + ret +kernel_end: + mov eax, stack + ret +kernel_full_end: + mov eax, stack_end + ret + +crash: + int 14 + ret + +hlt: + hlt + ret + +disablePaging: + push ebp + mov ebp, esp + + push eax + push ebx + + mov eax, cr0 + mov ebx, 0x80000000 + not ebx + and eax, ebx + mov cr0, eax + + pop ebx + pop eax + + pop ebp + + ret + +shutdown: + mov al, 0x20 + mov dx, 0xb004 + out dx, al + xor eax, eax + out dx, al + ret + +base_pointer: + mov eax, ebp + ret + +interrupt_work: + mov eax, 1 + mov ebx, 2 + int 81 + ret diff --git a/src/arch/asm/fs.s b/src/arch/asm/fs.s new file mode 100644 index 0000000..c77c26e --- /dev/null +++ b/src/arch/asm/fs.s @@ -0,0 +1,135 @@ +global read_ata_hd +global reset_ata_hd +global check_ata_hd + +COMMAND_REG equ 1f7h +STATUS_REG equ 1f7h + +check_ata_hd: + push ebp + mov ebp, esp + push edx + + mov dx, STATUS_REG + xor eax, eax + in al, dx + + pop edx + pop ebp + ret + +read_ata_hd: + push ebp + mov ebp, esp + + push eax + push ebx + push ecx + push edx + push edi + + mov ebx, [ebp+8] ; the chs values + mov ecx, [ebp+12] ; the 16-bit number of sectors to read max 65536 + mov edi, [ebp+16] ; the address of buffer to put data obtained + + mov edx, 1f6h ; port to send drive & head numbers + mov al, bh ; head index in bh + and al, 00001111b ; head is only 4 bit long + or al, 10100000b ; default 1010b in high nibble + out dx, al + + mov edx, 1f2h ; sector count port + mov al, cl ; read ch sectors + out dx, al + + mov edx, 1f3h ; sector number port + mov al, bl ; bl is a sector index + out dx, al + + mov edx, 1f4h ; cylinder low port + mov eax, ebx ; byte 2 in ebx, just above bh + mov cl, 16 + shr eax, cl ; shift down to al + out dx, al + + mov edx, 1f5h ; cylinder high port + mov eax, ebx ; byte 3 in ebx, just above byte 2 + mov cl, 24 + shr eax, cl ; shift down to al + out dx, al + + mov edx, 1f7h ; command port + mov al, 20h ; read with retry + out dx, al + + .still_going: + in al, dx + test al, 8 ; the sector buffer requires servicing + jz .still_going ; until the sector buffer is ready + + mov eax, 256 ; to read 512/2 = 256 words = 1 sector + xor bx, bx + mov bl, ch ; read ch sectors + mul bx + mov ecx, eax ; ecx is a counter for insw + mov edx, 1f8h ; data port, in and out + rep insw ; in to [rdi] + + pop edi + pop edx + pop ecx + pop ebx + pop eax + + pop ebp + ret + +wait_ready: + mov edx, 17fh ; status/command register + xor eax, eax +.poll_status: + in al, dx + test al, 64 ; ready flag + jz .poll_status ; waiting for ready status + + ret + +reset_ata_hd: + push ebp + mov ebp, esp + + cli + + mov edx, 17fh + mov al, 0ech ; identify command + out dx, al + + call wait_ready + + xor eax, eax + in al, dx + + mov edx, 1f7h ; command port + xor eax, eax + in al, dx + + mov edx, 1f6h ; port to send drive & head numbers + mov al, 0 + out dx, al + + call wait_ready + + mov edx, 1f7h ; command port + mov al, 08h + out dx, al + + xor eax, eax + in al, dx + + xor eax, eax + in al, dx + + sti + + pop ebp + ret diff --git a/src/arch/asm/irq.s b/src/arch/asm/irq.s new file mode 100644 index 0000000..dd76cd0 --- /dev/null +++ b/src/arch/asm/irq.s @@ -0,0 +1,141 @@ +global irq0 +global irq1 +global irq2 +global irq3 +global irq4 +global irq5 +global irq6 +global irq7 +global irq8 +global irq9 +global irq10 +global irq11 +global irq12 +global irq13 +global irq14 +global irq15 + +; 32: IRQ0 + +irq0: + cli + push byte 0 ; "dummy" kod błędu + push byte 32 + jmp irq_common_stub + +irq1: + cli + push byte 0 ; "dummy" kod błędu + push byte 33 + jmp irq_common_stub + +irq2: + cli + push byte 0 ; "dummy" kod błędu + push byte 34 + jmp irq_common_stub + +irq3: + cli + push byte 0 ; "dummy" kod błędu + push byte 35 + jmp irq_common_stub + +irq4: + cli + push byte 0 ; "dummy" kod błędu + push byte 36 + jmp irq_common_stub + +irq5: + cli + push byte 0 ; "dummy" kod błędu + push byte 37 + jmp irq_common_stub + +irq6: + cli + push byte 0 ; "dummy" kod błędu + push byte 38 + jmp irq_common_stub + +irq7: + cli + push byte 0 ; "dummy" kod błędu + push byte 39 + jmp irq_common_stub + +irq8: + cli + push byte 0 ; "dummy" kod błędu + push byte 40 + jmp irq_common_stub + +irq9: + cli + push byte 0 ; "dummy" kod błędu + push byte 41 + jmp irq_common_stub + +irq10: + cli + push byte 0 ; "dummy" kod błędu + push byte 42 + jmp irq_common_stub + +irq11: + cli + push byte 0 ; "dummy" kod błędu + push byte 43 + jmp irq_common_stub + +irq12: + cli + push byte 0 ; "dummy" kod błędu + push byte 44 + jmp irq_common_stub + +irq13: + cli + push byte 0 ; "dummy" kod błędu + push byte 45 + jmp irq_common_stub + +irq14: + cli + push byte 0 ; "dummy" kod błędu + push byte 46 + jmp irq_common_stub + +irq15: + cli + push byte 0 ; "dummy" kod błędu + push byte 47 + jmp irq_common_stub + + +extern irq_handler + +irq_common_stub: + pusha + push ds + push es + push fs + push gs + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov eax, esp + push eax + mov eax, irq_handler + call eax + pop eax + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 + iret diff --git a/src/arch/asm/isr.s b/src/arch/asm/isr.s new file mode 100644 index 0000000..53c1c60 --- /dev/null +++ b/src/arch/asm/isr.s @@ -0,0 +1,254 @@ +global isr0 +global isr1 +global isr2 +global isr3 +global isr4 +global isr5 +global isr6 +global isr7 +global isr8 +global isr9 +global isr10 +global isr11 +global isr12 +global isr13 +global isr14 +global isr15 +global isr16 +global isr17 +global isr18 +global isr19 +global isr20 +global isr21 +global isr22 +global isr23 +global isr24 +global isr25 +global isr26 +global isr27 +global isr28 +global isr29 +global isr30 +global isr31 +global isr81 + +section .text + +isr0: + cli + push byte 0 + push byte 0 + jmp isr_common_stub + +isr1: + cli + push byte 0 + push byte 1 + jmp isr_common_stub + +isr2: + cli + push byte 0 + push byte 2 + jmp isr_common_stub + +isr3: + cli + push byte 0 + push byte 3 + jmp isr_common_stub + +isr4: + cli + push byte 0 + push byte 4 + jmp isr_common_stub + +isr5: + cli + push byte 0 + push byte 5 + jmp isr_common_stub + +isr6: + cli + push byte 0 + push byte 6 + jmp isr_common_stub + +isr7: + cli + push byte 0 + push byte 7 + jmp isr_common_stub + +isr8: + cli + push byte 8 + jmp isr_common_stub + +isr9: + cli + push byte 0 + push byte 9 + jmp isr_common_stub + +isr10: + cli + push byte 10 + jmp isr_common_stub + +isr11: + cli + push byte 11 + jmp isr_common_stub + +isr12: + cli + push byte 12 + jmp isr_common_stub + +isr13: + cli + push byte 13 + jmp isr_common_stub + +isr14: + cli + push byte 14 + jmp isr_common_stub + +isr15: + cli + push byte 0 + push byte 15 + jmp isr_common_stub + +isr16: + cli + push byte 0 + push byte 16 + jmp isr_common_stub + +isr17: + cli + push byte 0 + push byte 17 + jmp isr_common_stub + +isr18: + cli + push byte 0 + push byte 18 + jmp isr_common_stub + +isr19: + cli + push byte 0 + push byte 19 + jmp isr_common_stub + +isr20: + cli + push byte 0 + push byte 20 + jmp isr_common_stub + +isr21: + cli + push byte 0 + push byte 21 + jmp isr_common_stub + +isr22: + cli + push byte 0 + push byte 22 + jmp isr_common_stub + +isr23: + cli + push byte 0 + push byte 23 + jmp isr_common_stub + +isr24: + cli + push byte 0 + push byte 24 + jmp isr_common_stub + +isr25: + cli + push byte 0 + push byte 25 + jmp isr_common_stub + +isr26: + cli + push byte 0 + push byte 26 + jmp isr_common_stub + +isr27: + cli + push byte 0 + push byte 27 + jmp isr_common_stub + +isr28: + cli + push byte 0 + push byte 28 + jmp isr_common_stub + +isr29: + cli + push byte 0 + push byte 29 + jmp isr_common_stub + +isr30: + cli + push byte 0 + push byte 30 + jmp isr_common_stub + +isr31: + cli + push byte 0 + push byte 31 + jmp isr_common_stub + +isr81: + cli + push byte 0 + push byte 81 + jmp isr_common_stub + + +extern fault_handler + +isr_common_stub: +; pusha + push ds + push es + push fs + push gs + mov ax, 0x10 ; ładujemy deskryptor segmentu danych jądra + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov eax, esp +; push eax + mov eax, fault_handler + call eax + ; pop eax + pop gs + pop fs + pop es + pop ds +; popa + add esp,8 + iret diff --git a/src/arch/asm/pit.s b/src/arch/asm/pit.s new file mode 100644 index 0000000..e69de29 diff --git a/src/arch/basic/console.c b/src/arch/basic/console.c new file mode 100644 index 0000000..8563227 --- /dev/null +++ b/src/arch/basic/console.c @@ -0,0 +1,209 @@ +#include +#define COLOUR (COLOURS << 8) + +volatile unsigned short int *scr; +int curx = 0, cury = 0; +unsigned short int EmptySpace = COLOUR | 0x20; + + +int scroll() { + int distance = cury - VGA_HEIGHT + 1; + + if (distance <= 0) { + return 0; + } + + unsigned char *newStart = ((unsigned char *)scr) + + distance * VGA_WIDTH * 2; + int bytesToCopy = (VGA_HEIGHT - distance) * VGA_WIDTH * 2; + volatile unsigned short int *newBlankStart = scr + + (VGA_HEIGHT - distance) * VGA_WIDTH; + int blankBytesToSet = distance * VGA_WIDTH * 2; + memcpy((unsigned char *)scr, newStart, bytesToCopy); + memcpy2((unsigned char *)newBlankStart, (unsigned char *)&EmptySpace, + 2,blankBytesToSet); + cury = VGA_HEIGHT - 1; + + return 0; +} + +int putchar(unsigned char c){ + volatile unsigned short int *addr = 0; + if (c == '\t') { + curx = ((curx + 4)/4)*4; + } else if (c == '\r') { + curx = 0; + } else if (c == '\n') { + curx = 0; + cury++; + } else if (c == 0x08 && curx != 0) { + curx--; + } else { + addr = scr + (cury * VGA_WIDTH + curx); + *addr = COLOUR | c; + curx++; + } + + if (curx >= VGA_WIDTH) { + curx = 0; + cury++; + } + + scroll(); + + return 0; +} + +int puts(unsigned char *str) { + while (*str) { + putchar(*str); + str++; + } + return 0; +} + +int vga_clear() { + volatile char *vga = (volatile char*)VGA_ADDRESS; + + for (int i = 0 ; i < VGA_WIDTH * VGA_HEIGHT; i++) { + vga[2*i] = ' '; + } + + return 0; +} + + +int vga_init() { + scr = (volatile unsigned short int *)VGA_ADDRESS; + return vga_clear(); +} + +int snprintf(char *buffer, int length, char *format, ...) { + char **arg = base_pointer() + sizeof(const char *)*2; + int c; + char buf[20]; + + int index = 0; + + arg++; + char c2; + while ((c = *format++) != 0 && index < length) { + if (c != '%') { + if (index < length) { + buffer[index++] = c; + } + } else { + char *p; + c = *format++; + switch(c) { + case 'd': + case 'u': + case 'x': + itoa(buf, c, *((int *) arg++)); + p = buf; + goto string; + break; + case 's': + p = *arg++; + if (p == 0) { + p = "(null)"; + } + string: + while(*p && index < length) { + buffer[index++] = *p++; + } + break; + default: + c2 = (*((int *) arg++)); + if (index < length) { + buffer[index++] = c2; + } + break; + } + } + } + + return 0; +} + +int printf(const char *format, ...) __attribute__((cdecl)) { + char **arg = base_pointer() + sizeof(const char *)*2; + int c; + char buf[20]; + + arg++; + + while ((c = *format++) != 0) { + if (c != '%') { + putchar(c); + } else { + char *p; + c = *format++; + switch(c) { + case 'd': + case 'u': + case 'x': + itoa(buf, c, *((int *) arg++)); + p = buf; + goto string; + break; + case 's': + p = *arg++; + if (p == 0) { + p = "(null)"; + } + string: + while(*p) { + putchar(*p++); + } + break; + default: + putchar(*((int *) arg++)); + break; + } + } + } + + return 0; +} + +int log(const char *format, ...) { + char **arg = base_pointer() + sizeof(const char *)*2; + int c; + char buf[20]; + + arg++; + + while ((c = *format++) != 0) { + if (c != '%') { + write_serial(c); + } else { + char *p; + c = *format++; + switch(c) { + case 'd': + case 'u': + case 'x': + itoa(buf, c, *((int *) arg++)); + p = buf; + goto string; + break; + case 's': + p = *arg++; + if (p == 0) { + p = "(null)"; + } + string: + while(*p) { + write_serial(*p++); + } + break; + default: + write_serial(*((int *) arg++)); + break; + } + } + } + + return 0; +} diff --git a/src/arch/basic/gdt.c b/src/arch/basic/gdt.c new file mode 100644 index 0000000..e6f63ef --- /dev/null +++ b/src/arch/basic/gdt.c @@ -0,0 +1,36 @@ +#include + +struct gdt_entry gdt[3]; +struct gdt_ptr gp; + +int gdt_set_gate(int num, + unsigned long base, + unsigned long limit, + unsigned char access, + unsigned char gran) { + + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16 ) & 0xFF; + gdt[num].base_hight = (base >> 24) & 0xFF; + + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = ((limit >> 16) & 0x0F); + + gdt[num].granularity |= (gran & 0xF0); + gdt[num].access = access; + + return 0; +} + +int gdt_install() { + gp.limit = (sizeof(struct gdt_entry)*3) - 1; + gp.base = (unsigned int)&gdt; + + gdt_set_gate(0, 0, 0, 0, 0); + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + gdt_flush(); + + return 0; +} diff --git a/src/arch/basic/idt.c b/src/arch/basic/idt.c new file mode 100644 index 0000000..27abd90 --- /dev/null +++ b/src/arch/basic/idt.c @@ -0,0 +1,27 @@ +#include + +struct idt_entry idt[256]; +struct idt_ptr idtp; + +int idt_set_gate(unsigned char num, + unsigned long base, + unsigned short sel, + unsigned char flags) { + idt[num].base_lo = (base & 0xFFFF); + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; + idt[num].base_hi = ((base >> 16) & 0xFFFF); + + return 0; +} + +int idt_install() { + idtp.limit = (sizeof(struct idt_entry) * 256) - 1; + idtp.base = (unsigned int)&idt; + + memset((unsigned char *)&idt, 0, sizeof(struct idt_entry) * 256); + + idt_load(); + return 0; +} diff --git a/src/arch/basic/irq.c b/src/arch/basic/irq.c new file mode 100644 index 0000000..81a2b2e --- /dev/null +++ b/src/arch/basic/irq.c @@ -0,0 +1,114 @@ +#include + +extern void remap(); + +void *irq_routines[16] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +int irq_install_handler(int irq, int (*handler)(struct regs *r)) { + irq_routines[irq] = handler; + return 0; +} + +int irq_uninstall_handler(int irq) { + irq_routines[irq] = 0; + return 0; +} + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +#define PIC1_CMD 0x20 +#define PIC1_COMMAND PIC1_CMD +#define PIC1_DATA 0x21 +#define PIC2_CMD 0xA0 +#define PIC2_COMMAND PIC2_CMD +#define PIC2_DATA 0xA1 +#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */ +#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */ + +void PIC_remap(int offset1, int offset2) +{ + unsigned char a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence (in cascade mode) + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset + io_wait(); + outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset + io_wait(); + outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) + io_wait(); + outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} + +int irq_remap() { + PIC_remap(0x20,0x20+8); + return 0; +} + +int irq_install() { + remap(); + idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E); + idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E); + idt_set_gate(34, (unsigned)irq2, 0x08, 0x8E); + idt_set_gate(35, (unsigned)irq3, 0x08, 0x8E); + idt_set_gate(36, (unsigned)irq4, 0x08, 0x8E); + idt_set_gate(37, (unsigned)irq5, 0x08, 0x8E); + idt_set_gate(38, (unsigned)irq6, 0x08, 0x8E); + idt_set_gate(39, (unsigned)irq7, 0x08, 0x8E); + idt_set_gate(40, (unsigned)irq8, 0x08, 0x8E); + idt_set_gate(41, (unsigned)irq9, 0x08, 0x8E); + idt_set_gate(42, (unsigned)irq10, 0x08, 0x8E); + idt_set_gate(43, (unsigned)irq11, 0x08, 0x8E); + idt_set_gate(44, (unsigned)irq12, 0x08, 0x8E); + idt_set_gate(45, (unsigned)irq13, 0x08, 0x8E); + idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E); + idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E); + + return 0; +} + +int irq_handler(struct regs *r) { + void (*handler)(struct regs *r); + handler = irq_routines[r->int_no-32]; + if (handler) { + handler(r); + } + + if (r->int_no >= 40) { + outb(0xA0, 0x20); + } + + outb((unsigned short)0x20, (unsigned char)0x20); + + return 0; +} + diff --git a/src/arch/basic/isr.c b/src/arch/basic/isr.c new file mode 100644 index 0000000..8703d54 --- /dev/null +++ b/src/arch/basic/isr.c @@ -0,0 +1,129 @@ +#include + +extern int isr0(); +extern int isr1(); +extern int isr2(); +extern int isr3(); +extern int isr4(); +extern int isr5(); +extern int isr6(); +extern int isr7(); +extern int isr8(); +extern int isr9(); +extern int isr10(); +extern int isr11(); +extern int isr12(); +extern int isr13(); +extern int isr14(); +extern int isr15(); +extern int isr16(); +extern int isr17(); +extern int isr18(); +extern int isr19(); +extern int isr20(); +extern int isr21(); +extern int isr22(); +extern int isr23(); +extern int isr24(); +extern int isr25(); +extern int isr26(); +extern int isr27(); +extern int isr28(); +extern int isr29(); +extern int isr30(); +extern int isr31(); +extern int isr81(); + +int isrs_install() { + idt_set_gate(0,(unsigned)isr0, 0x08, 0x8E); + idt_set_gate(1,(unsigned)isr1, 0x08, 0x8E); + idt_set_gate(2,(unsigned)isr2, 0x08, 0x8E); + idt_set_gate(3,(unsigned)isr3, 0x08, 0x8E); + idt_set_gate(4,(unsigned)isr4, 0x08, 0x8E); + idt_set_gate(5,(unsigned)isr5, 0x08, 0x8E); + idt_set_gate(6,(unsigned)isr6, 0x08, 0x8E); + idt_set_gate(7,(unsigned)isr7, 0x08, 0x8E); + idt_set_gate(8,(unsigned)isr8, 0x08, 0x8E); + idt_set_gate(9,(unsigned)isr9, 0x08, 0x8E); + idt_set_gate(10,(unsigned)isr10, 0x08, 0x8E); + idt_set_gate(11,(unsigned)isr11, 0x08, 0x8E); + idt_set_gate(12,(unsigned)isr12, 0x08, 0x8E); + idt_set_gate(13,(unsigned)isr13, 0x08, 0x8E); + idt_set_gate(14,(unsigned)isr14, 0x08, 0x8E); + idt_set_gate(15,(unsigned)isr15, 0x08, 0x8E); + idt_set_gate(16,(unsigned)isr16, 0x08, 0x8E); + idt_set_gate(17,(unsigned)isr17, 0x08, 0x8E); + idt_set_gate(18,(unsigned)isr18, 0x08, 0x8E); + idt_set_gate(19,(unsigned)isr19, 0x08, 0x8E); + idt_set_gate(20,(unsigned)isr20, 0x08, 0x8E); + idt_set_gate(21,(unsigned)isr21, 0x08, 0x8E); + idt_set_gate(22,(unsigned)isr22, 0x08, 0x8E); + idt_set_gate(23,(unsigned)isr23, 0x08, 0x8E); + idt_set_gate(24,(unsigned)isr24, 0x08, 0x8E); + idt_set_gate(25,(unsigned)isr25, 0x08, 0x8E); + idt_set_gate(26,(unsigned)isr26, 0x08, 0x8E); + idt_set_gate(27,(unsigned)isr27, 0x08, 0x8E); + idt_set_gate(28,(unsigned)isr28, 0x08, 0x8E); + idt_set_gate(29,(unsigned)isr29, 0x08, 0x8E); + idt_set_gate(30,(unsigned)isr30, 0x08, 0x8E); + idt_set_gate(31,(unsigned)isr31, 0x08, 0x8E); + idt_set_gate(81,(unsigned)isr81, 0x08, 0x8E); + return 0; +} + +char *exception_messages[] = { + "[0]: Division by zero", + "[1]: Debug", + "[2]: Non Maskable Interrupt", + "[3]: Breakpoint", + "[4]: Into Detected Overflow", + "[5]: Out Of Bounds", + "[6]: Invalid Opcode", + "[7]: No Coprocessor Found", + "[8]: Double Fault", + "[9]: Coprocessor Segment Overrun", + "[10]: Bad TSS", + "[11]: Segment Not Present", + "[12]: Stack Fault", + "[13]: General Protection Fault", + "[14]: Page Fault", + "[15]: Unknown Interrupt", + "[16]: Coprocessor Fault", + "[17]: Alignment Check", + "[18]: Machine Check", + "[19]: Reserved", + "[20]: Reserved", + "[21]: Reserved", + "[22]: Reserved", + "[23]: Reserved", + "[24]: Reserved", + "[25]: Reserved", + "[26]: Reserved", + "[27]: Reserved", + "[28]: Reserved", + "[29]: Reserved", + "[30]: Reserved", + "[31]: Reserved", +}; + +int fault_handler(struct regs *r) { +// printf("AAA"); + /* Is this a fault whose number is from 0 to 31? */ + if (r->int_no < 32) + { + /* Display the description for the Exception that occurred. + * In this tutorial, we will simply halt the system using an + * infinite loop */ + log(exception_messages[r->int_no]); + log(" Exception. System Halted!\n"); + printf(exception_messages[r->int_no]); + printf(" Exception. System Halted!\n"); + + for (;;); + } else { + printf("Exception handling nr %d, eax: 0x%x, ebx: 0x%x\n", + r->int_no, r->eax, r->ebx); + return 5; + } + return 0; +} diff --git a/src/arch/basic/kbd.c b/src/arch/basic/kbd.c new file mode 100644 index 0000000..e92ae88 --- /dev/null +++ b/src/arch/basic/kbd.c @@ -0,0 +1,66 @@ +#include + +/* KBDUS means US Keyboard Layout. This is a scancode table +* used to layout a standard US keyboard. I have left some +* comments in to give you an idea of what key is what, even +* though I set it's array index to 0. You can change that to +* whatever you want using a macro, if you wish! */ +unsigned char kbdus[128] = +{ + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ + '9', '0', '-', '=', '\b', /* Backspace */ + '\t', /* Tab */ + 'q', 'w', 'e', 'r', /* 19 */ + 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ + 0, /* 29 - Control */ + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ + '\'', '`', 0, /* Left shift */ + '\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */ + 'm', ',', '.', '/', 0, /* Right shift */ + '*', + 0, /* Alt */ + ' ', /* Space bar */ + 0, /* Caps lock */ + 0, /* 59 - F1 key ... > */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* < ... F10 */ + 0, /* 69 - Num lock*/ + 0, /* Scroll Lock */ + 0, /* Home key */ + 0, /* Up Arrow */ + 0, /* Page Up */ + '-', + 0, /* Left Arrow */ + 0, + 0, /* Right Arrow */ + '+', + 0, /* 79 - End key*/ + 0, /* Down Arrow */ + 0, /* Page Down */ + 0, /* Insert Key */ + 0, /* Delete Key */ + 0, 0, 0, + 0, /* F11 Key */ + 0, /* F12 Key */ + 0, /* All other keys are undefined */ +}; + + +int keyboard_handler(struct regs *r) { + UNUSED(r); + unsigned char scancode; + scancode = inb(0x60); + + if (scancode & 0x80) { + /** alt, special **/ + } else { + putchar(kbdus[scancode]); + } + + return 0; +} + +int kbd_install() { + irq_install_handler(1, keyboard_handler); + return 0; +} diff --git a/src/arch/basic/kernel.c b/src/arch/basic/kernel.c new file mode 100644 index 0000000..9121613 --- /dev/null +++ b/src/arch/basic/kernel.c @@ -0,0 +1,187 @@ +#include +#include +#include + +multiboot_info_t *m; +u32int mem_lower; +u32int mem_upper; + +fs_node_t *fs_root = NULL; + +void pre_init(unsigned long magic) { + vga_init(); + log("Zainicjalizowano ekran\r\n"); + init_serial(); + log("Zainicjalizowano port seryjny\r\n"); + + initAcpi(); + acpiEnable(); + + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printf ("Invalid magic number: 0x%x\n", (unsigned) magic); + PANIC("INVALID MULTIBOOT MAGIC"); + return; + } + + if (CHECK_FLAG(m->flags, 0)) { + mem_lower = m->mem_lower; + mem_upper = m->mem_upper; + printf("mem_lower: %uKB, mem_upper: %uKB\n", + m->mem_lower, m->mem_upper); + } + + if (CHECK_FLAG(m->flags, 1)) { + printf("boot device: %s\n", (char *)m->boot_device); + } + + if (CHECK_FLAG(m->flags, 2)) { + printf("command line: %s\n", (char *)m->cmdline); + } + + if (CHECK_FLAG(m->flags, 3)) { + printf("nr of modules: %u\n", m->mods_count); + multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr; + for (u32int i = 0; i < m->mods_count; i++) { + printf("module nr %u: start: 0x%x, end: 0x%x, cmdline: %s\n", + i, + modules[i].mod_start, + modules[i].mod_end, + modules[i].cmdline); + } + } + + log("Acpi: 0x%x\n", initAcpi()); + + gdt_install(); + log("Zainstalowano struktury GDT\r\n"); + idt_install(); + log("Zainstalowano struktury IDT (przerwania)\r\n"); + isrs_install(); + log("Zainstalowano procedury obsługujące przerwania\r\n"); + + init_paging3(); + printf("OK\n"); + // init_paging3(); + printf("OK2\n"); + + irq_install(); + log("Zainstalowano przerwania irq\r\n"); + timer_install(); + log("Zainstalowano systemowy timer\r\n"); + kbd_install(); + log("Zainicjalizowano klawiature\r\n"); + sti(); + + + log("Wlaczono przerwania\r\n"); + log("Start: 0x%x\r\n", kernel_start()); + log("End: 0x%x\r\n", kernel_end()); + log("End (with stack): 0x%x\r\n", kernel_full_end()); + log("Size: 0x%x\r\n", kernel_end()-kernel_start()); + log("Size (with stack): 0x%x\r\n", kernel_full_end()-kernel_start()); + + multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr; + + u32int initrd_start = modules[0].mod_start; + u32int initrd_end = modules[0].mod_end; + + printf("Initrd start: 0x%x\n", initrd_start); + printf("Initrd end: 0x%x\n", initrd_end); + + /* + + for (u32int addr = initrd_start / 0x1000 * 0x1000; addr < initrd_end; + addr += 0x1000) { + printf ("Allocating addr: 0x%x\n", addr); + ident_alloc_frame(get_page(addr, 1, kernel_directory), + 1, 1, addr); + } + + fs_root = initrd_init(initrd_start); + */ + +} + +void post_destroy() { + disablePaging(); + acpiPowerOff(); + // TODO + // init_acpi(); + // AcpiEnable(); + // AcpiPowerOff(); + + for (;;) { + hlt(); + } + +} + +int cmain(unsigned long magic, multiboot_info_t *mbi) { + m = mbi; + pre_init(magic); + printf("Zaladowano system useless os\n"); + + u32int k = 0; + struct dirent *node = NULL; + unsigned char buffer[512]; + printf("Reading...\n"); + check_ata_hd(); + reset_ata_hd(); + read_ata_hd(0, 1, buffer); + printf("Buffer: %s\n", buffer); + /* + + while ( (node = readdir_fs(fs_root, k)) != 0) { + printf ("Found file: %s\n", node->name); + fs_node_t *fsnode = finddir_fs(fs_root, node->name); + if ((fsnode->flags & 0x7) == FS_DIRECTORY) { + printf("\n\t(directory)\n"); + } else { + printf("\n\t contents:\""); + unsigned char buf[256]; + read_fs(fsnode, 0, 256, buf); + printf("%s\"\n", buf); + printf("\n"); + } + k++; + } + */ + /* + int *c = 0x1000000 - 0x1000; + // printf("0x%x\n", *c); + //c = 0xffffff; + // printf("0x%x\n", *c); +// c = 0xffffffff; + for (c = 0; c < 0xfffff000; c += 0x1000) { + printf("0x%x - 0x%x\n", c, *c); + } + */ + + printf("CR0: 0x%x\n", get_cr0()); + printf("CR3: 0x%x\n", get_cr3()); + printf("PRE\n"); + printf("Val: %d\n", interrupt_work()); + printf("POST\n"); + for (u32int i = 0; i < 10; i++) { + printf("."); + sleep(1); + } + + outw( 0xB004, 0x0 | 0x2000 ); + printf("Switching off failed\n"); + for(;;) { + hlt(); + } + + +// printf("\nYou can now safely turn it down\n"); + + /* + for(;;) { + hlt(); +// printf("Interrupted\n"); + } +*/ + //post_destroy(); + return 0; +} diff --git a/src/arch/basic/pit.c b/src/arch/basic/pit.c new file mode 100644 index 0000000..537c2f5 --- /dev/null +++ b/src/arch/basic/pit.c @@ -0,0 +1,45 @@ +#include + +#define MAX_HERTZ 1193180 +#define HZ 18 +#define quant (MAX_HERTZ / HZ) +#define quant_time ((double) quant / (double)(MAX_HERTZ)) +int timer_ticks = 0; +double left_time = 0.0; + +int timer_phase(int hz) { + + int divisor = MAX_HERTZ / hz; + outb(0x43, 0x36); + outb(0x40, divisor & 0xFF); + outb(0x40, divisor >> 8); + + return 0; +} + +int timer_handler(struct regs *r) { + UNUSED(r); + timer_ticks++; + left_time += quant_time; + /* + if (timer_ticks % HZ == 0) { + printf((char *)"One seconds has passed: %d\n", + (unsigned int)left_time); + } + */ + return 0; +} + +int timer_install() { + irq_install_handler(0, timer_handler); + return 0; +} + +int sleep(double sec) { + double start = left_time; + while (left_time - start < sec) { + hlt(); // from hlt we are woken up by timer interruption + } + return 0; +} + diff --git a/src/arch/basic/serial.c b/src/arch/basic/serial.c new file mode 100644 index 0000000..b6e29aa --- /dev/null +++ b/src/arch/basic/serial.c @@ -0,0 +1,37 @@ +#include + +void init_serial() { + outb(PORT + 1, 0x00); // Disable all interrupts + outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outb(PORT + 1, 0x00); // (hi byte) + outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set +} + +int serial_received() { + return inb(PORT + 5) & 1; +} + +char read_serial() { + while (serial_received() == 0); + + return inb(PORT); +} + +int is_transmit_empty() { + return inb(PORT + 5) & 0x20; +} + +void write_serial(char a) { + while (is_transmit_empty() == 0); + + outb(PORT,a); +} + +void write_serial_string(char *s) { + while (*s) { + write_serial(*s++); + } +} diff --git a/src/arch/basic/strings.c b/src/arch/basic/strings.c new file mode 100644 index 0000000..b7b307f --- /dev/null +++ b/src/arch/basic/strings.c @@ -0,0 +1,147 @@ +#include + +void *memcpy(void *d, + const void *s, + int count) { + char *dest = (char *)d; + char *src = (char *)s; + + for (int i = 0; i < count; i++) { + dest[i] = src[i]; + } + return dest; +} + +void *memcpy2(void *d, + const void *s, + int length, + int count) { + char *dest = (char *)d; + char *src = (char *)s; + + for (int i = 0; i < count; i++) { + dest[i] = src[i%length]; + } + return dest; +} + + +void *memset(void *d, + unsigned char val, + int count) { + char *dest = (char *)d; + + for (int i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +u32int memcmp(void *m1, void *m2, u32int l){ + char *mem1 = (char *)m1; + char *mem2 = (char *)m2; + + u32int count = 0; + for (u32int i = 0; i < l; i++) { + if (mem1[i] != mem2[i]) { + count++; + } + } + + return count; + +} + +int itoa(void *buf, int base, int d) { + char *p = buf; + char *p1, *p2; + unsigned long ud = d; + int divisor = 10; + + if (base == 'd' && d < 0) { + *p++ = '-'; + buf++; + ud = -d; + } else if (base == 'x') { + divisor = 16; + } + + u32int t = 0; + + do { + int remainder = ud % divisor; + *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10; + t++; + } while (ud /= divisor); + + for (u32int i = t; i < 2; i++) { + *p++ = '0'; + } + + *p = 0; + p1 = buf; + p2 = p - 1; + + while (p1 < p2) { + char tmp = *p1; + *p1 = *p2; + *p2 = tmp; + p1++; + p2--; + } + return 0; +} + +void dump(void *a, u32int size) { + char *addr = (char *)a; + u32int lines = size / 16; + u32int offset = size % 16; + + for (u32int line = 0; line < lines; line++) { + printf ("0x%x: ", addr + line * 16); + for (u32int i = 0; i < 16; i++) { + u8int c = addr[16*line+i]; + printf ("%x ", c); + } + + printf("| "); + for (u32int i = 0; i < 16; i++) { + u8int c = addr[16*line+i]; + if (c >= 32) { + printf ("%c", c); + } else { + printf ("."); + } + } + + printf("\n"); + + } + + if (offset > 0 ) { + printf("0x%x: ", addr + (lines + 1)*16); + for (u32int i = 0; i < offset; i++) { + u8int c = addr[16*(lines+1)+i]; + printf ("%x ", c); + } + + for (u32int i = 0; i < 16 - offset; i++) { + printf (" "); + } + + printf("| "); + for (u32int i = 0; i < offset; i++) { + u8int c = addr[16*(lines+1)+i]; + if (c >= 32) { + printf ("%c", addr[16*(lines+1)+i]); + } else { + printf ("."); + } + } + + printf("\n"); + + } +} + + diff --git a/src/arch/boot/boot.s b/src/arch/boot/boot.s new file mode 100644 index 0000000..a22cd24 --- /dev/null +++ b/src/arch/boot/boot.s @@ -0,0 +1,40 @@ +ASM equ 1 +MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 +MULTIBOOT_HEADER_FLAGS equ 0x00000003 +STACK_SIZE equ 0x4000 + +extern cmain +global _start +global stack +global stack_end + +section .multiboot +multiboot_header: + align 4 + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd -(MULTIBOOT_HEADER_FLAGS + MULTIBOOT_HEADER_MAGIC) + +section .text +_start: + align 4 + jmp multiboot_entry + +multiboot_entry: + mov esp, stack + STACK_SIZE + push ebx + push eax + call cmain + + ; tu nigdy nie powinno dojść + add esp, 8 + +loop: + hlt + jmp loop + +section .bss + +stack: + resb STACK_SIZE +stack_end: diff --git a/src/arch/mm/frame.c b/src/arch/mm/frame.c new file mode 100644 index 0000000..5a951ca --- /dev/null +++ b/src/arch/mm/frame.c @@ -0,0 +1,158 @@ +#include + +u32int *frames; +u32int nframes; + +void set_frame(u32int frame_addr) { + u32int frame = frame_addr / 0x1000; + u32int idx = INDEX_FROM_BIT(frame); + u32int off = OFFSET_FROM_BIT(frame); + frames[idx] |= (0x1 << off); + // log("Frame 0x%x used\r\n", frame_addr); +} + +void clear_frame(u32int frame_addr) { + u32int frame = frame_addr / 0x1000; + u32int idx = INDEX_FROM_BIT(frame); + u32int off = OFFSET_FROM_BIT(frame); + frames[idx] &= ~(0x1 << off); + // log("Frame 0x%x freed\r\n", frame_addr); +} + +u32int test_frame(u32int frame_addr) { + u32int frame = frame_addr / 0x1000; + u32int idx = INDEX_FROM_BIT(frame); + u32int off = OFFSET_FROM_BIT(frame); + return (frames[idx] & (0x1 << off)); +} + +u32int first_frame() { + u32int i,j; + for (i = 0; i < INDEX_FROM_BIT(nframes); i++) { + if (frames[i] != 0xFFFFFFFF) { + for (j = 0; j < 32; j++) { + u32int toTest = 0x1 << j; + if (!(frames[i]&toTest)) { + return i*4*8+j; + } + } + } + } + return -1; +} + +u32int frames_allocated() { + u32int count = 0; + + for (u32int frameNr = 0; frameNr < nframes; frameNr++) { + if (test_frame(frameNr * 0x1000)) { +// log("Frame allocated: 0x%x\r\n", frameNr * 0x1000); + count++; + } + } + + return count; +} + +void dump_frames() { + u32int start,end; + u32int block = 0; + u32int frameNr = 0; + for (frameNr = 0; frameNr < nframes; frameNr++) { + if (test_frame(frameNr * 0x1000)) { + if (!block) { + block = 1; + start = frameNr; + } + } else { + if (block) { + block = 0; + end = frameNr; + + log("[0x%x - 0x%x] [0x%x(%d)]\r\n", + start, + end-1, + end-start, + end-start); + + printf("[0x%x - 0x%x] [0x%x(%d)]\n", + start, + end-1, + end-start, + end-start); + + + } + } + } + +} + +void alloc_frame(page_t *page, int is_kernel, int is_writable) { + /* + log("Alloc frame 0x%x [%c%c]\r\n", + page->frame * 0x1000, + page->user ? 'u' : 'k', + page->rw ? 'w' : 'r'); + */ + + if (page->frame != NULL) { + //log("Strona juz zalokowana: 0x%x\r\n", page->frame*0x1000); + return; + } else { + u32int idx = first_frame(); + if (idx == (u32int)-1) { + PANIC("No free frames"); + return; + } + + set_frame(idx*0x1000); + page->present = 1; + page->rw = (is_writable) ? 1 : 0; + page->user = (is_kernel) ? 0 : 1; + page->frame = idx; + // log("Strona juz zaalokowano: 0x%x\r\n", page->frame*0x1000); + } +} + +void ident_alloc_frame(page_t *page, int is_kernel, int is_writable, + u32int addr) { + /* + printf("ident alloc frame: 0x%x\n", page); + log("Alloc frame 0x%x [%c%c]\r\n", + page->frame * 0x1000, + page->user ? 'u' : 'k', + page->rw ? 'w' : 'r'); + */ + if (page->frame != NULL) { + //log("Strona juz zalokowana: 0x%x\r\n", page->frame*0x1000); + return; + } else { + u32int idx = addr / 0x1000; + if (idx == (u32int)-1) { + PANIC("No free frames"); + return; + } + + set_frame(idx*0x1000); + page->present = 1; + page->rw = (is_writable) ? 1 : 0; + page->user = (is_kernel) ? 0 : 1; + page->frame = idx; + // log("Strona juz zaalokowano: 0x%x\r\n", page->frame*0x1000); + } +} + + +void free_frame(page_t *page) { + // log("free frame: 0x%x\r\n", page->frame * 0x1000); + u32int frame; + if (!(frame = page->frame)) { + // log("frame was not assigned\r\n"); + return; /** ponieważ dana strona nie ma przypisanej ramki pamięci */ + } else { + clear_frame(frame*0x1000); + page->frame = 0x0; + // log("cleared frame\r\n"); + } +} diff --git a/src/arch/mm/paging.c b/src/arch/mm/paging.c new file mode 100644 index 0000000..e10e113 --- /dev/null +++ b/src/arch/mm/paging.c @@ -0,0 +1,227 @@ +#include + +u32int page_directory[1024] __attribute__((aligned(4096))); +u32int first_page_table[1024] __attribute__((aligned(4096))); + +page_directory_t *current_directory = NULL; +page_directory_t *kernel_directory = NULL; +u32int nframes; +u32int *frames; +u32int full_end = 0; + +u32int max(u32int a, u32int b) { + return a > b ? a : b; +} + +u32int min(u32int a, u32int b) { + return a < b ? a : b; +} + +u32int c_log_phys(u32int logical) { + page_t *page = get_page(logical, 0, current_directory); + u32int logical_frame = logical & 0xFFFFF000; + u32int offset = logical - logical_frame; + u32int real_address = page->frame * 0x1000 + offset; + return real_address; +} + +void initialise_paging2() { + u32int mem_end_page = mem_upper * 1024; + nframes = mem_end_page / 0x1000; + printf("Mem upper: 0x%xu\n", mem_upper); + printf("Available memory: %uMB, NFRAMES: %u\n", + (u32int)(mem_upper / 1024 ), + nframes); + + full_end = (u32int)&end; + multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr; + full_end = max(full_end,modules[0].mod_end); + u32int tables = nframes / 1024; + full_end = ((full_end - 1) / 0x1000 + 1) * 0x1000; + + printf("Full end: 0x%x\n", full_end); + u32int full_end_pages = full_end + 0x1000 * tables; + printf("Full end with pages: 0x%x\n", full_end_pages); + + u32int frames_size = ((nframes - 1) / 32 + 1 * 32) * sizeof(u32int); + u32int frames_start = full_end_pages; + u32int frames_end = frames_start + frames_size; + + frames = (u32int *)frames_start; + memset((unsigned char *)frames, 0, frames_size); + + u32int pd_start = ((frames_end - 1) / 0x1000 + 1) * 0x1000; + u32int pd_size = sizeof(page_directory_t); + u32int pd_end = pd_start + pd_size; + + page_directory_t *page_directory = + (page_directory_t *)pd_start; + memset((unsigned char *)page_directory, 0, sizeof(page_directory_t)); + + log("page_directory: 0x%x\r\n", page_directory); + unsigned int i = 0; + for (i = 0; i < 1024; i++) { + page_directory->tablesPhysical[i] = 0 | 2; + } + + page_directory->physicalAddr = (u32int)page_directory->tablesPhysical; + init_heap(&kernel_heap, pd_end, + min(mem_end_page, pd_end + 0x5000), + mem_end_page, 1,1); + + printf("Inicjalizacja\n"); + + dump_heap(&kernel_heap); + + + unsigned int address = 0; + + current_directory = page_directory; + kernel_directory = page_directory; + + //we will fill all 1024 entries, mapping 4 megabytes + + log("Tworzenie mapy 1-1 dla stronnicowania\r\n"); + + for(address = 0; address < kernel_heap.max_address; address += 0x1000) + { + page_t *page = get_page(address, 1, page_directory); + page->frame = address >> 12; + page->present = 1;; // attributes: supervisor level, + page->rw = 1; + page->user = 0; + // read/write, present. + } + + log("Oznaczenie ramek kernel + reserved as used\r\n"); + log("Ramek pamięci jest: 0x%x\n", full_end_pages / 0x1000); + + dump_frames(); + + for (u32int i = 0; i < kernel_heap.max_address; i += 0x1000) { + set_frame(i); + } + + log("Zakonczono oznaczenie\r\n"); + + dump_frames(); + + /** zapisujemy, które ramki adresów fizycznych są już zajęte */ + + idt_set_gate(14, (unsigned)page_fault, 0x08, 0X8E); + log("Ustawiono nowy handler page fault\r\n"); + + switch_page_directory(page_directory); + log("Uaktywniono stronnicowanie\r\n"); + + printf("Slotow: 0x%x\n", kernel_heap.max_id); + +} + + +void switch_page_directory(page_directory_t *dir) { + current_directory = dir; + asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical)); + u32int cr0; + asm volatile("mov %%cr0, %0": "=r"(cr0)); + cr0 |= 0x80000000; // uaktywniamy stronnicowanie + asm volatile("mov %0, %%cr0":: "r"(cr0)); +} + +page_t *get_page(u32int address, int make, page_directory_t *dir) { + // przekształcamy adres w indeks + // log("get_page, address: 0x%x, make: %d, dir: 0x%x\r\n", address, + // make, dir); + address /= 0x1000; + // znajdujemy tablicę stron zawierający dany adres + u32int table_idx = address / 1024; + if (dir->table[table_idx]) { + // jeżeli tablica jest już aktualnie przypisana + return &dir->table[table_idx]->pages[address % 1024]; + } else if(make) { + // adres podany nie jest zmapowany, ale możemy go utworzyć + dir->table[table_idx] = (page_table_t *)(full_end + 0x1000 * table_idx); + memset((unsigned char *)dir->table[table_idx], 0, sizeof(page_table_t)); + dir->tablesPhysical[table_idx] = (u32int)dir->table[table_idx] | 0x3; + // PRESENT | RW | US + // log("Table: 0x%x, page: 0x%x\n", table_idx, address % 1024); + return &dir->table[table_idx]->pages[address % 1024]; + } else { + return NULL; + } +} + +int page_fault(struct regs *r) { + u32int faulting_address; + asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); + + + int present = !(r->err_code & 0x1); // strona nie istnieje + int rw = r->err_code & 0x2; // czy strona zapisywalna + int us = r->err_code & 0x4; // czy procesor w user-mode + int reserved = r->err_code & 0x8; // nadpisywane przez cpu zarezerwowane + // bity + int id = r->err_code & 0x10; // czy spowodowane przez + // pobranie rozkazu + log("Page fault! ( "); + if (present) { + log("present"); + } + if (rw) { + log("read-only "); + } + if (us) { + log("user-mode "); + } + if (reserved) { + log("reserved "); + } + if (id) { + log("instr_fetch "); + } + log(") at 0x%x\r\n", faulting_address); + + printf("Page fault! ( "); + if (present) { + printf("present"); + } + if (rw) { + printf("read-only "); + } + if (us) { + printf("user-mode "); + } + if (reserved) { + printf("reserved "); + } + if (id) { + printf("instr_fetch "); + } + printf(") at 0x%x\r\n", faulting_address); + + PANIC("PAGE FAULT"); + +} + +u32int* init_paging3() { + for (int i = 0; i < 1024; i++) { + page_directory[i] = 0x00000002; + } + + for (int i = 0; i < 1024; i++) { + first_page_table[i] = (i * 0x1000) | 3; + // attributes - supervisor, read/write, present + } + + page_directory[0] = ((unsigned int)first_page_table) | 3; + + idt_set_gate(14, (unsigned)page_fault, 0x08, 0X8E); + log("Ustawiono nowy handler page fault\r\n"); + + //switch_page_directory(page_directory); + log("Uaktywniono stronnicowanie\r\n"); + + loadPageDirectory(page_directory); + enablePaging(); + return page_directory; +} diff --git a/src/arch/mm/paging.s b/src/arch/mm/paging.s new file mode 100644 index 0000000..ebcbba7 --- /dev/null +++ b/src/arch/mm/paging.s @@ -0,0 +1,68 @@ +section .text + +global loadPageDirectory +global set_cr0 +global get_cr0 +global set_cr3 +global get_cr3 + +loadPageDirectory: + +push ebp +mov ebp, esp +mov eax, [esp+8] +mov cr3, eax +mov esp, ebp +pop ebp +ret + +global enablePaging +enablePaging: +push ebp +mov ebp, esp +mov eax, cr0 +or eax, 0x80000000 +mov cr0, eax +mov esp, ebp +pop ebp +ret + +global disablePaging2 + +disablePaging2: +push ebp +mov ebp, esp +mov eax, cr0 +and eax, 0x7fffffff +pop ebp +ret + +set_cr3: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr3, eax + pop ebp + ret + +get_cr3: + push ebp + mov ebp, esp + mov eax, cr3 + pop ebp + ret + +set_cr0: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr0, eax + pop ebp + ret + +get_cr0: + push ebp + mov ebp, esp + mov eax, cr0 + pop ebp + ret diff --git a/src/arch/task/copy.c b/src/arch/task/copy.c new file mode 100644 index 0000000..df2c094 --- /dev/null +++ b/src/arch/task/copy.c @@ -0,0 +1,70 @@ +#include + +page_directory_t *clone_directory(page_directory_t *src) { + page_directory_t *dir = (page_directory_t *)kmalloc_a( + sizeof(page_directory_t)); + u32int phys = c_log_phys((u32int)dir); + memset(dir, 0, sizeof(page_directory_t)); + + u32int offset = (u32int)dir->tablesPhysical - (u32int)dir; + dir->physicalAddr = phys + offset; + + for (u32int i = 0; i < 1024; i++) { + if (!src->table[i]) { + continue; + } + + if (kernel_directory->table[i] == src->table[i]) { + // takie same są już w jądrze, linkujemy + dir->table[i] = src->table[i]; + dir->tablesPhysical[i] = src->tablesPhysical[i]; + } else { + u32int phys; + dir->table[i] = clone_table(src->table[i], &phys); + dir->tablesPhysical[i] = phys | 0x07; + } + } + + return dir; +} + + +page_table_t *clone_table(page_table_t *src, u32int *phys) { + page_table_t *table = (page_table_t *)kmalloc_a(sizeof(page_table_t)); + *phys = c_log_phys((u32int)table); + memset(table, 0, sizeof(page_directory_t)); + + for(u32int i = 0; i < 1024; i++) { + if (!src->pages[i].frame) { + continue; + } + + alloc_frame(&table->pages[i], 0, 0); + + if (src->pages[i].present) { + table->pages[i].present = 1; + } + + if (src->pages[i].rw) { + table->pages[i].rw = 1; + } + + if (src->pages[i].user) { + table->pages[i].user = 1; + } + + if (src->pages[i].accessed) { + table->pages[i].accessed = 1; + } + + if (src->pages[i].dirty) { + table->pages[i].dirty = 1; + } + + copy_page_physical(src->pages[i].frame*0x1000, + table->pages[i].frame*0x1000); + + } + + return table; +} diff --git a/src/arch/task/fork.c b/src/arch/task/fork.c new file mode 100644 index 0000000..a409bb2 --- /dev/null +++ b/src/arch/task/fork.c @@ -0,0 +1 @@ +#include diff --git a/src/arch/task/process.s b/src/arch/task/process.s new file mode 100644 index 0000000..7320e29 --- /dev/null +++ b/src/arch/task/process.s @@ -0,0 +1,51 @@ +global copy_page_physical + +copy_page_physical: + push ebp + pushf + + push eax + push ebx + push ecx + push edx + + cli ; disabling interruptions + + ; pobieramy adresy stron zanim wyłączymy stronnicowanie + mov ebx, [esp+12] + mov ecx, [esp+16] + + ; wyłączamy stronnicowanie + mov edx, cr0 + and edx, 0x7fffffff + mov cr0, edx + ; wyłączono stronnicowanie + + mov edx, 1024 + +.loop: ; pętla kopiująca dane strony + mov eax, [ebx] ; kopiujemy dane + mov [ecx], eax + add ebx, 4 ; przesuwamy wskaźniki + add ecx, 4 + dec edx ; zmniejszamy licznik bajtów do przekopiowania + cmp edx, 0 ; tu w kodzie tego nie było TODO potestuj + jnz .loop + + ; przywracamy stronnicowanie + mov edx, cr0 + or edx, 0x80000000 + mov cr0, edx + ; przywrócono stronnicowanie + + + sti ; enabling interruptions + + pop edx + pop ecx + pop ebx + pop eax + + popf + pop ebp + ret diff --git a/src/generic/fs/initrd.c b/src/generic/fs/initrd.c new file mode 100644 index 0000000..77df9ef --- /dev/null +++ b/src/generic/fs/initrd.c @@ -0,0 +1,177 @@ +#include + +char *initrd = NULL; +char *initrd_data = NULL; +initrd_header_t *headers = NULL; +fs_node_t *initrd_root = NULL; +fs_node_t *initrd_dev = NULL; +fs_node_t *root_nodes = NULL; +u32int nroot_nodes = 0; +dirent_t dirent; + +u32int strcmp(void *s1, void *s2) { + char *m1 = (char *)s1; + char *m2 = (char *)s2; + u32int differences = 0; + + while (*m1 && *m2) { + if (*m1 != *m2) { + differences++; + } + ++m1; + ++m2; + } + + if (*m1 || *m2) { + return differences + 1; + } + + return differences; + +} + +void *strcpy(void *d, void *s) { + void *copy = d; + char *dest = (char *)d; + char *src = (char *)s; + while (*src) { + *dest = *src; + src++; + dest++; + } + return copy; +} + +fs_node_t *initrd_init(u32int addr) { + initrd = (char *)addr; + nroot_nodes = *((u32int *)(initrd)); + headers = (initrd_header_t *)(initrd + sizeof(char)*16); + initrd_data = (char *)headers + sizeof(initrd_header_t) * nroot_nodes; + + initrd_root = (fs_node_t *)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_root->name, "initrd"); + initrd_root->mask = initrd_root->uid = initrd_root->gid = 0; + initrd_root->inode = initrd_root->length = 0; + initrd_root->flags = FS_DIRECTORY; + initrd_root->read = 0; + initrd_root->write = 0; + initrd_root->open = 0; + initrd_root->close = 0; + initrd_root->readdir = &readdir_initrd; + initrd_root->finddir = &finddir_initrd; + initrd_root->ptr = 0; + initrd_root->impl = 0; + + initrd_dev = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_dev->name, "dev"); + initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0; + initrd_dev->flags = FS_DIRECTORY; + initrd_dev->read = 0; + initrd_dev->write = 0; + initrd_dev->open = 0; + initrd_dev->close = 0; + initrd_dev->readdir = &readdir_initrd; + initrd_dev->finddir = &finddir_initrd; + initrd_dev->ptr = 0; + initrd_dev->impl = 0; + + root_nodes = (fs_node_t*)kmalloc(sizeof(fs_node_t) * nroot_nodes); + + for (u32int i = 0; i < nroot_nodes; i++) { + strcpy(root_nodes[i].name, &headers[i].name); + root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0; + root_nodes[i].length = headers[i].length; + root_nodes[i].inode = i; + root_nodes[i].flags = FS_FILE; + root_nodes[i].read = &read_initrd; + root_nodes[i].write = 0; + root_nodes[i].readdir = 0; + root_nodes[i].finddir = 0; + root_nodes[i].open = 0; + root_nodes[i].close = 0; + root_nodes[i].impl = 0; + } + + return initrd_root; + +} + +u32int read_initrd(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer) { + initrd_header_t header = headers[node->inode]; + + if (offset >= header.length) { + return 0; + } + + if (offset + size > header.length) { + size = header.length - offset; + } + + memcpy(buffer, initrd_data + header.offset, size); + + return size; +} + +u32int write_initrd(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer) { + UNUSED(node); UNUSED(offset); UNUSED(size); + UNUSED(buffer); + + // system plików read-only + + return 0; +} + +void open_initrd(fs_node_t *node, + u8int read, + u8int write) { + UNUSED(node); UNUSED(read); UNUSED(write); + + // system plików in-memory, nic nie robimy +} + +void close_initrd(fs_node_t *node) { + UNUSED(node); + // system plików in-memory, nic nie robimy +} + +struct dirent *readdir_initrd(fs_node_t *node, + u32int index) { + if (node == initrd_root && index == 0) { + memcpy(dirent.name, "dev", 3); + dirent.name[3] = 0; + dirent.ino = 0; + return &dirent; + } + + if (index - 1 >= nroot_nodes) { + return NULL; + } + + memcpy(dirent.name, root_nodes[index-1].name, INITRD_NAME_LENGTH); + dirent.ino = root_nodes[index-1].inode; + + return &dirent; +} + +fs_node_t *finddir_initrd(fs_node_t *node, + char *name) { + + if (node == initrd_root && memcmp(name, "dev", 3) == 0) { + return initrd_dev; + } + + for (u32int i = 0; i < nroot_nodes; i++) { + if (strcmp(name, root_nodes[i].name) == 0) { + return &root_nodes[i]; + } + } + + return NULL; +} + diff --git a/src/generic/fs/vfs.c b/src/generic/fs/vfs.c new file mode 100644 index 0000000..a91f633 --- /dev/null +++ b/src/generic/fs/vfs.c @@ -0,0 +1,65 @@ +#include + +u32int read_fs(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer) { + if (node->read != NULL) { + return node->read(node, + offset, + size, + buffer); + } else { + return NULL; + } +} + +u32int write_fs(fs_node_t *node, + u32int offset, + u32int size, + u8int *buffer) { + if (node->write != NULL) { + return node->write(node, + offset, + size, + buffer); + } else { + return NULL; + } +} + +void open_fs(fs_node_t *node, + u8int read, + u8int write) { + UNUSED(read); UNUSED(write); + if (node->open != NULL) { + node->open(node); + } +} + +void close_fs(fs_node_t *node) { + if (node->close != NULL) { + node->close(node); + } +} + +struct dirent *readdir_fs(fs_node_t *node, + u32int index) { + if (node->readdir != NULL) { + return node->readdir(node, + index); + } else { + return NULL; + } +} + +fs_node_t *finddir_fs(fs_node_t *node, + char *name) { + if (node->finddir != NULL) { + return node->finddir(node, + name); + } else { + return NULL; + } +} + diff --git a/src/generic/mm/heap.c b/src/generic/mm/heap.c new file mode 100644 index 0000000..432f859 --- /dev/null +++ b/src/generic/mm/heap.c @@ -0,0 +1,566 @@ +#include + +#define STRUCTURES_SIZE (sizeof(block_header_t)+sizeof(block_footer_t)) + +heap_t kernel_heap; + +void *kmalloc(u32int size) { + return kalloc_int(size, 0, 1, 1, &kernel_heap); +} +void kfree(void *addr) { + kfree_int(addr, &kernel_heap); +} +void *kmalloc_a(u32int size) { + return kalloc_int(size, 1, 1, 1, &kernel_heap); +} + + +void init_heap(heap_t *heap, u32int min_address, u32int max_address, + u32int limit_max, u32int kernel, u32int rw) { + memset((unsigned char *)heap, 0, sizeof(heap_t)); + heap->min_address = min_address; + heap->max_address = max_address; + heap->marker1 = HEAP_MARKER; + heap->marker2 = HEAP_MARKER; + heap->max_id = 1; + heap->blocks[0] = (block_header_t *)min_address; + heap->limit_max = limit_max; + + // tworzenie początkowego 1. bloku + block_header_t *header = (block_header_t *)min_address; + block_footer_t *footer = (block_footer_t *) + (max_address - sizeof(block_footer_t)); + + for(u32int addr = ALIGN_DOWN(min_address); addr <= max_address; + addr += 0x1000) { + alloc_frame(get_page(addr, 1, current_directory),1,1); + } + + header->marker1 = HEAP_MARKER; + header->marker2 = HEAP_MARKER; + header->start = min_address; + header->size = max_address - min_address; + header->id = 0; + header->aligned = 0; + header->block = 0; + header->kernel = kernel; + header->rw = rw; + + footer->marker1 = HEAP_MARKER; + footer->marker2 = HEAP_MARKER; + footer->header = min_address; + + ASSERT(sanity_check(heap)); + +} + +void destroy_heap(heap_t *heap) { + ASSERT(heap->marker1); + ASSERT(heap->marker2); + + for(u32int addr = ALIGN_DOWN(heap->min_address); addr <= heap->max_address; + addr += 0x1000) { + if (addr >= kernel_full_end()) { + free_frame(get_page(addr, 1, current_directory)); + } + } + + memset((unsigned char *)heap, 0, sizeof(heap_t)); + +} + +int sanity_check(heap_t *heap) { + + for (u32int i = 0; i < heap->max_id; i++) { + block_header_t *header = heap->blocks[i]; + block_footer_t *footer = (block_footer_t *) + (heap->blocks[i]->start + heap->blocks[i]->size + - sizeof(block_footer_t)); + ASSERT(header->marker1 == HEAP_MARKER); + ASSERT(header->marker2 == HEAP_MARKER); + ASSERT(footer->marker1 == HEAP_MARKER); + ASSERT(footer->marker2 == HEAP_MARKER); + } + + return 1; +} + +int find_smallest_gap(u32int size, u32int aligned, heap_t *heap) { + int smallest_id = -1; + if (aligned) { + // musimy wyrównać region (rozmiar) + size = ((size - 1) / ALIGNMENT_SIZE + 1) * ALIGNMENT_SIZE; + } + + u32int needed_size = size + sizeof(block_header_t) + + sizeof(block_footer_t); + + for (u32int i = 0; i < heap->max_id; i++) { + if (!heap->blocks[i]->block) { + // mamy "dziurę" + u32int gap_start = heap->blocks[i]->start; + u32int block_start = gap_start; + u32int gap_size = heap->blocks[i]->size; + + if (aligned) { + // zdefiniowano wyrównywanie, zaokrąglam do góry adres + block_start = ((gap_start - 1) / ALIGNMENT_SIZE + 1) + * ALIGNMENT_SIZE - sizeof(block_header_t); + } + + // uwzględniamy rozmiar wewnętrznych struktur + if (block_start + needed_size > gap_start + gap_size) { + continue; // za mała przestrzeń + } + + smallest_id = i; + break; + // spełnia wymagania, najmniejsza bo posortowane + // wg. rozmiaru bloku + } + } + + return smallest_id; +} + +// FIXME co zrobić jeśli wolnego miejsca za mało by nawet +// struktury tam wcisnąć? +// +// 1. Pomysł - przygarnąć na koniec jakiegoś bloku zarezerwowanego +// dać mu więcej niż potrzebuje, nie będzie się skarżył + +u32int insert_block(u32int size, u32int aligned, u32int kernel, u32int rw, + heap_t *heap, u32int id) { + u32int block_size = size; + if (aligned) { + block_size = ALIGN_UP(block_size); + } + block_size += sizeof(block_header_t) + sizeof(block_footer_t); + u32int gap_start = heap->blocks[id]->start; + u32int gap_end = gap_start + heap->blocks[id]->size; + u32int block_start = gap_start; + if (aligned) { + block_start = ALIGN_UP(block_start+sizeof(block_header_t)) + - sizeof(block_header_t); + } + u32int block_end = block_start + block_size; + u32int gap_before_size = block_start - gap_start; + u32int gap_after_size = gap_end - block_end; + + block_header_t *left_header = (block_header_t *)gap_start; + block_header_t *header = (block_header_t *)block_start; + block_header_t *right_header = (block_header_t *)block_end; + block_header_t c_left = *left_header; + block_header_t c = *header; + block_header_t c_right = *right_header; + block_footer_t *left_footer = (block_footer_t *) + (block_start - sizeof(block_footer_t)); + block_footer_t *footer = (block_footer_t *) + (block_end - sizeof(block_footer_t)); + block_footer_t *right_footer = (block_footer_t *) + (gap_end - sizeof(block_footer_t)); + + int blocks_offset = 0; + // jeśli cały zaalokowany block wypełnia dziurę w całości dziurę + + heap->blocks[id] = NULL; // usuwamy blok z rejestru + + if (gap_before_size >= STRUCTURES_SIZE) { + blocks_offset++; + } else if (gap_before_size > 0) { + // TODO trzeba znaleźć poprzednika + // a co jeśli go nie ma np. jest na początku + + block_footer_t *preceeder_footer + = (block_footer_t *)((u32int)left_header - sizeof(block_footer_t)); + + ASSERT(preceeder_footer->marker1 == HEAP_MARKER); + ASSERT(preceeder_footer->marker2 == HEAP_MARKER); + + block_header_t *preceeder_header + = (block_header_t *)(preceeder_footer->header); + + ASSERT(preceeder_header->marker1 == HEAP_MARKER); + ASSERT(preceeder_header->marker2 == HEAP_MARKER); + + preceeder_header->size += gap_before_size; + + block_footer_t copy = *preceeder_footer; + preceeder_footer = (block_footer_t *) + ((u32int)preceeder_header->start + preceeder_header->size + - sizeof(block_footer_t)); + + *preceeder_footer = copy; + + } + + heap->blocks[id] = NULL; // czyścimy miejsce, w którym już leżał + + if (gap_after_size >= STRUCTURES_SIZE) { + blocks_offset++; + } else if (gap_after_size > 0) { + // TODO + block_size += gap_after_size; + footer = (block_footer_t *) + (block_start + block_size - sizeof(block_footer_t)); + // poprzednik przyjmie więcej niż chciał bez problemu + } + + // FIXME a co jeśli jakaś wolna przestrzeń jest za mała by + // nawet wcisnąć tam struktury bloku? + // teoretycznie można spróbować dokleić na koniec poprzednika + // ale problem pojawia się w przypadku 1. elementu + // teoretycznie można zapisać sobie np. w heapie, ale to dziwne + // rozwiązanie. + + + + + /** + * Usunięte stare deskryptory z tablicy + */ + + span_items(heap); + + if (blocks_offset >= 2) { + *left_header = c_left; + } + + *header = c; + + if (blocks_offset >= 1) { + *right_header = c_right; + } + + if (blocks_offset >= 2) { + left_header->size = gap_before_size; + left_header->block = 0; + + left_footer->marker1 = HEAP_MARKER; + left_footer->marker2 = HEAP_MARKER; + left_footer->header = left_header->start; + + } + + if (blocks_offset >= 1) { + right_header->start = block_end; + right_header->size = gap_after_size; + right_header->marker1 = HEAP_MARKER; + right_header->marker2 = HEAP_MARKER; + right_header->block = 0; + + right_footer->marker1 = HEAP_MARKER; + right_footer->marker2 = HEAP_MARKER; + right_footer->header = right_header->start; + + } + + header->start = block_start; + header->size = block_size; + header->marker1 = HEAP_MARKER; + header->marker2 = HEAP_MARKER; + header->aligned = aligned; + header->kernel = kernel; + header->rw = rw; + header->block = 1; + + footer->marker1 = HEAP_MARKER; + footer->marker2 = HEAP_MARKER; + footer->header = header->start; + + if (blocks_offset >= 2) { + insert_block_array(heap, left_header, heap->max_id); + } + insert_block_array(heap, header, heap->max_id); + if (blocks_offset >= 1) { + insert_block_array(heap, right_header, heap->max_id); + } + + return block_start + sizeof(block_header_t); +} + +void *kalloc_int(u32int size, u32int aligned, u32int kernel, u32int rw, + heap_t *heap) { + + // FIXME owszem wypełniamy struktury block_header_t + // ale nie naprawiamy wskaźników do niego prowadzących + // w "blocks" + + if (aligned) { + // jeśli potrzebujemy wyrównać, wyrównujemy rozmiar + size = ALIGN_UP(size); + } + + int smallest_id = find_smallest_gap(size, aligned, heap); + int needed_size = sizeof(block_header_t) + sizeof(block_footer_t) + + size; + + void *ret = NULL; + + if (smallest_id >= 0) { + // znaleźliśmy wolną przestrzeń w dotychczasowej + // przesuwamy o 1 wskaźniki + ret = (void *)insert_block(size,aligned,kernel,rw,heap,smallest_id); + } else { + // rozszerzamy na prawo + u32int block_start = heap->max_address; + if (aligned) { + // wyrównujemy adres do jednostki + block_start = ALIGN_UP(block_start); + } + + u32int max_address = block_start + needed_size; + if (max_address >= heap->limit_max) { + printf("New failed max address: 0x%x\n", + max_address); + PANIC("Max limit of heap was exceeded"); + return NULL; + } + + for (u32int addr = ALIGN_UP(heap->max_address); + addr < max_address; addr += 0x1000) { + alloc_frame(get_page(addr,1, current_directory), 1,rw); + } + + block_header_t *new_header = (block_header_t *)heap->max_address; + heap->max_address = max_address; + + insert_block_array(heap, new_header, heap->max_id); + // wstawiliśmy nowy blok w odpowiednie miejsce + // nie musieliśmy spanować, bo nie robiliśmy dziur (tylko + // dodawaliśmy na koniec) + + new_header->marker1 = HEAP_MARKER; + new_header->start = block_start; + new_header->size = needed_size; + new_header->aligned = aligned; + new_header->kernel = kernel; + new_header->rw = rw; + new_header->block = 1; + new_header->marker2 = HEAP_MARKER; + block_footer_t *new_footer = (block_footer_t *) + (new_header->start + new_header->size - sizeof(block_footer_t)); + new_footer->marker1 = HEAP_MARKER; + new_footer->marker2 = HEAP_MARKER; + new_footer->header = new_header->start; + ret = (void *)(block_start + sizeof(block_header_t)); + } + + ASSERT(sanity_check(heap)); + return ret; +} + +// TODO sprawdź, przetestuj funkcję kfree_int, ale wygląda ok. + +void kfree_int(void *addr, heap_t *heap) { + u32int a = (u32int)addr; + block_header_t *header = (block_header_t *)(a - sizeof(block_header_t)); + block_footer_t *footer = (block_footer_t *) + ((u32int)header + header->size - sizeof(block_footer_t)); + + ASSERT(header->marker1 == HEAP_MARKER); + ASSERT(header->marker2 == HEAP_MARKER); + + ASSERT(footer->marker1 == HEAP_MARKER); + ASSERT(footer->marker2 == HEAP_MARKER); + + ASSERT(header->block); + + u32int block_end = (u32int)header + header->size; + if (block_end >= heap->max_address) { + // blok nasz jest ostatnim na prawo + // trzeba zwęzić + + for (u32int addr = ALIGN_UP(header->start); addr < heap->max_address; + addr += 0x1000) { + free_frame(get_page(addr, 0, current_directory)); + } + + heap->max_address = header->start; + + heap->blocks[header->id] = NULL; // usuwamy jego adres z bloków + span_items(heap); // usuwamy dziurę w tablicy + } else { + // blok nasz jest gdzieś w środku + block_footer_t *left_footer = + (block_footer_t *)((u32int)header - sizeof(block_footer_t)); + block_header_t *left_header = (block_header_t *) + (left_footer->header); + + block_header_t *right_header = (block_header_t *) + ((u32int)header + header->size); + block_footer_t *right_footer = + (block_footer_t *) + ((u32int)right_header + right_header->size-sizeof(block_footer_t)); + + int rA = 0; + + if ((u32int)left_footer >= heap->min_address) { + rA = 1; + ASSERT(left_header->marker1 == HEAP_MARKER); + ASSERT(left_header->marker2 == HEAP_MARKER); + + ASSERT(left_footer->marker1 == HEAP_MARKER); + ASSERT(left_footer->marker2 == HEAP_MARKER); + } + + int rB = 0; + + if ((u32int)right_header <= heap->max_address) { + rB = 1; + ASSERT(right_header->marker1 == HEAP_MARKER); + ASSERT(right_header->marker2 == HEAP_MARKER); + + ASSERT(right_footer->marker1 == HEAP_MARKER); + ASSERT(right_footer->marker2 == HEAP_MARKER); + } + + header->block = 0; + u32int start = header->start; + u32int end = start + header->size; + + if (rA && !(left_header->block)) { + start = left_header->start; + heap->blocks[left_header->id] = NULL; + // usuwamy nadmiarowy gap + } + + if (rB && !(right_header->block)) { + end = right_header->start +right_header->size; + heap->blocks[right_header->id] = NULL; + // usuwamy nadmiarowy gap + } + + heap->blocks[header->id] = NULL; // siebie też usuwamy + + u32int size = end-start; + block_header_t *new_header = (block_header_t *)start; + block_footer_t *new_footer = (block_footer_t *) + (end - sizeof(block_footer_t)); + + new_footer->header = start; + new_header->size = size; + new_header->block = 0; + span_items(heap); + + insert_block_array(heap,new_header, heap->max_id); + + } + + ASSERT(sanity_check(heap)); + +} + +void span_items(heap_t *heap) { + if (heap == NULL) { + PANIC("Heap cannot be NULL"); + return; + } + + ASSERT(heap->marker1 == HEAP_MARKER); + ASSERT(heap->marker2 == HEAP_MARKER); + + int idx = 0; + + for (u32int i = 0; i < heap->max_id; i++) { + if (heap->blocks[i]) { + heap->blocks[idx] = heap->blocks[i]; + heap->blocks[idx]->id = idx; + idx++; + } + } + + heap->max_id = idx; + +} + +int find_idx_to_insert(heap_t *heap, block_header_t *header, u32int max_id) { + for (u32int i = 0; i < max_id; i++) { + if (!heap->blocks[i]) { + continue; + } + + if (heap->blocks[i]->size >= header->size) { + return i; + } + + } + + return max_id; + +} + +void insert_block_array(heap_t *heap, block_header_t *header, u32int max_id) { + if (heap->max_id + 1 >= MAX_BLOCKS) { + PANIC("NO FREE MEMORY DESCRIPTOR SLOTS"); + return; + } + + u32int idx = find_idx_to_insert(heap,header,max_id); + for (u32int i = max_id; i >= idx + 1; i--) { + heap->blocks[i] = heap->blocks[i-1]; + heap->blocks[i]->id = i; + } + + heap->blocks[idx] = header; + heap->blocks[idx]->id = idx; + heap->max_id++; // dodaliśmy nowy element +} + +void dump_heap(heap_t *heap) { + log("Header min address 0x%x, max address: 0x%x\n", + heap->min_address, + heap->max_address); + + block_header_t *header = (block_header_t *)heap->min_address; + + printf("----------- START OF MEMORY MAP-----------\n"); + log("----------- START OF MEMORY MAP-----------\r\n"); + printf("Descriptor table: ["); + for (u32int i = 0; i < heap->max_id-1; i++) { + printf("0x%x(%d), ", (u32int)heap->blocks[i], heap->blocks[i]->size); + } + printf("0x%x(%d)]\n", heap->blocks[heap->max_id-1], + heap->blocks[heap->max_id-1]->size); + printf("Min address: 0x%x, max address: 0x%x, limit max: 0x%x\n", + heap->min_address, + heap->max_address, + heap->limit_max); + + while ((u32int)header < heap->max_address) { + ASSERT(header->marker1 == HEAP_MARKER); + ASSERT(header->marker2 == HEAP_MARKER); + + printf("[0x%x(0x%x)-0x%x(0x%x)] - %d(%d) %s [%c%c%c]\n", + header->start, + header->start+sizeof(block_header_t), + header->start + header->size, + header->start + header->size - sizeof(block_footer_t), + header->size - sizeof(block_header_t) - sizeof(block_footer_t), + header->id, + header->block ? "BLOCK" : "FREE", + header->kernel ? 'k' : ' ', + header->rw ? 'w' : 'r', + header->aligned ? 'a': ' '); + + log("[0x%x(0x%x)-0x%x(0x%x)] - %d(%d) %s [%c%c%c]\r\n", + header->start, + header->start+sizeof(block_header_t), + header->start + header->size, + header->start + header->size - sizeof(block_footer_t), + header->size - sizeof(block_header_t) - sizeof(block_footer_t), + header->id, + header->block ? "BLOCK" : "FREE", + header->kernel ? 'k' : ' ', + header->rw ? 'w' : 'r', + header->aligned ? 'a': ' '); + + + header = (block_header_t *)((u32int)header + header->size); + + } + + printf("----------- END OF MEMORY MAP-------------\n"); + log("----------- END OF MEMORY MAP-------------\r\n"); + +} diff --git a/test/test-frames.c b/test/test-frames.c new file mode 100644 index 0000000..505d860 --- /dev/null +++ b/test/test-frames.c @@ -0,0 +1,199 @@ +#include + +multiboot_info_t *m; +u32int mem_lower; +u32int mem_upper; + +void pre_init(unsigned long magic) { + vga_init(); + log("Zainicjalizowano ekran\r\n"); + init_serial(); + log("Zainicjalizowano port seryjny\r\n"); + + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printf ("Invalid magic number: 0x%x\n", (unsigned) magic); + PANIC("INVALID MULTIBOOT MAGIC"); + return; + } + + if (CHECK_FLAG(m->flags, 0)) { + mem_lower = m->mem_lower; + mem_upper = m->mem_upper; + printf("mem_lower: %uKB, mem_upper: %uKB\n", + m->mem_lower, m->mem_upper); + } + + if (CHECK_FLAG(m->flags, 1)) { + printf("boot device: %s\n", (char *)m->boot_device); + } + + if (CHECK_FLAG(m->flags, 2)) { + printf("command line: %s\n", (char *)m->cmdline); + } + + if (CHECK_FLAG(m->flags, 3)) { + printf("nr of modules: %u\n", m->mods_count); + multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr; + for (u32int i = 0; i < m->mods_count; i++) { + printf("module nr %u: start: 0x%x, end: 0x%x, cmdline: %s\n", + i, + modules[i].mod_start, + modules[i].mod_end, + modules[i].cmdline); + } + } + + gdt_install(); + log("Zainstalowano struktury GDT\r\n"); + idt_install(); + log("Zainstalowano struktury IDT (przerwania)\r\n"); + isrs_install(); + log("Zainstalowano procedury obsługujące przerwania\r\n"); + + initialise_paging2(); + + irq_install(); + log("Zainstalowano przerwania irq\r\n"); + timer_install(); + log("Zainstalowano systemowy timer\r\n"); + kbd_install(); + log("Zainicjalizowano klawiature\r\n"); + sti(); + + log("Wlaczono przerwania\r\n"); + log("Start: 0x%x\r\n", kernel_start()); + log("End: 0x%x\r\n", kernel_end()); + log("End (with stack): 0x%x\r\n", kernel_full_end()); + log("Size: 0x%x\r\n", kernel_end()-kernel_start()); + log("Size (with stack): 0x%x\r\n", kernel_full_end()-kernel_start()); + + +} + +void post_destroy() { + cli(); + disablePaging(); + sti(); + init_acpi(); + AcpiEnable(); + AcpiPowerOff(); + + for (;;) { + hlt(); + } + +} + +u32int tests_count = 0; +u32int tests_succeeded_count = 0; + +void test_ident_allocation() { + log("Test %s started\n", __FUNCTION__); + // na początku, przy uruchomieniu + ++tests_count; + + dump_frames(); + u32int allocated1 = frames_allocated(); + log("Frames allocated number: 0x%x\n", allocated1); + + u32int addr = 0x200 * 0x1000; + ident_alloc_frame(get_page(addr, 1, kernel_directory), + 1, + 1, + addr); + + if (!test_frame(addr)) { + log("test ident failed. Requested addr is not 1:1 mapped\r\n"); + return; + } + + dump_frames(); + u32int allocated2 = frames_allocated(); + log("Frames allocated number: 0x%x\n", allocated2); + + if (allocated2 != allocated1 + 1) { + log("Number of frames allocated has not grown by 1\r\n"); + return; + } + + free_frame(get_page(addr, 0, kernel_directory)); + + dump_frames(); + u32int allocated3 = frames_allocated(); + + if (allocated1 != allocated3) { + log("Number of frames has not lowered by 1, not equal before\r\n"); + return; + } + + // na końcu, po uruchomieniu + ++tests_succeeded_count; + log("Test %s ended\n", __FUNCTION__); +} + +void test_allocation() { + log("Test %s started\n", __FUNCTION__); + // na początku, przy uruchomieniu + ++tests_count; + + dump_frames(); + u32int allocated1 = frames_allocated(); + log("Frames allocated number: 0x%x\n", allocated1); + + u32int addr = 0x200 * 0x1000; + page_t *page = get_page(addr, 1, kernel_directory); + + alloc_frame(page, 1, 1); + + if (!test_frame(page->frame * 0x1000)) { + log("test allocation failed. Requested addr is not mapped\r\n"); + return; + } + + dump_frames(); + u32int allocated2 = frames_allocated(); + log("Frames allocated number: 0x%x\n", allocated2); + + if (allocated2 != allocated1 + 1) { + log("Number of frames allocated has not grown by 1\r\n"); + return; + } + + free_frame(get_page(addr, 0, kernel_directory)); + + dump_frames(); + u32int allocated3 = frames_allocated(); + + if (allocated1 != allocated3) { + log("Number of frames has not lowered by 1, not equal before\r\n"); + return; + } + + // na końcu, po uruchomieniu + ++tests_succeeded_count; + log("Test %s ended\n", __FUNCTION__); +} + + +void run_tests() { + test_ident_allocation(); + test_allocation(); + + if (tests_count == tests_succeeded_count){ + log("ALL TESTS PASSED\r\n"); + } else { + log("SOME TESTS FAILED\r\n"); + } +} + + +int cmain(unsigned long magic, multiboot_info_t *mbi) { + m = mbi; + pre_init(magic); + printf("Zaladowano system useless os\n"); + + run_tests(); + + post_destroy(); + return 0; +} diff --git a/test/test-heap.c b/test/test-heap.c new file mode 100644 index 0000000..f6b4f79 --- /dev/null +++ b/test/test-heap.c @@ -0,0 +1,99 @@ +#include + +multiboot_info_t *m; +u32int mem_lower; +u32int mem_upper; + +void pre_init(unsigned long magic) { + vga_init(); + log("Zainicjalizowano ekran\r\n"); + init_serial(); + log("Zainicjalizowano port seryjny\r\n"); + + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printf ("Invalid magic number: 0x%x\n", (unsigned) magic); + PANIC("INVALID MULTIBOOT MAGIC"); + return; + } + + if (CHECK_FLAG(m->flags, 0)) { + mem_lower = m->mem_lower; + mem_upper = m->mem_upper; + printf("mem_lower: %uKB, mem_upper: %uKB\n", + m->mem_lower, m->mem_upper); + } + + if (CHECK_FLAG(m->flags, 1)) { + printf("boot device: %s\n", (char *)m->boot_device); + } + + if (CHECK_FLAG(m->flags, 2)) { + printf("command line: %s\n", (char *)m->cmdline); + } + + if (CHECK_FLAG(m->flags, 3)) { + printf("nr of modules: %u\n", m->mods_count); + multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr; + for (u32int i = 0; i < m->mods_count; i++) { + printf("module nr %u: start: 0x%x, end: 0x%x, cmdline: %s\n", + i, + modules[i].mod_start, + modules[i].mod_end, + modules[i].cmdline); + } + } + + gdt_install(); + log("Zainstalowano struktury GDT\r\n"); + idt_install(); + log("Zainstalowano struktury IDT (przerwania)\r\n"); + isrs_install(); + log("Zainstalowano procedury obsługujące przerwania\r\n"); + + initialise_paging2(); + + irq_install(); + log("Zainstalowano przerwania irq\r\n"); + timer_install(); + log("Zainstalowano systemowy timer\r\n"); + kbd_install(); + log("Zainicjalizowano klawiature\r\n"); + sti(); + + log("Wlaczono przerwania\r\n"); + log("Start: 0x%x\r\n", kernel_start()); + log("End: 0x%x\r\n", kernel_end()); + log("End (with stack): 0x%x\r\n", kernel_full_end()); + log("Size: 0x%x\r\n", kernel_end()-kernel_start()); + log("Size (with stack): 0x%x\r\n", kernel_full_end()-kernel_start()); + + +} + +void post_destroy() { + cli(); + disablePaging(); + sti(); + init_acpi(); + AcpiEnable(); + AcpiPowerOff(); + + for (;;) { + hlt(); + } + +} + +int cmain(unsigned long magic, multiboot_info_t *mbi) { + m = mbi; + pre_init(magic); + printf("Zaladowano system useless os\n"); + + for (u32int i = 0; i < 10; i++) { + printf("."); + sleep(1); + } + + post_destroy(); + return 0; +} diff --git a/tools/generator/Makefile b/tools/generator/Makefile new file mode 100644 index 0000000..6efb63d --- /dev/null +++ b/tools/generator/Makefile @@ -0,0 +1,20 @@ +CXX = gcc +SOURCES = $(wildcard *.c) +BINARIES = $(SOURCES:%.c=%.c.o) + +all: compile + +compile: $(BINARIES) + $(CXX) -g -o ./initrd $^ + +%.c.o: %.c + $(CXX) -g -I../../include -std=gnu99 -pedantic -c -o $@ $< + +.PHONY: clean initrd + +clean: + rm -f *.o initrd + +initrd: all + ./initrd file1.txt file2.txt + diff --git a/tools/generator/initrd.c b/tools/generator/initrd.c new file mode 100644 index 0000000..0300bf9 --- /dev/null +++ b/tools/generator/initrd.c @@ -0,0 +1,139 @@ +#include + +int main(int argc, char **argv) { + + if (argc < 2) { + fprintf(stderr, "No input files\n"); + return 1; + } + + fprintf (stderr, "Rozmiar struktury: %x\n", sizeof(initrd_header_t)); + + for (u32int i = 1; i < argc; i++) { + fprintf(stderr, "File nr %d to embed: '%s'\n", + i, argv[i]); + } + + u32int nrFiles = 0; + + FILE *f = fopen("initrd.img", "w+"); + if (!f) { + fprintf(stderr, "I cannot open file 'initrd.img for write\n"); + return 2; + } + + u32int offset = 0; + u32int buffer[12]; + memset(buffer, 0, sizeof(buffer)); + fwrite(&nrFiles, 4, 1, f); // teraz tylko dla wyrównania danych + fwrite(buffer, 1, 12, f); // wyrównanie do 16 + + initrd_header_t *headers = (initrd_header_t *) + malloc(sizeof(initrd_header_t) * (argc - 1)); + memset(headers, 0, sizeof(initrd_header_t) * (argc - 1)); + + fprintf(stderr, "Filling in headers\n"); + + for (u32int i = 1; i < argc; i++) { + fprintf (stderr, "writing file %s to initrd.img\n", + argv[i]); + + FILE *fAttachment = fopen(argv[i], "r"); + if (!fAttachment) { + fprintf (stderr, "cannot open attachment %s to read\n", + argv[i]); + continue; + } + + if (fseek(fAttachment, 0, SEEK_END) < 0) { + fprintf (stderr, "cannot rewind attachment %s to the end\n", + argv[i]); + continue; + } + + long size = ftell(fAttachment); + if (size < 0) { + fprintf (stderr, "cannot acquire current position in file %s\n", + argv[i]); + continue; + } + + fprintf (stderr, "Rozmiar pliku: 0x%x\n", size); + + if (fseek(fAttachment, 0, SEEK_SET) < 0) { + fprintf (stderr, "cannot rewind attachment %s to the start\n", + argv[i]); + continue; + } + + fclose(fAttachment); // zamykamy, na co nam jest jeszcze potrzebny + + headers[nrFiles].magic = INITRD_MAGIC; + char *bName = basename(argv[i]); + fprintf (stderr, "Base name: %s\n", bName); + strncpy(headers[nrFiles].name ,bName, INITRD_NAME_LENGTH); + headers[nrFiles].length = size; + headers[nrFiles].offset = offset; + offset += size; + + fprintf (stderr, "[%d] header MAGIC: 0x%x\n", nrFiles, + headers[nrFiles].magic); + fprintf (stderr, "[%d] header name: '%s'\n", nrFiles, + headers[nrFiles].name); + fprintf (stderr, "[%d] header offset: 0x%x\n", nrFiles, + headers[nrFiles].offset); + fprintf (stderr, "[%d] header length: 0x%x\n", nrFiles, + headers[nrFiles].length); + + nrFiles++; + // zwiększamy liczbę plików, które zapisaliśmy faktycznie + // do initrd.img + + } + + fwrite(headers, 1, sizeof(initrd_header_t) * nrFiles, f); + + // zapisane nagłówki initrd. + + fprintf(stderr, "Filling in file content\n"); + + u32int idx = 0; + + for (u32int i = 1; i < argc; i++) { + fprintf (stderr, "writing file %s to initrd.img\n", + argv[i]); + + FILE *fAttachment = fopen(argv[i], "r"); + if (!fAttachment) { + fprintf (stderr, "cannot open attachment %s to read\n", + argv[i]); + continue; + } + + char *content = (char *)malloc(sizeof(char) * headers[idx].length); + if (!content) { + fprintf (stderr, "cannot allocate buffer for file content\n"); + continue; + } + int bytesRead = fread(content, 1, headers[idx].length, fAttachment); + if (bytesRead < 0) { + fprintf (stderr, "cannot read open attachment file: %s\n", + argv[i]); + continue; + } + + fclose(fAttachment); // zamykamy, na co nam jest jeszcze potrzebny + + fwrite(content, 1, headers[idx].length, f); + free(content); + idx++; + } + + fseek(f, 0, SEEK_SET); + + fwrite(&nrFiles, 4, 1, f); // nadpisujemy prawidłową liczbę plików + + fclose(f); + free(headers); + return 0; +}