Unfortunately not revisioned version of my earaly osdev rather plays.
parent
4cca53a2b9
commit
1e3dc4e18b
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
Prosty system operacyjny protected mode unixowaty.
|
||||||
|
Tworzony w celach edukacyjnych, domyślnie ma mieć architekturę mikrokernela.
|
|
@ -0,0 +1 @@
|
||||||
|
assert na kfree wywala się ponieważ błędne są markery dla 2. adresu ?
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
Tomasz Półgrabia
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef __ACPI2__H
|
||||||
|
#define __ACPI2__H
|
||||||
|
|
||||||
|
#include <generic.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <pit.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef __BASIC_H__
|
||||||
|
#define __BASIC_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __CONSOLE_H__
|
||||||
|
#define __CONSOLE_H__
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#define VGA_ADDRESS 0xB8000
|
||||||
|
#define VGA_WIDTH 80
|
||||||
|
#define VGA_HEIGHT 25
|
||||||
|
#define COLOURS 0x0F
|
||||||
|
#define PRINTABLE(c) (c >= ' ')
|
||||||
|
|
||||||
|
#include <serial.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef __FRAME_H__
|
||||||
|
#define __FRAME_H__
|
||||||
|
|
||||||
|
#include <basic.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <generic.h>
|
||||||
|
#include <page.h>
|
||||||
|
|
||||||
|
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
|
|
@ -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
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef __FS_INITRD_H__
|
||||||
|
#define __FS_INITRD_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <fs/vfs.h>
|
||||||
|
#include <heap.h>
|
||||||
|
#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
|
|
@ -0,0 +1,85 @@
|
||||||
|
#ifndef __FS_VFS__
|
||||||
|
#define __FS_VFS__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <generic.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -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
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef __GENERIC_H__
|
||||||
|
#define __GENERIC_H__
|
||||||
|
|
||||||
|
#include <console.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef __HEAP_H__
|
||||||
|
#define __HEAP_H__
|
||||||
|
|
||||||
|
#include <generic.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <frame.h>
|
||||||
|
#include <paging.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef __IDT_H__
|
||||||
|
#define __IDT_H__
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef __IO_H__
|
||||||
|
#define __IO_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef __IRQ_H__
|
||||||
|
#define __IRQ_H__
|
||||||
|
|
||||||
|
#include <isr.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <basic.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __ISR_H__
|
||||||
|
#define __ISR_H__
|
||||||
|
|
||||||
|
#include <console.h>
|
||||||
|
#include <idt.h>
|
||||||
|
#include <serial.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __KBD_H__
|
||||||
|
#define __KBD_H__
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
#include <isr.h>
|
||||||
|
#include <irq.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <generic.h>
|
||||||
|
|
||||||
|
extern unsigned char kbdus[128];
|
||||||
|
|
||||||
|
int keyboard_handler(struct regs *r);
|
||||||
|
int kbd_install();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef __MEM_H__
|
||||||
|
#define __MEM_H__
|
||||||
|
|
||||||
|
#include <multiboot.h>
|
||||||
|
#include <generic.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
extern u32int end;
|
||||||
|
extern void disablePaging();
|
||||||
|
extern multiboot_info_t *m;
|
||||||
|
extern u32int mem_lower;
|
||||||
|
extern u32int mem_upper;
|
||||||
|
|
||||||
|
#endif
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef __PAGE_H__
|
||||||
|
#define __PAGE_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef __PAGING_H__
|
||||||
|
#define __PAGING_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <mem.h>
|
||||||
|
#include <isr.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <isr.h>
|
||||||
|
#include <heap.h>
|
||||||
|
#include <generic.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <page.h>
|
||||||
|
#include <frame.h>
|
||||||
|
#include <irq.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef __PIT_H__
|
||||||
|
#define __PIT_H__
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <irq.h>
|
||||||
|
#include <generic.h>
|
||||||
|
|
||||||
|
int timer_phase(int hz);
|
||||||
|
int timer_handler(struct regs *r);
|
||||||
|
int timer_install();
|
||||||
|
int sleep(double sec);
|
||||||
|
#endif
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef __SERIAL_H__
|
||||||
|
#define __SERIAL_H__
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
#include <console.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef __STRINGS_H__
|
||||||
|
#define __STRINGS_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <console.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef __SYSTEM_H__
|
||||||
|
#define __SYSTEM_H__
|
||||||
|
|
||||||
|
#include <mem.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <gdt.h>
|
||||||
|
#include <idt.h>
|
||||||
|
#include <isr.h>
|
||||||
|
#include <irq.h>
|
||||||
|
#include <pit.h>
|
||||||
|
#include <basic.h>
|
||||||
|
#include <kbd.h>
|
||||||
|
#include <paging.h>
|
||||||
|
#include <serial.h>
|
||||||
|
#include <heap.h>
|
||||||
|
#include <acpi/acpi2.h>
|
||||||
|
#include <multiboot.h>
|
||||||
|
#include <fs/initrd.h>
|
||||||
|
#include <frame.h>
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef __TASK_COPY__
|
||||||
|
#define __TASK_COPY__
|
||||||
|
|
||||||
|
#include <page.h>
|
||||||
|
#include <heap.h>
|
||||||
|
#include <task/process.h>
|
||||||
|
|
||||||
|
page_directory_t *clone_directory(page_directory_t *src);
|
||||||
|
page_table_t *clone_table(page_table_t *src, u32int *phys);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef __TASK_FORK__
|
||||||
|
#define __TASK_FORK__
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __TASK_PROCESS_H__
|
||||||
|
#define __TASK_PROCESS_H__
|
||||||
|
|
||||||
|
void copy_page_physical(u32int src, u32int dest);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
||||||
|
menuentry "myos" {
|
||||||
|
multiboot /boot/myos.bin
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
menuentry "myos" {
|
||||||
|
multiboot /boot/myos.bin
|
||||||
|
}
|
Binary file not shown.
|
@ -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 = .;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
#include <acpi/acpi2.h>
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,209 @@
|
||||||
|
#include <console.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <gdt.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <idt.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include <irq.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
#include <isr.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include <kbd.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
#include <system.h>
|
||||||
|
#include <acpi/acpi2.h>
|
||||||
|
#include <fs.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include <pit.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <serial.h>
|
||||||
|
|
||||||
|
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++);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
|
@ -0,0 +1,158 @@
|
||||||
|
#include <frame.h>
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
#include <paging.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include <task/copy.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
#include <task/fork.h>
|
|
@ -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
|
|
@ -0,0 +1,177 @@
|
||||||
|
#include <fs/initrd.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include <fs/vfs.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,566 @@
|
||||||
|
#include <heap.h>
|
||||||
|
|
||||||
|
#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");
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
#include <system.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include <system.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
#include <fs/initrd.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue