Леночка

This commit is contained in:
mykola2312 2019-03-29 00:27:42 +02:00
commit 00318a6b5e
193 changed files with 81446 additions and 0 deletions

1265
.bochsrc Normal file

File diff suppressed because it is too large Load diff

124
Makefile Normal file
View file

@ -0,0 +1,124 @@
OLD_KOBJ=multiboot.o kmain.o vga_terminal.o stdlib.o x86stdlib.o \
gdt.o x86gdt.o pic.o idt.o x86idt.o x86int.o string.o \
paging.o x86utils.o x86_utils.o keyboard.o exceptions.o \
memory.o pci.o x86io.o pit.o ahci.o
KOBJ=start.o kmain.o x64io.o stdlib.o string.o vga_terminal.o \
x64stdlib.o va_list.o idt.o x64idt.o x64ints.o pic.o pit.o \
exceptions.o keyboard.o paging.o multiboot.o lvalloc.o \
pci.o ahci.o disk.o fat.o heap.o x64utils.o file.o \
x64font.o video.o bmp.o
LOBJ=loader.o lmain.o x86io.o x86stdlib.o x86gdt.o stdlib.o \
string.o vga_terminal.o gdt.o x86enter64.o memory.o idt.o \
exceptions.o x86idt.o x86int.o
KSRC_DIR=kernel/
LSRC_DIR=loader/
KOBJ_DIR=kobj/
LOBJ_DIR=lobj/
INCLUDE=kernel/
LINCLUDE=loader/
TOOLCHAIN32=/home/adriane/opt/cross
HDISK=/home/adriane/lenochka_vm/hdisk.img
CC32=$(TOOLCHAIN32)/bin/i686-elf-gcc
AS32=nasm
LD32=$(TOOLCHAIN32)/i686-elf/bin/ld
TOOLCHAIN=/home/adriane/opt64/cross
CC=$(TOOLCHAIN)/bin/x86_64-elf-gcc
AS=nasm
LD=$(TOOLCHAIN)/x86_64-elf/bin/ld
# 32 bit
OPT_C32=-O0 -Wall -std=c99 -nostdlib -nostartfiles -nodefaultlibs \
-Wimplicit-function-declaration -fno-stack-protector
OPT_ASM32=-s -f elf32
OPT_LD32=-T loader.ld --build-id=none -m elf_i386 -Map lmap.txt
# 64 bit
OPT_C=-m64 -ffreestanding -z max-page-size=0x1000 -mno-red-zone \
-mno-mmx -mno-sse -mno-sse2 -std=gnu99 -O0 -Wall -Wextra \
-nostdlib -nostartfiles -nodefaultlibs -mcmodel=large
OPT_ASM=-s -f elf64
OPT_LD=-T lenochka.ld --build-id=none -m elf_x86_64 -Map kmap.txt \
-z max-page-size=0x1000
%.o: $(KSRC_DIR)%.c
$(CC) $(OPT_C) -c $< -o $(KOBJ_DIR)$@ -I$(INCLUDE)
%.o: $(KSRC_DIR)%.asm
$(AS) $(OPT_ASM) $< -o $(KOBJ_DIR)$@
loader.elf:
$(AS32) $(OPT_ASM32) $(LSRC_DIR)loader.asm -o $(LOBJ_DIR)loader.o
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86io.asm -o $(LOBJ_DIR)x86io.o
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86stdlib.asm -o $(LOBJ_DIR)x86stdlib.o
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86gdt.asm -o $(LOBJ_DIR)x86gdt.o
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86idt.asm -o $(LOBJ_DIR)x86idt.o
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86int.asm -o $(LOBJ_DIR)x86int.o
$(CC32) $(OPT_C32) -c $(LSRC_DIR)stdlib.c -o $(LOBJ_DIR)stdlib.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)gdt.c -o $(LOBJ_DIR)gdt.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)vga_terminal.c -o $(LOBJ_DIR)vga_terminal.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)string.c -o $(LOBJ_DIR)string.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)memory.c -o $(LOBJ_DIR)memory.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)idt.c -o $(LOBJ_DIR)idt.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)exceptions.c -o $(LOBJ_DIR)exceptions.o -I$(LINCLUDE)
$(CC32) $(OPT_C32) -c $(LSRC_DIR)lmain.c -o $(LOBJ_DIR)lmain.o -I$(LINCLUDE)
$(AS32) $(OPT_ASM32) $(LSRC_DIR)x86enter64.asm -o $(LOBJ_DIR)x86enter64.o
$(LD32) $(OPT_LD32) -o os/loader.elf $(addprefix $(LOBJ_DIR),$(LOBJ))
lenochka.elf: $(KOBJ)
$(LD) $(OPT_LD) -o os/lenochka.elf $(addprefix $(KOBJ_DIR),$(KOBJ))
mkbootldr:
nasm -f bin boot/stage1.asm -o boot/boot.bin
nasm -f bin boot/stage2.asm -o os/BOOTLOAD.BIN
format:
dd if=/dev/zero of=vm/hdisk.img bs=1M count=64
mkdosfs -F 16 vm/hdisk.img
mount:
losetup /dev/loop0 $(HDISK)
losetup /dev/loop1 $(HDISK) -o 1048576
losetup /dev/loop2 $(HDISK) -o 34603008
mount -o umask=000 /dev/loop1 /media/img
mount -o umask=000 /dev/loop2 /media/disk1
update:
cp os/loader.elf /media/img/boot/loader.elf
cp os/lenochka.elf /media/img/boot/lenochka.elf
unmount:
umount /media/img
umount /media/disk1
losetup -d /dev/loop0
losetup -d /dev/loop1
losetup -d /dev/loop2
unmount1:
losetup -d /dev/loop0
losetup -d /dev/loop1
losetup -d /dev/loop2
install-usb:
mount -o umask=000 /dev/sdb1 /media/usb_3
cp os/loader.elf /media/usb_3/boot/loader.elf
cp os/lenochka.elf /media/usb_3/boot/lenochka.elf
umount /media/usb_3
run-qemu:
qemu-system-x86_64 -hda $(HDISK) -m 512M -machine q35
run-qemu-debug:
qemu-system-x86_64 -hda $(HDISK) -m 512M -machine q35 -d int \
-no-shutdown -no-reboot -d guest_errors
clean:
rm -rf kobj/*
rm -rf lobj/*
all: lenochka.elf

BIN
bdf2bin Normal file

Binary file not shown.

95
bdf2bin.c Normal file
View file

@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
//align(8) chars = amount of characters
//align(8) encoding table - 2 byte array [chars]
//align(8) bitmap table - 16 byte array [chars]
#define ROUND2_UP(val,bit) (( (val>>bit) \
+ ( (val&((1<<bit)-1)) ? 1 : 0 ) ) << bit)
typedef struct {
uint8_t bmap[16];
} bmchar_t;
int main(int argc,char** argv)
{
FILE* bdf,*bin;
char buf[512];
uint64_t chars = 1;
uint16_t* encodings;
bmchar_t* bitmaps;
int enc = 0;
int parse_chr = 0;
int parse_bm = 0;
int cur_chr = 0;
int cur_bm = 0;
bdf = fopen(argv[1],"rb");
while(fgets(buf,sizeof(buf),bdf))
{
if(!memcmp(buf,"CHARS ",6))
{
sscanf(buf,"CHARS %u\n",&chars);
printf("chars %u\n",chars);
encodings = (uint16_t*)calloc(chars,sizeof(uint16_t));
bitmaps = (bmchar_t*)calloc(chars,sizeof(bmchar_t));
}
else if(!memcmp(buf,"ENDFONT",7)) break;
else if(!memcmp(buf,"STARTCHAR",9))
parse_chr = 1;
if(parse_chr)
{
if(parse_bm)
{
if(!memcmp(buf,"ENDCHAR",7))
{
parse_chr = 0;
parse_bm = 0;
cur_bm = 0;
printf("cur_chr %u\n",cur_chr);
if(++cur_chr == chars) break;
}
else
{
int a;
sscanf(buf,"%02X\n",&a);
bitmaps[cur_chr].bmap[cur_bm] = a&0xFF;
printf("bm %x\n",a);
cur_bm++;
}
}
else
{
if(!memcmp(buf,"ENCODING ",9))
{
sscanf(buf,"ENCODING %u\n",&enc);
encodings[cur_chr] = enc;
printf("char %u\n",enc);
}
else if(!memcmp(buf,"BITMAP",6))
parse_bm = 1;
}
}
}
fclose(bdf);
bin = fopen(argv[2],"wb");
fwrite(&chars,sizeof(uint64_t),1,bin);
fwrite(encodings,chars<<1,1,bin);
fwrite(bitmaps,chars<<4,1,bin);
fclose(bin);
free(encodings);
free(bitmaps);
return 0;
}

226
bochsout.txt Normal file
View file

@ -0,0 +1,226 @@
00000000000i[ ] Bochs x86 Emulator 2.6.9
00000000000i[ ] Built from SVN snapshot on April 9, 2017
00000000000i[ ] Compiled on Jan 11 2019 at 07:51:24
00000000000i[ ] System configuration
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
00000000000i[ ] A20 line support: yes
00000000000i[ ] load configurable MSRs from file "msrs.def"
00000000000i[ ] IPS is set to 50000000
00000000000i[ ] CPU configuration
00000000000i[ ] SMP support: yes, quantum=16
00000000000i[ ] Using pre-defined CPU configuration: core2_penryn_t9600
00000000000i[ ] Optimization configuration
00000000000i[ ] RepeatSpeedups support: no
00000000000i[ ] Fast function calls: no
00000000000i[ ] Handlers Chaining speedups: no
00000000000i[ ] Devices configuration
00000000000i[ ] PCI support: i440FX i430FX
00000000000i[ ] Networking: no
00000000000i[ ] Sound support: no
00000000000i[ ] USB support: UHCI
00000000000i[ ] VGA extension support: vbe
00000000000i[MEM0 ] allocated memory at 0x7f56ceb6a010. after alignment, vector=0x7f56ceb6b000
00000000000i[MEM0 ] 512,00MB
00000000000i[MEM0 ] mem block size = 0x00020000, blocks=4096
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('/usr/share/bochs/BIOS-bochs-latest')
00000000000i[STIMER] using 'slowdown' timer synchronization method
00000000000i[PLUGIN] init_dev of 'pci' plugin device by virtual method
00000000000i[DEV ] i440FX PMC present at device 0, function 0
00000000000i[PLUGIN] init_dev of 'pci2isa' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method
00000000000i[CMOS ] Using local time for initial clock
00000000000i[CMOS ] Setting initial clock to: Mon Feb 25 00:23:01 2019 (time0=1551054181)
00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method
00000000000i[DMA ] channel 4 used by cascade
00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'pit' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'vga' plugin device by virtual method
00000000000i[MEM0 ] Register memory access handlers: 0x0000000a0000 - 0x0000000bffff
00000000000i[VGA ] interval=200000, mode=realtime
00000000000i[MEM0 ] Register memory access handlers: 0x0000e0000000 - 0x0000e0ffffff
00000000000i[BXVGA ] VBE Bochs Display Extension Enabled
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24
00000000000i[MEM0 ] rom at 0xc0000/41472 ('/usr/share/bochs/VGABIOS-lgpl-latest')
00000000000i[PLUGIN] init_dev of 'floppy' plugin device by virtual method
00000000000i[DMA ] channel 2 used by Floppy Drive
00000000000i[FLOPPY] Using boot sequence disk, none, none
00000000000i[FLOPPY] Floppy boot signature check is enabled
00000000000i[PLUGIN] init_dev of 'acpi' plugin device by virtual method
00000000000i[DEV ] ACPI Controller present at device 1, function 3
00000000000i[PLUGIN] init_dev of 'ioapic' plugin device by virtual method
00000000000i[IOAPIC] initializing I/O APIC
00000000000i[MEM0 ] Register memory access handlers: 0x0000fec00000 - 0x0000fec00fff
00000000000i[IOAPIC] IOAPIC enabled (base address = 0xfec00000)
00000000000i[PLUGIN] init_dev of 'keyboard' plugin device by virtual method
00000000000i[KBD ] will paste characters every 400 keyboard ticks
00000000000i[PLUGIN] init_dev of 'harddrv' plugin device by virtual method
00000000000i[HD ] HD on ata0-0: 'vm/hdisk.img', 'flat' mode
00000000000i[IMG ] hd_size: 134217728
00000000000i[HD ] ata0-0: autodetect geometry: CHS=260/16/63
00000000000i[HD ] ata0-0: extra data outside of CHS address range
00000000000i[HD ] translation on ata0-0 set to 'none'
00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1
00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'speaker' plugin device by virtual method
00000000000e[PCSPK ] Failed to open /dev/console: Отказано в доступе
00000000000e[PCSPK ] Deactivating beep on console
00000000000i[PLUGIN] init_dev of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'parallel' plugin device by virtual method
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
00000000000i[PLUGIN] init_dev of 'serial' plugin device by virtual method
00000000000i[SER ] com1 at 0x03f8 irq 4 (mode: null)
00000000000i[PLUGIN] init_dev of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'usb_uhci' plugin device by virtual method
00000000000i[DEV ] USB UHCI present at device 1, function 2
00000000000i[UHCI ] USB UHCI initialized
00000000000i[PLUGIN] register state of 'pci' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] register state of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] register state of 'dma' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pit' plugin device by virtual method
00000000000i[PLUGIN] register state of 'vga' plugin device by virtual method
00000000000i[PLUGIN] register state of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] register state of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] register state of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] register state of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] register state of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] register state of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] register state of 'serial' plugin device by virtual method
00000000000i[PLUGIN] register state of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] register state of 'usb_uhci' plugin device by virtual method
00000000000i[PLUGIN] register state of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] register state of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] register state of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci_ide' plugin device by virtual method
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00000000000i[CPU0 ] cpu hardware reset
00000000000i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
00000000000i[CPU0 ] CPU[0] is the bootstrap processor
00000000000i[CPU0 ] CPUID[0x00000000]: 0000000d 756e6547 6c65746e 49656e69
00000000000i[CPU0 ] CPUID[0x00000001]: 0001067a 00010800 0408e3dd bfebfbff
00000000000i[CPU0 ] CPUID[0x00000002]: 05b0b101 005657f0 00000000 2cb4304e
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000004]: 04000121 01c0003f 0000003f 00000001
00000000000i[CPU0 ] CPUID[0x00000005]: 00000040 00000040 00000003 03122220
00000000000i[CPU0 ] CPUID[0x00000006]: 00000003 00000002 00000003 00000000
00000000000i[CPU0 ] CPUID[0x00000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000008]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000009]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] WARNING: Architectural Performance Monitoring is not implemented
00000000000i[CPU0 ] CPUID[0x0000000a]: 07280202 00000000 00000000 00000503
00000000000i[CPU0 ] CPUID[0x0000000b]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x0000000c]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x0000000d]: 00000003 00000240 00000240 00000000
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000001]: 00000000 00000000 00000001 20100000
00000000000i[CPU0 ] CPUID[0x80000002]: 65746e49 2952286c 726f4320 4d542865
00000000000i[CPU0 ] CPUID[0x80000003]: 44203229 43206f75 20205550 54202020
00000000000i[CPU0 ] CPUID[0x80000004]: 30303639 20402020 30382e32 007a4847
00000000000i[CPU0 ] CPUID[0x80000005]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 00000000 18008040 00000000
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000
00000000000i[PLUGIN] reset of 'pci' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] reset of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] reset of 'dma' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pit' plugin device by virtual method
00000000000i[PLUGIN] reset of 'vga' plugin device by virtual method
00000000000i[PLUGIN] reset of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] reset of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] reset of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] reset of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci_ide' plugin device by virtual method
00000000000i[PLUGIN] reset of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] reset of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] reset of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] reset of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] reset of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] reset of 'serial' plugin device by virtual method
00000000000i[PLUGIN] reset of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] reset of 'usb_uhci' plugin device by virtual method
00000000000i[XGUI ] charmap update. Font is 9 x 16
00000004662i[BIOS ] $Revision: 13073 $ $Date: 2017-02-16 22:43:52 +0100 (Do, 16. Feb 2017) $
00000337544i[KBD ] reset-disable command received
00000363303i[BIOS ] Starting rombios32
00000363741i[BIOS ] Shutdown flag 0
00000364333i[BIOS ] ram_size=0x20000000
00000364776i[BIOS ] ram_end=512MB
00000860684i[BIOS ] Found 1 cpu(s)
00000874268i[BIOS ] bios_table_addr: 0x000f9cd8 end=0x000fcc00
00001202063i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
00001529992i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0b
00001530011i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x09
00001530030i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b
00001530049i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x09
00001530059i[P2ISA ] write: ELCR2 = 0x0a
00001530829i[BIOS ] PIIX3/PIIX4 init: elcr=00 0a
00001538552i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237 class=0x0600
00001540831i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000 class=0x0601
00001542949i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010 class=0x0101
00001543178i[PIDE ] new BM-DMA address: 0xc000
00001543794i[BIOS ] region 4: 0x0000c000
00001545808i[BIOS ] PCI: bus=0 devfn=0x0a: vendor_id=0x8086 device_id=0x7020 class=0x0c03
00001546012i[UHCI ] new base address: 0xc020
00001546628i[BIOS ] region 4: 0x0000c020
00001546756i[UHCI ] new irq line = 9
00001548651i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113 class=0x0680
00001548883i[ACPI ] new irq line = 11
00001548895i[ACPI ] new irq line = 9
00001548920i[ACPI ] new PM base address: 0xb000
00001548934i[ACPI ] new SM base address: 0xb100
00001548962i[PCI ] setting SMRAM control register to 0x4a
00001713055i[CPU0 ] Enter to System Management Mode
00001713065i[CPU0 ] RSM: Resuming from System Management Mode
00001877086i[PCI ] setting SMRAM control register to 0x0a
00001891993i[BIOS ] MP table addr=0x000f9db0 MPC table addr=0x000f9ce0 size=0xc8
00001893815i[BIOS ] SMBIOS table addr=0x000f9dc0
00001896005i[BIOS ] ACPI tables: RSDP addr=0x000f9ee0 ACPI DATA addr=0x1fff0000 size=0xf72
00001899239i[BIOS ] Firmware waking vector 0x1fff00cc
00001901034i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
00001901757i[BIOS ] bios_table_cur_addr: 0x000f9f04
00002029374i[VBIOS ] VGABios $Id: vgabios.c,v 1.76 2013/02/10 08:07:03 vruppert Exp $
00002029445i[BXVGA ] VBE known Display Interface b0c0
00002029477i[BXVGA ] VBE known Display Interface b0c5
00002032402i[VBIOS ] VBE Bios $Id: vbe.c,v 1.65 2014/07/08 18:02:25 vruppert Exp $
00002376822i[BIOS ] ata0-0: PCHS=260/16/63 translation=none LCHS=260/16/63
00005823626i[BIOS ] IDE time out
00006101046i[BIOS ] Booting from 0000:7c00
00007617800i[XGUI ] charmap update. Font is 9 x 16
00520252587i[CPU0 ] CPU is in long mode (active)
00520252587i[CPU0 ] CS.mode = 64 bit
00520252587i[CPU0 ] SS.mode = 64 bit
00520252587i[CPU0 ] EFER = 0x00000500
00520252587i[CPU0 ] | RAX=0000000000000000 RBX=0000000000200000
00520252587i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
00520252587i[CPU0 ] | RSP=000000000010cfd0 RBP=000000000010cffc
00520252587i[CPU0 ] | RSI=0000000000000000 RDI=0000000000000000
00520252587i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00520252587i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00520252587i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00520252587i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00520252587i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf ZF af PF cf
00520252587i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00520252587i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 0
00520252587i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00520252587i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00520252587i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00520252587i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00520252587i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00520252587i[CPU0 ] | MSR_FS_BASE:0000000000000000
00520252587i[CPU0 ] | MSR_GS_BASE:0000000000000000
00520252587i[CPU0 ] | RIP=0000000000101eb1 (0000000000101eb1)
00520252587i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000
00520252587i[CPU0 ] | CR3=0x00201000 CR4=0x00000020
00520252587d[PCI ] Exit
00520252587i[CMOS ] Last time is 1551054191 (Mon Feb 25 00:23:11 2019)
00520252587i[XGUI ] Exit
00520252587i[SIM ] quit_sim called with exit code 0

8
boot/grub/grub.cfg Normal file
View file

@ -0,0 +1,8 @@
set timeout=15
set default=0
menuentry "Lenochka" {
multiboot /boot/loader.elf
module /boot/lenochka.elf "LENOCHKA"
boot
}

2
build.sh Normal file
View file

@ -0,0 +1,2 @@
#!/usr/bin/bash
make lenochka.elf && make mount && make update && make unmount

26
bx_enh_dbg.ini Normal file
View file

@ -0,0 +1,26 @@
# bx_enh_dbg_ini
SeeReg[0] = TRUE
SeeReg[1] = TRUE
SeeReg[2] = TRUE
SeeReg[3] = TRUE
SeeReg[4] = FALSE
SeeReg[5] = FALSE
SeeReg[6] = FALSE
SeeReg[7] = FALSE
SingleCPU = FALSE
ShowIOWindows = TRUE
ShowButtons = TRUE
SeeRegColors = TRUE
ignoreNxtT = TRUE
ignSSDisasm = TRUE
UprCase = 0
DumpInAsciiMode = 3
isLittleEndian = TRUE
DefaultAsmLines = 512
DumpWSIndex = 0
DockOrder = 0x123
ListWidthPix[0] = 192
ListWidthPix[1] = 323
ListWidthPix[2] = 231
MainWindow = 0, 0, 746, 500
FontName = Normal

2
export.sh Normal file
View file

@ -0,0 +1,2 @@
#!/usr/bin/bash
export PATH="$HOME/opt/cross/bin:$PATH"

BIN
font.bin Normal file

Binary file not shown.

276
kernel/ahci.c Normal file
View file

@ -0,0 +1,276 @@
#include "ahci.h"
#include "pci.h"
#include "pit.h"
#include "io.h"
#include "lvalloc.h"
#include "paging.h"
#include "stdlib.h"
typedef struct {
u64 hba_phys;
hba_port_t* sata;
hba_port_t* atapi;
u16* buf;
} ahci_t;
static ahci_t s_ahci;
static hba_mem_t* HBA;
void ahci_issue_cmd(hba_port_t* port,u64 cmd)
{
if(!(port->cmd & SCMD_ST))
port->cmd |= SCMD_ST;
port->cmd |= (1<<28);
port->serr = port->serr;
port->is = port->is;
//If idle, reset PxCMD
/*if(port->cmd & (0x7F<<23))
{
port->cmd &= ~SCMD_ST;
port->cmd |= SCMD_ST|SCMD_FRE|(1<<3);
}*/
port->ci = (1<<cmd);
//Wait for command
while(port->tfd & ATA_DEV_BUSY)
{
}
}
u64 ahci_read_sectors(hba_port_t* port,u64 lba,u64 sectors,
u64 __phys buf)
{
hba_cmd_header_t* cmdhdr = (hba_cmd_header_t*)port->clb;
hba_cmd_tbl_t* cmdtbl = (hba_cmd_tbl_t*)cmdhdr->ctba;
fis_reg_h2d_t* fis = (fis_reg_h2d_t*)&cmdtbl->cfis;
port->is = 0xFFFFFFFF;
cmdhdr->cfl = sizeof(fis_reg_h2d_t)/sizeof(u32);
cmdhdr->w = 0;
cmdhdr->prdtl = (sectors>>4)+1;
kmemzero(cmdtbl, sizeof(hba_cmd_tbl_t) +
(cmdhdr->prdtl-1)*sizeof(hba_prdt_entry_t));
kmemzero(fis,sizeof(fis_reg_h2d_t));
fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = ATA_CMD_READ_DMA_EX;
fis->lba0 = lba&0xFF;
fis->lba1 = (lba>>8)&0xFF;
fis->lba2 = (lba>>16)&0xFF;
fis->device = ATA_LBA_MODE;
fis->lba3 = (lba>>24)&0xFF;
fis->lba4 = (lba>>32)&0xFF;
fis->lba5 = (lba>>36)&0xFF;
fis->countl = sectors&0xFF;
fis->counth = (sectors>>8)&0xFF;
u64 i;
for(i = 0; i < (u64)(cmdhdr->prdtl-1); i++)
{
kmemzero(&cmdtbl->prdt_entry[i],sizeof(hba_prdt_entry_t));
cmdtbl->prdt_entry[i].dba = buf;
cmdtbl->prdt_entry[i].dbc = 8191;
cmdtbl->prdt_entry[i].i = 1;
buf += 8192;
sectors -= 16;
}
cmdtbl->prdt_entry[i].dba = buf;
cmdtbl->prdt_entry[i].dbc = (sectors<<9)-1;
cmdtbl->prdt_entry[i].i = 1;
ahci_issue_cmd(port,0);
if(port->is & (1<<30))
{
kprintf("disk read error!\n");
return 1;
}
return 0;
}
u64 ahci_identify(hba_port_t* port)
{
hba_cmd_header_t* cmdhdr = (hba_cmd_header_t*)port->clb;
hba_cmd_tbl_t* cmdtbl = (hba_cmd_tbl_t*)cmdhdr->ctba;
fis_reg_h2d_t* fis = (fis_reg_h2d_t*)&cmdtbl->cfis;
port->is = 0xFFFFFFFF;
cmdhdr->cfl = sizeof(fis_reg_h2d_t)/sizeof(u32);
cmdhdr->w = 0;
cmdhdr->prdtl = 1;
kmemzero(cmdtbl, sizeof(hba_cmd_tbl_t) +
(cmdhdr->prdtl-1)*sizeof(hba_prdt_entry_t));
kmemzero(fis,sizeof(fis_reg_h2d_t));
fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = ATA_CMD_IDENTIFY;
fis->lba0 = 0;
fis->lba1 = 0;
fis->lba2 = 0;
fis->device = ATA_LBA_MODE;
fis->lba3 = 0;
fis->lba4 = 0;
fis->lba5 = 0;
fis->countl = 1;
fis->counth = 0;
cmdtbl->prdt_entry[0].dba = (u64)s_ahci.buf;
cmdtbl->prdt_entry[0].dbc = 511;
cmdtbl->prdt_entry[0].i = 1;
ahci_issue_cmd(port,0);
return *(u64*)(&s_ahci.buf[100]);
}
void port_start(hba_port_t* port)
{
//while(port->cmd & (1<<15)){__asm("nop");}
port->cmd |= SCMD_ST;
port->cmd |= SCMD_FRE;
}
void port_stop(hba_port_t* port)
{
if(!(port->cmd & SCMD_ST)) return;
port->cmd &= ~SCMD_ST;
port->cmd &= ~SCMD_ST;
while(port->cmd & SCMD_CR)
{
sleep(1000);
}
port->cmd &= ~SCMD_FRE;
while(port->cmd & SCMD_FR)
{
sleep(1000);
}
port->cmd &= ~SCMD_FRE;
}
void port_rebase(hba_port_t* port)
{
port_stop(port);
port->clb = (u64)lvalloc(4096);
port->fb = (u64)lvalloc(4096);
for(u64 i = 0; i < 32; i++)
{
hba_cmd_header_t* cmdhdr = &((hba_cmd_header_t*)port->clb)[i];
cmdhdr->prdtl = 8;
cmdhdr->ctba = (u64)lvalloc(4096);
}
port_start(port);
}
hba_port_t* ahci_get_sata()
{
return s_ahci.sata;
}
hba_port_t* ahci_get_atapi()
{
return s_ahci.atapi;
}
void ahci_init()
{
pci_device_t ahci;
u32 bar;
//Use PCI
ahci = pci_find_device(0x01,0x06);
if(ahci == 0)
{
kprintf("AHCI not found!\n");
return;
}
bar = pci_read_config_word_dev(ahci,0x24);
s_ahci.hba_phys = (u64)(bar & 0xFFFFFFF0);
kprintf("HBA %x\n",s_ahci.hba_phys);
//Identity map
page_map((void*)s_ahci.hba_phys,(void*)s_ahci.hba_phys,
16384);
HBA = (hba_mem_t*)s_ahci.hba_phys;
HBA->ghc |= (1<<31); //Enable GHC.AE
if(HBA->cap & (1<<27))
{
kprintf("AHCI supports stagered spin-up\n");
}
if(HBA->cap & (1<<31))
{
kprintf("AHCI supports 64-bit mode\n");
}
s_ahci.sata = NULL;
s_ahci.atapi = NULL;
//kprintf("pi %x\n",HBA->pi);
for(u32 i = 0; i < 32; i++)
{
hba_port_t* port = &HBA->ports[i];
if(!((HBA->pi>>i)&1)) continue;
switch(port->sig)
{
case SATA_SIG_ATA: s_ahci.sata = port; break;
case SATA_SIG_ATAPI: s_ahci.atapi = port; break;
}
if(port->cmd & (SCMD_ST|SCMD_FR|SCMD_CR|SCMD_FRE)) //Isn't IDLE
{
port->cmd &= ~SCMD_ST;
while(port->cmd & SCMD_CR)
{
sleep(1000);
}
port->cmd &= ~SCMD_FRE;
while(port->cmd & SCMD_FR)
{
sleep(1000);
}
}
//spin-up
port->cmd |= (1<<1);
//Start it again
//port->cmd |= SCMD_ST|SCMD_FRE|(1<<2);
//Initialize port
port_rebase(port);
port->is = 0xFFFFFFFF; //RWC
//port->is = 0xFD8000AF;
//power on
port->cmd |= (1<<2);
}
s_ahci.buf = (u16*)lvalloc(4096);
ahci_identify(s_ahci.sata);
}

326
kernel/ahci.h Normal file
View file

@ -0,0 +1,326 @@
#ifndef __AHCI_H
#define __AHCI_H
#include "os.h"
#define SATA_SIG_ATA 0x00000101 // SATA drive
#define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
#define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge
#define SATA_SIG_PM 0x96690101 // Port multiplier
#define ATA_DEV_BUSY (1<<7)
#define ATA_DEV_DRQ (1<<3)
typedef struct {
//u32 clb; // 0x00, command list base address, 1K-byte aligned
//u32 clbu; // 0x04, command list base address upper 32 bits
u64 clb;
u64 fb;
u32 is; // 0x10, interrupt status
u32 ie; // 0x14, interrupt enable
u32 cmd; // 0x18, command and status
u32 rsv0; // 0x1C, Reserved
u32 tfd; // 0x20, task file data
u32 sig; // 0x24, signature
u32 ssts; // 0x28, SATA status (SCR0:SStatus)
u32 sctl; // 0x2C, SATA control (SCR2:SControl)
u32 serr; // 0x30, SATA error (SCR1:SError)
u32 sact; // 0x34, SATA active (SCR3:SActive)
u32 ci; // 0x38, command issue
u32 sntf; // 0x3C, SATA notification (SCR4:SNotification)
u32 fbs; // 0x40, FIS-based switch control
u32 rsv1[11]; // 0x44 ~ 0x6F, Reserved
u32 vendor[4]; // 0x70 ~ 0x7F, vendor specific
} hba_port_t;
typedef struct
{
// 0x00 - 0x2B, Generic Host Control
u32 cap; // 0x00, Host capability
u32 ghc; // 0x04, Global host control
u32 is; // 0x08, Interrupt status
u32 pi; // 0x0C, Port implemented
u32 vs; // 0x10, Version
u32 ccc_ctl; // 0x14, Command completion coalescing control
u32 ccc_pts; // 0x18, Command completion coalescing ports
u32 em_loc; // 0x1C, Enclosure management location
u32 em_ctl; // 0x20, Enclosure management control
u32 cap2; // 0x24, Host capabilities extended
u32 bohc; // 0x28, BIOS/OS handoff control and status
// 0x2C - 0x9F, Reserved
u8 rsv[116];
// 0xA0 - 0xFF, Vendor specific registers
u8 vendor[96];
// 0x100 - 0x10FF, Port control registers
hba_port_t ports[32];
} hba_mem_t;
typedef enum
{
FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device
FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host
FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host
FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
} fis_type_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_REG_H2D
u8 pmport:4; // Port multiplier
u8 rsv0:3; // Reserved
u8 c:1; // 1: Command, 0: Control
u8 command; // Command register
u8 featurel; // Feature register, 7:0
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 featureh; // Feature register, 15:8
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 icc; // Isochronous command completion
u8 control; // Control register
// DWORD 4
u8 rsv1[4]; // Reserved
} fis_reg_h2d_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_REG_D2H
u8 pmport:4; // Port multiplier
u8 rsv0:2; // Reserved
u8 i:1; // Interrupt bit
u8 rsv1:1; // Reserved
u8 status; // Status register
u8 error; // Error register
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 rsv2; // Reserved
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 rsv3[2]; // Reserved
// DWORD 4
u8 rsv4[4]; // Reserved
} fis_reg_d2h_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_DATA
u8 pmport:4; // Port multiplier
u8 rsv0:4; // Reserved
u8 rsv1[2]; // Reserved
// DWORD 1 ~ N
u32 data[1]; // Payload
} fis_data_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_PIO_SETUP
u8 pmport:4; // Port multiplier
u8 rsv0:1; // Reserved
u8 d:1; // Data transfer direction, 1 - device to host
u8 i:1; // Interrupt bit
u8 rsv1:1;
u8 status; // Status register
u8 error; // Error register
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 rsv2; // Reserved
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 rsv3; // Reserved
u8 e_status; // New value of status register
// DWORD 4
u16 tc; // Transfer count
u8 rsv4[2]; // Reserved
} fis_pio_setup_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_DMA_SETUP
u8 pmport:4; // Port multiplier
u8 rsv0:1; // Reserved
u8 d:1; // Data transfer direction, 1 - device to host
u8 i:1; // Interrupt bit
u8 a:1; // Auto-activate. Specifies if DMA Activate FIS is needed
u8 rsved[2]; // Reserved
//DWORD 1&2
u64 DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
//DWORD 3
u32 rsvd; //More reserved
//DWORD 4
u32 DMAbufOffset; //Byte offset into buffer. First 2 bits must be 0
//DWORD 5
u32 TransferCount; //Number of bytes to transfer. Bit 0 must be 0
//DWORD 6
u32 resvd; //Reserved
} fis_dma_setup_t;
typedef struct
{
// 0x00
fis_dma_setup_t dsfis; // DMA Setup FIS
u8 pad0[4];
// 0x20
fis_pio_setup_t psfis; // PIO Setup FIS
u8 pad1[12];
// 0x40
fis_reg_d2h_t rfis; // Register Device to Host FIS
u8 pad2[4];
// 0x58
u64 sdbfis; // Set Device Bit FIS
// 0x60
u8 ufis[64];
// 0xA0
u8 rsv[0x100-0xA0];
} hba_fis_t;
typedef struct
{
// DW0
u8 cfl:5; // Command FIS length in DWORDS, 2 ~ 16
u8 a:1; // ATAPI
u8 w:1; // Write, 1: H2D, 0: D2H
u8 p:1; // Prefetchable
u8 r:1; // Reset
u8 b:1; // BIST
u8 c:1; // Clear busy upon R_OK
u8 rsv0:1; // Reserved
u8 pmp:4; // Port multiplier port
u16 prdtl; // Physical region descriptor table length in entries
// DW1
u32 prdbc; // Physical region descriptor byte count transferred
// DW2, 3
//u32 ctba; // Command table descriptor base address
//u32 ctbau; // Command table descriptor base address upper 32 bits
u64 ctba;
// DW4 - 7
u32 rsv1[4]; // Reserved
} hba_cmd_header_t;
typedef struct
{
//u32 dba; // Data base address
//u32 dbau; // Data base address upper 32 bits
u64 dba;
u32 rsv0; // Reserved
// DW3
u32 dbc:22; // Byte count, 4M max
u32 rsv1:9; // Reserved
u32 i:1; // Interrupt on completion
} hba_prdt_entry_t;
typedef struct
{
// 0x00
u8 cfis[64]; // Command FIS
// 0x40
u8 acmd[16]; // ATAPI command, 12 or 16 bytes
// 0x50
u8 rsv[48]; // Reserved
// 0x80
hba_prdt_entry_t prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
} hba_cmd_tbl_t;
u64 ahci_read_sectors(hba_port_t* port,u64 lba,u64 sectors,
u64 __phys buf);
u64 ahci_identify(hba_port_t* port);
hba_port_t* ahci_get_sata();
hba_port_t* ahci_get_atapi();
void ahci_init();
#define AHCI_CLB_SIZE ((sizeof(hba_cmd_header_t)*32)+4096)
#define AHCI_FB_SIZE ((sizeof(hba_fis_t)*32)+4096)
#define SCMD_ST (1<<0)
#define SCMD_CR (1<<15)
#define SCMD_FR (1<<14)
#define SCMD_FRE (1<<4)
#define ATA_LBA_MODE 0x40
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_CMD_READ_DMA_EX 0x25
#endif

51
kernel/bmp.c Normal file
View file

@ -0,0 +1,51 @@
#include "bmp.h"
#include "heap.h"
#include "video.h"
#include "stdlib.h"
#include "defines.h"
void bmp_draw(u64 px,u64 py,u64 w,u64 h,u8* bmp)
{
u32 offbits = *(u32*)(bmp+0x0A);
u64 bw,bh,stride;
u64 bc;
u8* bmap = bmp+offbits;
w = MIN(w,lmem->v_width);
h = MIN(h,lmem->v_height);
bw = *(u32*)(bmp+0x12);
bh = *(u32*)(bmp+0x16);
bc = *(u16*)(bmp+0x1C)>>3;
stride = ROUND2_UP((bw*bc),2);
u64 f_w,f_h;
if(!w) f_w = 0x00010000;
else f_w = (w<<32) / (bw<<16);
if(!h) f_h = 0x00010000;
else f_h = (h<<32) / (bh<<16);
u64 c_y = 0;
for(u64 y = 0; y < bh; y++)
{
u64 c_x = 0;
u8* line = &bmap[(bh-y-1)*stride];
for(u64 x = 0; x < bw; x++)
{
u8 r,g,b;
r = *line++;
g = *line++;
b = *line++;
u32 color = (b<<16|g<<8|r);
for(u64 i = 0; i < (f_w>>16); i++)
{
video_pixel(px+c_x+i,py+c_y,color);
for(u64 j = 1; j < (f_h>>16); j++)
video_pixel(px+c_x+i,py+c_y+j,color);
}
c_x = ((c_x<<16) + f_w) >> 16;
}
c_y = ((c_y<<16) + f_h) >> 16;
}
}

8
kernel/bmp.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __BMP_H
#define __BMP_H
#include "os.h"
void bmp_draw(u64 px,u64 py,u64 w,u64 h,u8* bmp);
#endif

10
kernel/defines.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __DEFINES_H
#define __DEFINES_H
#define ROUND2_UP(val,bit) (( (val>>bit) \
+ ( (val&((1<<bit)-1)) ? 1 : 0 ) ) << bit)
#define ROUND1_ADD(val) (val ? val : 1)
#define MIN(a,b) (a < b ? a : b)
#endif

137
kernel/disk.c Normal file
View file

@ -0,0 +1,137 @@
#include "disk.h"
#include "string.h"
#include "paging.h"
#include "stdlib.h"
#include "lvalloc.h"
#include "pit.h"
typedef struct {
u32 disk_available;
disk_t disk[26];
} diskhost_t;
static diskhost_t s_diskhost;
static __align(4096) u8 mbr[512];
static u32 disk_chr2idx(char name)
{
return name-'A';
}
disk_t* disk_get(char name)
{
u32 idx = disk_chr2idx(name);
if(idx >= 26) return NULL;
return &s_diskhost.disk[idx];
}
u32 disk_available()
{
u32 disks;
for(u64 i = 0; i < 26; i++)
{
if(s_diskhost.disk[i].phys.type != DISK_INVALID)
disks |= (1<<i);
}
return disks;
}
u64 disk_read_ex(disk_t* disk,u64 lba,u64 sectors,void* __virt buf)
{
u64 ret,attempts = 0;
switch(disk->phys.type)
{
case DISK_INVALID: break;
case DISK_AHCI:
do {
ret = ahci_read_sectors(disk->phys.hba_port,lba,sectors,
(u64)page_v2p((void*)buf));
if(ret) sleep(1000);
} while(ret != 0 || attempts++ < 2);
break;
}
return (attempts == 2);
}
u64 disk_write_ex(disk_t* disk,u64 lba,u64 sectors,void* __virt buf)
{
u64 ret,attempts = 0;
switch(disk->phys.type)
{
case DISK_INVALID: break;
case DISK_AHCI:
do {
ret = ahci_read_sectors(disk->phys.hba_port,lba,sectors,
(u64)page_v2p((void*)buf));
if(ret) sleep(1000);
} while(ret != 0 || attempts++ < 2);
break;
}
return (attempts == 2);
}
u64 disk_read(disk_t* disk,u64 lba,u64 sectors,void* __virt buf)
{
kmemzero(buf,sectors<<9);
if((lba+sectors) >= disk->parts[disk->cur_part].lba_num)
{
kprintf("disk_read out of bounds!\n");
return 1;
}
return disk_read_ex(disk,lba+(u64)disk->parts[disk->cur_part].lba_start,
sectors,buf);
}
u64 disk_write(disk_t* disk,u64 lba,u64 sectors,void* __virt buf)
{
if((lba+sectors) >= disk->parts[disk->cur_part].lba_num)
{
kprintf("disk_write out of bounds!\n");
return 1;
}
return disk_write_ex(disk,lba+(u64)disk->parts[disk->cur_part].lba_start,
sectors,buf);
}
void disk_setup(disk_t* disk)
{
disk->phys_totalsectors = ahci_identify(disk->phys.hba_port);
disk_read_ex(disk,0,1,mbr);
kmemcpy(&disk->uid,&mbr[0x1B4],10);
kmemcpy(disk->parts,&mbr[0x1BE],64);
//Determine which partition we should use
disk->cur_part = 0;
do {
disk_read(disk,0,1,mbr);
if(!kmemcmp((char*)&mbr[71],"DISK1",5))
{
//That's FAT32
break;
}
disk->cur_part = disk->cur_part + 1;
} while(disk->cur_part < 4);
}
void disk_init()
{
disk_t* disk;
//s_diskhost.mbr = (u8*)lvalloc(4096);
//kmemzero(&s_diskhost,sizeof(s_diskhost));
ahci_init();
//SATA (D)
disk = &s_diskhost.disk[disk_chr2idx('D')];
disk->phys.type = DISK_AHCI;
disk->phys.hba_port = ahci_get_sata();
//get sectors
//ATAPI (E)
disk = &s_diskhost.disk[disk_chr2idx('E')];
disk->phys.type = DISK_AHCI;
disk->phys.hba_port = ahci_get_atapi();
}

50
kernel/disk.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef __DISK_H
#define __DISK_H
#include "os.h"
#include "ahci.h"
typedef enum {
DISK_INVALID = 0,
DISK_AHCI = 1,
} disk_type_t;
struct disk_phys_t {
disk_type_t type;
union {
hba_port_t* hba_port;
};
};
typedef struct {
u8 attributes;
u8 chs_start[3];
u8 type;
u8 chs_last[3];
u32 lba_start;
u32 lba_num;
} __packed partition_t;
typedef struct {
struct disk_phys_t phys;
char disk_name; //ASCII char A-Z
u64 phys_totalsectors;
u8 uid[10];
partition_t parts[4];
u64 cur_part;
} disk_t;
disk_t* disk_get(char name);
u32 disk_available(); //return bitmap A-Z (26 bits)
u64 disk_read_ex(disk_t* disk,u64 lba,u64 sectors,void* __virt buf);
u64 disk_write_ex(disk_t* disk,u64 lba,u64 sectors,void* __virt buf);
u64 disk_read(disk_t* disk,u64 lba,u64 sectors,void* __virt buf);
u64 disk_write(disk_t* disk,u64 lba,u64 sectors,void* __virt buf);
void disk_setup(disk_t* disk);
void disk_init();
#endif

141
kernel/exceptions.c Normal file
View file

@ -0,0 +1,141 @@
#include "exceptions.h"
#include "vga_terminal.h"
#include "stdlib.h"
#include "idt.h"
#include "pit.h"
//#include "x86utils.h"
/* We need to implement those excpetions:
* 0 Division by zero
* 3 Breakpoint
* 6 Invalid opcode
* 7 Device not available
* 8 Double Fault
* 10 Invalid TSS
* 11 Segment not present
* 12 Stack segment fault
* 13 General protection fault
* 14 Page fault
*
*/
static void hang()
{
//x86_print_regs();
while(1){__asm("nop");}
}
//extern void command_interpreter();
//extern void _load_legacy_stack();
void _enter_rescue_mode()
{
/*_load_legacy_stack();
sleep(500);
command_interpreter();*/
}
void enter_rescue_mode(int skip_check)
{
if(!skip_check)
{
chg_color(VGA_COLOR_LIGHT_CYAN);
kprintf("Rollback to terminal? (y - yes, n - no): ");
u8 ans = kgetc();
if(ans == 'y' || skip_check)
{
kputc('\n');
chg_color(VGA_COLOR_MAGENTA);
_enter_rescue_mode();
}
chg_color(VGA_COLOR_MAGENTA);
}
else
{
cls();
kprintf("Terminal reloaded\n");
_enter_rescue_mode();
}
}
void exception0()
{
kprintf("[Exception] Division by zero\n");
hang();
}
void exception3()
{
kprintf("[Exception] Debug\n");
hang();
}
void exception6()
{
kprintf("[Exception] Invalid opcode\n");
hang();
}
void exception7()
{
kprintf("[Exception] Device not available\n");
hang();
}
void exception8()
{
kprintf("[Exception] Double fault\n");
hang();
}
void exception10()
{
kprintf("[Exception] Invalid TSS\n");
hang();
}
void exception11()
{
kprintf("[Exception] Segment not present\n");
hang();
}
void exception12()
{
kprintf("[Exception] Stack segment fault\n");
hang();
}
extern u64 x64_get_cr2();
void exception13()
{
kprintf("[Exception] General protection fault (%x)\n",
x64_get_cr2());
hang();
}
void exception14()
{
//x64_rax_n_stop(x64_get_cr2());
kprintf("[Exception] Page fault (%x)\n",x64_get_cr2());
//x86_print_regs();
//Do we want to rollback in command interpreter
enter_rescue_mode(0);
while(1){__asm("hlt");}
}
void install_exceptions()
{
idt_set_handler(0,exception0,IDT_TYPE_TRAP);
idt_set_handler(3,exception3,IDT_TYPE_TRAP);
idt_set_handler(6,exception6,IDT_TYPE_TRAP);
idt_set_handler(7,exception7,IDT_TYPE_TRAP);
idt_set_handler(8,exception8,IDT_TYPE_TRAP);
idt_set_handler(10,exception10,IDT_TYPE_TRAP);
idt_set_handler(11,exception11,IDT_TYPE_TRAP);
idt_set_handler(12,exception12,IDT_TYPE_TRAP);
idt_set_handler(13,exception13,IDT_TYPE_TRAP);
idt_set_handler(14,exception14,IDT_TYPE_TRAP);
}

9
kernel/exceptions.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef __EXCEPTIONS_H
#define __EXCEPTIONS_H
#include "os.h"
void enter_rescue_mode();
void install_exceptions();
#endif

331
kernel/fat.c Normal file
View file

@ -0,0 +1,331 @@
#include "fat.h"
#include "string.h"
#include "stdlib.h"
#include "lvalloc.h"
#include "defines.h"
fat_t g_fat;
void fat_read_cluster(fat_t* fat,u32 clus)
{
if(!IS_VALID_FAT(fat)) return;
disk_read(fat->disk,fat->datasec+((clus-2)*fat->spc),fat->spc,
fat->clusbuf);
}
static u32 fat_dir_clus(fat_dir_t* dir)
{
return (dir->dir_fstclushi<<16)|dir->dir_fstcluslo;
}
static u32 fat_dir_or_root_clus(fat_t* fat,fat_dir_t* dir)
{
if(dir != NULL)
return fat_dir_clus(dir);
return fat->rootclus;
}
u32 fat_table_read_entry(fat_t* fat,u32 idx)
{
//Do some caching
u32 clus = idx / fat->fatentperclus;
u32 offset = idx % fat->fatentperclus;
//if(!IS_VALID_FAT(fat)) return 0;
//kprintf("entry clus %u offset %u\n",
// fat->fatsec+(clus*fat->spc),offset);
if(clus == fat->curfatclus)
{
disk_read(fat->disk,fat->fatsec+(clus*fat->spc),fat->spc,fat->fatbuf);
fat->curfatclus = clus;
}
idx = FAT_CLUSTER(fat->fatbuf[offset]);
//kprintf("fat->fatbuf[offset] %u\n",idx);
//kprintf("%p\n",fat->fatbuf);
return FAT_CLUSTER(fat->fatbuf[offset]);
//kprintf("fat->fatbuf[offset] %u\n",(u64)FAT_CLUSTER(fat->fatbuf[offset]));
//return FAT_CLUSTER(fat->fatbuf[offset]);
}
void fat_read_file(fat_t* fat,fat_dir_t* file,u8* __virt buf)
{
if(!IS_VALID_FAT(fat)) return;
u32 clus = fat_dir_clus(file);
u32 size = file->dir_filesize;
u32 csize = fat->bps*fat->spc;
do {
u32 _size = MIN(size,csize);
fat_read_cluster(fat,clus);
kmemcpy(buf,fat->clusbuf,_size);
buf += _size;
size -= _size;
clus = fat_table_read_entry(fat,clus);
} while(!IS_FAT_CLUS_EOF(clus));
}
void fat_nametofmt38(const char* name,char* out)
{
char* d = out;
const char* s = name;
size_t slen = kstrlen(name);
for(u64 i = 0; i < 11; i++)
out[i] = ' ';
while(*s != '.' && (size_t)(d-out) < slen)
*d++ = ktoupper(*s++);
if((d-out) == 11) return;
d = &out[8];
s++;
for(u64 i = 0; i < 3 && *s; i++)
*d++ = ktoupper(*s++);
}
void fat_fmt38toname(const char* name,char* out)
{
char* d = out;
const char* s = name;
for(u64 i = 0; *s != ' ' && i < 11; i++)
*d++ = *s++;
if(name[8] != ' ' || name[9] != ' ' || name[10] != ' ')
{
*d++ = '.';
s = &name[8];
for(u64 i = 0; i < 3 && *s != ' '; i++)
*d++ = *s++;
}
*d++ = '\0';
}
int fat_is_valid_file(fat_dir_t* file)
{
if(file->dir_name[0] != 0 && file->dir_name[0] != (char)0xE5
&& file->dir_attr != FAT_ATTR_LONG_NAME
&& file->dir_attr != FAT_ATTR_VOLUME_ID)
{
return 1;
}
return 0;
}
u64 fat_first_file(fat_t* fat,fat_dir_t* parent,fat_dir_t* file,
char* longname)
{
char* d;
int load_long = 1;
u32 dir_clus = fat_dir_or_root_clus(fat,parent);
do {
fat_read_cluster(fat,dir_clus);
for(u32 i = 0; i < fat->dirsperclus; i++)
{
union {
fat_dir_t* file;
fat_ldir_t* ldir;
} tmp;
tmp.file = &((fat_dir_t*)fat->clusbuf)[i];
if(tmp.ldir->ldir_attr == FAT_ATTR_LONG_NAME && load_long)
{
if(IS_FAT_LDIR_LAST(tmp.ldir->ldir_ord))
{
tmp.ldir->ldir_ord &= ~(1<<6);
load_long = 0;
}
d = longname+(13*(tmp.ldir->ldir_ord-1));
for(u32 j = 0; j < 5; j++)
{
if(tmp.ldir->ldir_name1[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name1[j]);
}
for(u32 j = 0; j < 6; j++)
{
if(tmp.ldir->ldir_name2[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name2[j]);
}
for(u32 j = 0; j < 2; j++)
{
if(tmp.ldir->ldir_name3[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name3[j]);
}
}
else if(fat_is_valid_file(tmp.file))
{
kmemcpy(file,tmp.file,sizeof(fat_dir_t));
return ((u64)dir_clus<<32)|(i+1);
}
}
dir_clus = fat_table_read_entry(fat,dir_clus);
} while(!IS_FAT_CLUS_EOF(dir_clus));
return 0;
}
u64 fat_next_file(fat_t* fat,u64 val,fat_dir_t* file,char* longname)
{
char* d;
int load_long = 1;
u32 dir_clus = val>>32;
u32 offset = val&0xFFFFFFFF;
if(offset == fat->dirsperclus)
{
offset = 0;
dir_clus = fat_table_read_entry(fat,dir_clus);
}
while(!IS_FAT_CLUS_EOF(dir_clus))
{
u32 i = 0;
if(offset)
{
i = offset;
offset = 0;
}
fat_read_cluster(fat,dir_clus);
for(;i < fat->dirsperclus; i++)
{
union {
fat_dir_t* file;
fat_ldir_t* ldir;
} tmp;
tmp.file = &((fat_dir_t*)fat->clusbuf)[i];
if(tmp.ldir->ldir_attr == FAT_ATTR_LONG_NAME && load_long)
{
if(IS_FAT_LDIR_LAST(tmp.ldir->ldir_ord))
{
tmp.ldir->ldir_ord &= ~(1<<6);
load_long = 0;
}
d = longname+(13*(tmp.ldir->ldir_ord-1));
for(u32 j = 0; j < 5; j++)
{
if(tmp.ldir->ldir_name1[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name1[j]);
}
for(u32 j = 0; j < 6; j++)
{
if(tmp.ldir->ldir_name2[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name2[j]);
}
for(u32 j = 0; j < 2; j++)
{
if(tmp.ldir->ldir_name3[j] == 0xFFFF)
{
load_long = 0;
continue;
}
*d++ = DBCS2SBCS(tmp.ldir->ldir_name3[j]);
}
}
else if(fat_is_valid_file(tmp.file))
{
kmemcpy(file,tmp.file,sizeof(fat_dir_t));
return ((u64)dir_clus<<32)|(i+1);
}
}
dir_clus = fat_table_read_entry(fat,dir_clus);
}
return 0;
}
int fat_find_file(fat_t* fat,fat_dir_t* parent,char* name,
fat_dir_t* out)
{
u64 handle;
fat_dir_t file;
char longname[256];
char name38[11];
if(!IS_VALID_FAT(fat)) return 0;
fat_nametofmt38(name,name38);
kmemzero(longname,sizeof(longname));
handle = fat_first_file(fat,parent,&file,longname);
if(handle)
{
do {
if(*longname != '\0')
{
if(!kstrcmp(longname,name))
{
kmemcpy(out,&file,sizeof(fat_dir_t));
return 1;
}
}
else
{
if(!kmemcmp(file.dir_name,name38,11))
{
kmemcpy(out,&file,sizeof(fat_dir_t));
return 1;
}
}
kmemzero(longname,sizeof(longname));
} while((handle = fat_next_file(fat,handle,&file,longname)));
}
return 0;
}
void fat_init(fat_t* fat,disk_t* disk)
{
fat->disk = disk;
fat->secbuf = (u8*)lvalloc(4096);
if(disk_read(fat->disk,0,1,fat->secbuf))
{
kprintf("Failed to init fat!\n");
fat->disk = NULL;
return;
}
fat->bps = *(u16*)(&fat->secbuf[11]);
fat->spc = *(u8*)(&fat->secbuf[13]);
fat->rsvdsec = *(u16*)(&fat->secbuf[14]);
fat->fatnum = *(u8*)(&fat->secbuf[16]);
fat->rootentcnt = *(u16*)(&fat->secbuf[17]);
fat->totsec = *(u32*)(&fat->secbuf[32]);
fat->fatsz = *(u32*)(&fat->secbuf[36]);
fat->rootclus = *(u32*)(&fat->secbuf[44]);
fat->clusbuf = (u8*)lvalloc(fat->spc*fat->bps);
fat->fatbuf = (u32*)lvalloc(fat->spc*fat->bps);
fat->fatsec = fat->rsvdsec;
fat->datasec = fat->fatsec+(fat->fatsz*fat->fatnum);
fat->fatentperclus = (fat->bps>>2)*fat->spc;
fat->dirsperclus = (fat->bps>>5)*fat->spc;
fat->cursec = 0;
fat->curclus = 0;
fat->curfatclus = 0;
}

102
kernel/fat.h Normal file
View file

@ -0,0 +1,102 @@
#ifndef __FAT_H
#define __FAT_H
#include "os.h"
#include "disk.h"
#include "string.h"
#define FAT_BAD_CLUSTER 0xFFFFFF7
#define IS_FAT_CLUS_RESVD(a) (a >= 0xFFFFFF8 && a <= 0xFFFFFFE)
#define FAT_END_CLUSTER 0xFFFFFFF
#define FAT_CLUSTER(a) (a&0x0FFFFFFF)
#define IS_FAT_CLUS_EOF(clus) ((clus >= FAT_BAD_CLUSTER) || (clus == 0))
#define FAT_ATTR_READONLY 0x01
#define FAT_ATTR_HIDDEN 0x02
#define FAT_ATTR_SYSTEM 0x04
#define FAT_ATTR_VOLUME_ID 0x08
#define FAT_ATTR_DIRECTORY 0x10
#define FAT_ATTR_ARCHIVE 0x20
#define FAT_ATTR_LONG_NAME (FAT_ATTR_READONLY \
|FAT_ATTR_HIDDEN \
|FAT_ATTR_SYSTEM \
|FAT_ATTR_VOLUME_ID)
#define IS_VALID_FAT(fat) (fat->disk != NULL)
typedef struct {
disk_t* disk;
u32 bps; //11 2
u32 spc; //13 1
u32 rsvdsec; //14 2
u32 fatnum; //16 1
u32 rootentcnt; //17 2
u32 totsec; //32 4
u32 fatsz; //36 4
u32 rootclus; //44 4
u32 fatentperclus;
u32 dirsperclus;
u32 fatsec;
u32 datasec;
u8* secbuf;
u8* clusbuf;
u8* clusbuf_ex;
u32* fatbuf;
u32 cursec;
u32 curclus;
u32 curfatclus;
} fat_t;
typedef struct {
char dir_name[11];
u8 dir_attr;
u8 dir_ntres;
u8 dir_crttimetenth;
u16 dir_crttime;
u16 dir_crtdate;
u16 dir_lstaccdate;
u16 dir_fstclushi;
u16 dir_wrttime;
u16 dir_wrtdate;
u16 dir_fstcluslo;
u32 dir_filesize;
} __packed fat_dir_t;
#define IS_FAT_LDIR_LAST(ord) (ord&0x40)
typedef struct {
u8 ldir_ord;
dbcs_t ldir_name1[5];
u8 ldir_attr;
u8 ldir_type;
u8 ldir_chksum;
dbcs_t ldir_name2[6];
u16 ldir_fstcluslo;
dbcs_t ldir_name3[2];
} __packed fat_ldir_t;
void fat_init(fat_t* fat,disk_t* disk);
void fat_read_cluster(fat_t* fat,u32 clus);
u32 fat_table_read_entry(fat_t* fat,u32 idx);
void fat_read_file(fat_t* fat,fat_dir_t* file,u8* __virt buf);
void fat_nametofmt38(const char* name,char* out);
void fat_fmt38toname(const char* name,char* out);
int fat_is_valid_file(fat_dir_t* file);
u64 fat_first_file(fat_t* fat,fat_dir_t* parent,fat_dir_t* file,
char* longname);
u64 fat_next_file(fat_t* fat,u64 val,fat_dir_t* file,char* longname);
int fat_find_file(fat_t* fat,fat_dir_t* parent,char* name,
fat_dir_t* out);
extern fat_t g_fat;
#endif

86
kernel/file.c Normal file
View file

@ -0,0 +1,86 @@
#include "file.h"
#include "stdlib.h"
#include "string.h"
#include "defines.h"
#include "heap.h"
// /dir/file.txt
static int file_find(fat_t* fat,fat_dir_t* out,const char* filename)
{
char name[512];
const char* s = filename;
char* d = name;
fat_dir_t _parent;
fat_dir_t file;
fat_dir_t* parent;
parent = NULL;
kmemzero(&file,sizeof(file));
kmemzero(&_parent,sizeof(_parent));
kmemzero(name,sizeof(name));
do {
if(*s != '/')
*d++ = *s;
s++;
if(*s == '/')
{
//kprintf("name %s\n",name);
//Find directory
if(kstrchr(s+1,'/'))
{
fat_find_file(fat,parent,name,&_parent);
if(_parent.dir_fstcluslo == 0) return 0;
}
kmemzero(name,sizeof(name));
d = name;
}
if(!kstrchr(s+1,'/')) //Check if we hit file name
{
fat_find_file(fat,parent,name,&file);
if(file.dir_fstcluslo != 0)
{
//kprintf("file %s\n",name);
kmemcpy(out,&file,sizeof(file));
return 1;
}
}
} while(*s);
return 0;
}
void* file_load(fat_t* fat,u32* psize,const char* name)
{
fat_dir_t file;
u32 clus;
u32 size;
u8* buf,*ptr;
kmemzero(&file,sizeof(file));
if(!file_find(fat,&file,name))
{
kprintf("File \"%s\" not found!\n",name);
return NULL;
}
size = file.dir_filesize;
if(psize) *psize = size;
buf = (u8*)kmalloc(size);
if(!buf)
{
kprintf("Not enough memory for \"%s\"!\n",name);
return NULL;
}
ptr = buf;
clus = (file.dir_fstclushi<<16)|file.dir_fstcluslo;
do {
u32 csize = MIN(size,(fat->spc*fat->bps));
fat_read_cluster(fat,clus);
kmemcpy(ptr,fat->clusbuf,csize);
ptr += csize;
csize -= csize;
clus = fat_table_read_entry(fat,clus);
} while(!IS_FAT_CLUS_EOF(clus));
return buf;
}

9
kernel/file.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef __FILE_H
#define __FILE_H
#include "os.h"
#include "fat.h"
void* file_load(fat_t* fat,u32* size,const char* name);
#endif

194
kernel/heap.c Normal file
View file

@ -0,0 +1,194 @@
#include "heap.h"
#include "defines.h"
#include "lvalloc.h"
#include "paging.h"
#include "stdlib.h"
#define MBLOCK_ATTR_ALLOC (1<<0)
#define IS_MBLOCK_ALLOC(mblock) (mblock->size & MBLOCK_ATTR_ALLOC)
//static mheap_t s_heap; //heap for all available RAM
/*void heap_init(mheap_t* heap,u64 size)
{
heap->heapsz = size>>21;
heap->heap = (u64*)mmap(NULL,(heap->heapsz<<21),
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE,
-1,
0
);
memset(heap->heap,0,(heap->heapsz<<21));
}*/
static mblock_t* mblock_get_next(mblock_t* block)
{
return (mblock_t*)((u8*)block+(block->size & ~7));
}
static mblock_t* mblock_by_data(void* data)
{
return (mblock_t*)((u8*)data-24);
}
static u64 mblock_get_size(mblock_t* block)
{
return block->size & ~7;
}
void heap_join(mblock_t* start,int dir)
{
mblock_t* cur;
u64 blk_size;
blk_size = 0;
cur = start;
while(cur != NULL && !IS_MBLOCK_ALLOC(cur))
{
blk_size += mblock_get_size(cur);
cur->size = 0;
if(dir > 0) cur = cur->next;
else if(dir < 0) cur = cur->prev;
}
if(dir > 0)
{
start->next = cur;
start->size = blk_size & ~7;
if(cur)
{
if(cur->next) cur->next->prev = start;
}
}
else if(dir < 0)
{
if(cur)
{
cur = cur->next;
cur->size = blk_size & ~7;
cur->next = start->next;
}
}
}
void heap_split(mblock_t* block,u64 req_size)
{
u64 tot_size = mblock_get_size(block);
mblock_t* split;
block->size = (req_size)|MBLOCK_ATTR_ALLOC;
split = mblock_get_next(block);
//Init prev and next
split->prev = block;
split->next = block->next;
block->next = split;
split->size = (tot_size-req_size) & ~7;
}
void* heap_alloc(mheap_t* heap,u64 size)
{
mblock_t* start,*block,*prev;
size = ROUND2_UP((size+24),5);
/*for(i = 0; i < heap->heapsz; i++)
{
start = (mblock_t*)((u8*)heap->heap+(i<<21));
if(!(start->size & MBLOCK_ATTR_ALLOC_2MB)) break;
}
if(i == heap->heapsz) return NULL;*/
start = (mblock_t*)heap->heap;
//Find free block
prev = NULL;
block = start;
do {
if((!IS_MBLOCK_ALLOC(block) && mblock_get_size(block) >= size)
|| block->size == 0)
break;
prev = block;
if(block->next) block = block->next;
else break;
} while(block);
if(prev == block) prev = NULL;
//Allocate
if(block->size == 0) //Unformatted
{
block->size = size|MBLOCK_ATTR_ALLOC;
block->prev = prev;
block->next = mblock_get_next(block);
}
else heap_split(block,size);
if(prev && !prev->next) prev->next = block;
return block->data;
}
void heap_free(mheap_t* heap,void* mem)
{
mblock_t* block = (mblock_t*)((u8*)mem-24);
(void)heap;
//Unlink
block->size &= ~MBLOCK_ATTR_ALLOC;
//Link free blocks prev and next
heap_join(block,1);
heap_join(block,-1);
}
void heap_init()
{
ram_pool_t* pool;
u64 addr = (u64)lvalloc_get_next_addr();
u64 i;
//Decide in which mapping we have lvalloc mapped and kernel
for(i = 0; i < lmem->ram_pools; i++)
{
pool = &lmem->ram_pool[i];
if(addr >= pool->start && addr < pool->end)
break;
}
if(i == lmem->ram_pools)
{
kprintf("heap_init failed!\n");
return;
}
lmem->heap.heap = (u64*)addr;
lmem->heap.heapsz = (((pool->end - addr)>>21) - 1);
kprintf("heap %p heapsz %u\n",lmem->heap.heap,lmem->heap.heapsz<<21);
//Identity page map
//page_map(s_heap.heap,s_heap.heap,s_heap.heapsz<<21);
for(u64 i = 0; i < (lmem->heap.heapsz<<21)>>12; i++)
{
page_map((u8*)lmem->heap.heap+(i<<12),(u8*)lmem->heap.heap+(i<<12),
4096);
}
kmemzero(lmem->heap.heap,lmem->heap.heapsz<<21);
}
void* kmalloc(u64 size)
{
return heap_alloc(&lmem->heap,size);
}
void* krealloc(void* addr,u64 newsize)
{
void* newaddr = kmalloc(newsize);
if(!newaddr) return NULL;
kmemcpy(newaddr,addr,mblock_get_size(mblock_by_data(addr))-24);
kfree(addr);
return newaddr;
}
void kfree(void* addr)
{
heap_free(&lmem->heap,addr);
}

12
kernel/heap.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef __HEAP_H
#define __HEAP_H
#include "os.h"
void heap_init();
void* kmalloc(u64 size);
void* krealloc(void* addr,u64 newsize);
void kfree(void* addr);
#endif

91
kernel/idt.c Normal file
View file

@ -0,0 +1,91 @@
#include "idt.h"
#include "stdlib.h"
extern void int0_handler();
extern void int1_handler();
extern void int2_handler();
extern void int3_handler();
extern void int4_handler();
extern void int5_handler();
extern void int6_handler();
extern void int7_handler();
extern void int8_handler();
extern void int9_handler();
extern void int10_handler();
extern void int11_handler();
extern void int12_handler();
extern void int13_handler();
extern void int14_handler();
extern void int15_handler();
extern void int16_handler();
extern void int17_handler();
extern void int18_handler();
extern void int19_handler();
extern void int20_handler();
extern void int21_handler();
extern void int22_handler();
extern void int23_handler();
extern void int24_handler();
extern void int25_handler();
extern void int26_handler();
extern void int27_handler();
extern void int28_handler();
extern void int29_handler();
extern void int30_handler();
extern void int31_handler();
static u32 idt_table[1024];
static inthandler_t inthandlers[256];
static inthandler_t handlers[32] = {
int0_handler,int1_handler,int2_handler,int3_handler,
int4_handler,int5_handler,int6_handler,int7_handler,
int8_handler,int9_handler,int10_handler,int11_handler,
int12_handler,int13_handler,int14_handler,int15_handler,
int16_handler,int17_handler,int18_handler,int19_handler,
int20_handler,int21_handler,int22_handler,int23_handler,
int24_handler,int25_handler,int26_handler,int27_handler,
int28_handler,int29_handler,int30_handler,int31_handler
};
static u64 cur_handler = 0;
void idt_set_handler(u8 idx,inthandler_t hndr,u8 type)
{
u32* item = (u32*)(&idt_table[idx<<2]);
u64 addr;
if(cur_handler == 32)
{
kprintf("idt_set_handler: no free handlers!\n");
return;
}
inthandlers[cur_handler] = hndr;
addr = (u64)handlers[cur_handler++];
item[0] = (OS_CODE_SELECTOR<<16)|(addr&0xFFFF);
item[1] = (((addr>>16)&0xFFFF)<<16)|(1<<15)|((type&0x0F)<<8);
item[2] = (addr>>32);
item[3] = 0;
}
void idt_call_handler(u8 handler)
{
if(inthandlers[handler])
{
inthandlers[handler]();
}
}
extern void _idt_install(void* table,u64 limit);
void idt_install()
{
kmemzero(idt_table,sizeof(idt_table));
kmemzero(inthandlers,sizeof(inthandlers));
_idt_install(idt_table,sizeof(idt_table));
}
void idt_enable_interrupts()
{
__asm("sti");
}

17
kernel/idt.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef __IDT_H
#define __IDT_H
#include "os.h"
#define IDT_TYPE_INTR 0x0E
#define IDT_TYPE_TRAP 0x0F
typedef void (*inthandler_t)();
void idt_set_handler(u8 idx,inthandler_t hndr,u8 type);
void idt_call_handler(u8 idx);
void idt_install();
void idt_enable_interrupts();
#endif

21
kernel/io.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef __IO_H
#define __IO_H
#include "os.h"
extern u8 inb(u16 port);
extern void outb(u16 port,u8 data);
extern u16 inw(u16 port);
extern void outw(u16 port,u16 data);
extern u32 inl(u16 port);
extern void outl(u16 port,u32 data);
extern void _insw(u16 port,u8* buffer,u32 count);
extern void _outsw(u16 port,u8* buffer,u32 count);
extern void _insw256(u16 port,u8* buffer);
extern void _outsw256(u16 port,u8* buffer);
#endif

174
kernel/keyboard.c Normal file
View file

@ -0,0 +1,174 @@
#include "keyboard.h"
#include "exceptions.h"
#include "idt.h"
#include "pic.h"
#include "pit.h"
#include "stdlib.h"
#include "vga_terminal.h"
static u8 s_i8keycode = 0;
static u8 s_i8keycode2 = 0;
static u32 s_ctrlkeys = 0;
static u8 s_keymap[128] = {
0, 0x1B,
'1','2',
'3','4','5','6',
'7','8','9','0',
'-','=',
0x08,
0x09,
'Q','W','E','R',
'T','Y','U','I',
'O','P','[',']',
0x0A,0,
'A','S','D','F',
'G','H','J','K',
'L',';','\'','`',
0,
'\\',
'Z','X','C','V',
'B','N','M',',',
'.','/',
0,
'*',
0,
' ',
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,
};
static char* eng_layout = "qwertyuiop[]\\asdfghjkl;'zxcvbnm`,./";
static char* rus_layout = "йцукенгшщзхъ\\фывапролджэячсмитьёбю.";
static int cur_layout = 0;
static char* shift_numbers = "!@#$%^&*()_+";
static void check_keys()
{
if((s_ctrlkeys & (CTRLKEYS_LSHIFT|CTRLKEYS_LALT))
== (CTRLKEYS_LSHIFT|CTRLKEYS_LALT))
cur_layout = !cur_layout;
}
static void _keyboard_ctrlkeys_update(u8 keychar,u8 event)
{
u8 ctrlkey;
ctrlkey = 0;
if(keychar == KEY_RSHIFT) ctrlkey = CTRLKEYS_RSHIFT;
else if(keychar == KEY_LSHIFT) ctrlkey = CTRLKEYS_LSHIFT;
else if(keychar == KEY_LALT) ctrlkey = CTRLKEYS_LALT;
if(event) s_ctrlkeys &= ~ctrlkey; //Released
else s_ctrlkeys |= ctrlkey; //Pressed
}
void keyboard_interrupt()
{
u8 status;
u8 keycode,keychar;
status = inb(0x64);
if(status & 1)
{
keycode = inb(0x60);
keychar = keycode & ~0x80;
s_i8keycode2 = keychar;
if(keychar == KEY_RSHIFT
|| keychar == KEY_LSHIFT
|| keychar == KEY_LALT)
{
_keyboard_ctrlkeys_update(keychar,keycode>>7);
s_i8keycode = 0;
}
else if(!(keycode & 0x80))
{
s_i8keycode = keychar;
//kprintf("%c",keyboard_ascii());
}
}
check_keys();
pic_send_eoi(1);
}
u8 keyboard_scan_code()
{
return s_i8keycode;
}
u8 keyboard_ascii()
{
u8 ascii;
if(s_i8keycode >= sizeof(s_keymap)) return 0;
ascii = s_keymap[s_i8keycode];
if(s_ctrlkeys & (CTRLKEYS_LSHIFT|CTRLKEYS_RSHIFT))
{
if((s_i8keycode >= 0x02) && (s_i8keycode <= 0x0D))
{
if(s_i8keycode >= 2)
ascii = shift_numbers[s_i8keycode-2];
}
if(ascii == '[') ascii = '{';
else if(ascii == ']') ascii = '}';
else if(ascii == '\\') ascii = '|';
else if(ascii == ';') ascii = ':';
else if(ascii == '\'') ascii = '"';
else if(ascii == ',') ascii = '<';
else if(ascii == '.') ascii = '>';
else if(ascii == '/') ascii = '?';
else if(ascii == '`') ascii = '~';
}
else if(ascii >= 0x41 && ascii <= 0x5A) ascii += 0x20;
return ascii;
}
static dbcs_t keyboard_layout_get_sym(u8 _chr)
{
u64 i;
u8 chr = ktolower(_chr);
for(i = 0; i < 34; i++)
if(eng_layout[i] == chr) break;
if(i == 34) return (dbcs_t)_chr;
if(cur_layout == 1)
{
char* sym = rus_layout;
while(i--)
sym += kchrlen(*sym);
return kchr2dbcs(sym);
}
return (dbcs_t)_chr;
}
dbcs_t keyboard_sym()
{
return keyboard_layout_get_sym(keyboard_ascii());
}
void keyboard_reset_irq1_vars()
{
s_i8keycode = 0;
}
void keyboard_enable()
{
pic_set_mask(1,1);
}
void keyboard_disable()
{
pic_set_mask(1,0);
}
void keyboard_install()
{
pic_set_mask(1,1);
idt_set_handler(33,keyboard_interrupt,IDT_TYPE_INTR);
}

52
kernel/keyboard.h Normal file
View file

@ -0,0 +1,52 @@
#ifndef __KEYBOARD_H
#define __KEYBAORD_H
#include "os.h"
#include "string.h"
#define CTRLKEYS_LSHIFT (1<<0)
#define CTRLKEYS_RSHIFT (1<<1)
#define CTRLKEYS_LALT (1<<2)
typedef enum {
//Controls keys
KEY_LSHIFT = 0x2A,
KEY_RSHIFT = 0x36,
KEY_LALT = 0x38,
//Numpad
KEY_NP_7 = 0x47,
KEY_NP_8,
KEY_NP_9,
KEY_NP_MINUS,
KEY_NP_4,
KEY_NP_5,
KEY_NP_6,
KEY_NP_PLUS,
KEY_NP_DOT,
//Functions
KEY_F1 = 0x3B,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11 = 0x57,
KEY_F12
} kb_keys_t;
void keyboard_install();
u8 keyboard_scan_code();
u8 keyboard_ascii();
dbcs_t keyboard_sym();
void keyboard_enable();
void keyboard_disable();
void keyboard_reset_irq1_vars();
#endif

250
kernel/kmain.c Normal file
View file

@ -0,0 +1,250 @@
#include "os.h"
#include "stdlib.h"
#include "string.h"
#include "idt.h"
#include "pic.h"
#include "pit.h"
#include "pci.h"
#include "exceptions.h"
#include "keyboard.h"
#include "paging.h"
#include "lvalloc.h"
#include "multiboot.h"
#include "disk.h"
#include "heap.h"
#include "file.h"
#include "fat.h"
#include "video.h"
// IDT
// PIC
// PIT
// paging
// keyboard
static char* xnums = "0123456789ABCDEF";
lmem_t* lmem;
disk_t* disk1;
void command_interpreter()
{
dbcs_t _command[64];
char command[128];
char name[512];
char* buf = (char*)kmalloc(4096);
while(1)
{
kputc('>');
kgets(_command,64);
kdbcs2str(_command,command,sizeof(command));
/*if(!kstrncmp(command,"ram_map"))
{
ram_map_t* ram = ram_get_map();
kprintf("RAM size = %u\nRAM pools %u\n",
ram->ram_total_size,ram->ram_pool_count);
for(u32 i = 0; i < ram->ram_pool_count; i++)
{
kprintf("\t%p\t%p\n",ram->ram_pools[i].start,
ram->ram_pools[i].end);
}
}
else if(!kstrncmp(command,"page_map"))
{
u32 virt,phys,size;
ksscanf(command,"page_map %p %p %u",&virt,&phys,&size);
page_map(virt,phys,size,PAGE_TABLE_READWRITE);
}
else if(!kstrncmp(command,"page_unmap"))
{
u32 virt,size;
ksscanf(command,"page_unmap %p %u",&virt,&size);
page_unmap(virt,size);
}
else if(!kstrncmp(command,"page_v2p"))
{
u32 virt;
ksscanf(command,"page_v2p %p",&virt);
kprintf("VIRT %p -> PHYS %p\n",virt,page_v2p(virt));
}
else */
if(!kstrncmp(command,"ram_map"))
{
kprintf("RAM size = %u\nRAM pools %u\n",
lmem->ram_size,lmem->ram_pools);
for(u32 i = 0; i < lmem->ram_pools; i++)
{
kprintf("\t%p\t%p\n",lmem->ram_pool[i].start,
lmem->ram_pool[i].end);
}
}
else if(!kstrncmp(command,"dump"))
{
u64 lines,virt;
ksscanf(command,"dump %u %p",&lines,&virt);
for(u64 i = 0; i < lines; i++)
{
kprintf("%p: ",virt);
for(u64 j = 0; j < 16; j++)
{
u8 byte;
byte = *(u8*)(virt+j);
kprintf("%c%c ",xnums[byte>>4],xnums[byte&0x0F]);
}
kprintf("\n");
virt += 16;
}
}
else if(!kstrncmp(command,"pci_dump"))
{
pci_dump();
}
else if(!kstrncmp(command,"hang"))
{
while(1){__asm("nop");}
}
else if(!kstrncmp(command,"lvalloc"))
{
u64 size;
ksscanf(command,"lvalloc %u",&size);
kprintf(":\t%p\n",lvalloc(size));
}
else if(!kstrncmp(command,"memcpy"))
{
u64 dst,src,size;
ksscanf(command,"memecpy %p %p %u",&dst,&src,&size);
kmemcpy((void*)dst,(const void*)src,size);
}
else if(!kstrncmp(command,"vcopy"))
{
char* src;
u64 size;
ksscanf(command,"vcopy %p %u",&src,&size);
for(u64 i = 0; i < size; i++) kputc(src[i]);
}
else if(!kstrncmp(command,"disk_read"))
{
char name[2];
u64 lba,num;
disk_t* disk;
ksscanf(command,"disk_read \"%s\" %u %u",name,2,&lba,&num);
disk = disk_get(name[0]);
disk_read(disk,lba,num,buf);
kprintf(":\tbuf %p\n",buf);
}
else if(!kstrncmp(command,"disk_info"))
{
kprintf("UID: %x %x\n",*(u64*)&disk1->uid,
*((u64*)(&disk1->uid)+1));
for(u64 i = 0; i < 4; i++)
{
kprintf("%x\t%x\n",disk1->parts[i].lba_start,
disk1->parts[i].lba_num);
kprintf("%x\t%x\n\n",disk1->parts[i].attributes,
disk1->parts[i].type);
}
}
else if(!kstrncmp(command,"malloc"))
{
u64 size;
ksscanf(command,"malloc %u",&size);
kprintf(":\t%p\n",kmalloc(size));
}
else if(!kstrncmp(command,"free"))
{
u64 addr;
ksscanf(command,"free %p",&addr);
kfree((void*)addr);
}
else if(!kstrncmp(command,"file_load"))
{
u32 size;
kmemzero(name,sizeof(name));
ksscanf(command,"load_file \"%s\"",
name,sizeof(name));
void* addr = file_load(&g_fat,&size,name);
kprintf(":\t%p\t%u\n",addr,size);
}
else if(!kstrncmp(command,"тестовая_команда"))
{
kprintf("Работает :D\n");
}
else if(!kstrncmp(command,"draw"))
{
ksscanf(command,"draw \"%s\"",name,sizeof(name));
u8* bmp = file_load(&g_fat,NULL,name);
if(!bmp)
{
kprintf("Ошибка!\n");
continue;
}
printbmp(bmp);
kfree(bmp);
}
/*else if(!kstrncmp(command,"sata_identify"))
{
sata_identify();
}*/
}
}
void kmain(lmem_t* lptr)
{
lmem = lptr;
cls();
chg_color(VGA_COLOR_LIGHT_MAGENTA);
idt_install();
idt_enable_interrupts();
pic_init(0x20,0x28);
pit_init();
install_exceptions();
keyboard_install();
__asm("sti");
mbt_scan_memory();
lvalloc_init();
pci_detect_hardware();
disk_init();
disk1 = disk_get('D');
disk_setup(disk1);
kprintf("disk1 size %f GB (%u MB)\n",
(((disk1->phys_totalsectors<<9)>>20)<<16)>>10,
(disk1->phys_totalsectors<<9)>>20);
kprintf("sizeof(lmem_t) %u\n",sizeof(lmem_t));
if(lmem->ram_size < (1073741824ULL))
{
//We're running under QEMU
disk1->cur_part = 1;
}
fat_init(&g_fat,disk1);
//Initialize heap. Since heap was intitialized, we can't use
//linear allocator (lvalloc) anymore
heap_init();
video_init();
vga_terminal_init();
u8* logo = file_load(&g_fat,NULL,"/logo.bmp");
bmp_draw((lmem->v_width>>1)-80,
0,160,lmem->vt_charh*10,logo);
kfree(logo);
for(u64 i = 0; i < 10; i++) kputc('\n');
kprintf("Леночка x86-64\n");
command_interpreter();
while(1){__asm("hlt");} //Should never return!
}

38
kernel/lvalloc.c Normal file
View file

@ -0,0 +1,38 @@
#include "lvalloc.h"
#include "paging.h"
#include "defines.h"
#include "stdlib.h"
void* lvalloc(size_t size)
{
u64 addr;
addr = (u64)lvalloc_get_next_addr();
page_map((void*)addr,(void*)addr,size);
lmem->lv_current += (ROUND2_UP(size,12) >> 12);
kmemzero((void*)addr,ROUND2_UP(size,12));
return (void*)addr;
}
void* lvalloc_get_next_addr()
{
return (void*)((u64)lmem->lv_start+(lmem->lv_current<<12));
}
void lvalloc_push()
{
lmem->lv_stack[--lmem->lv_sp] = lmem->lv_current;
}
void lvalloc_pop()
{
lmem->lv_current = lmem->lv_stack[lmem->lv_sp++];
}
void lvalloc_init()
{
lmem->lv_sp = MAX_LV_SSIZE;
lmem->lv_start = (u8*)(lmem->kernel_phys_addr + KERNEL_SIZE);
}

15
kernel/lvalloc.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef __LVALLOC_H
#define __LVALLOC_H
#include "os.h"
void* lvalloc(size_t size);
void lvalloc_push();
void lvalloc_pop();
void* lvalloc_get_next_addr();
void lvalloc_init();
#endif

36
kernel/multiboot.c Normal file
View file

@ -0,0 +1,36 @@
#include "os.h"
#include "multiboot.h"
#include "stdlib.h"
void mbt_scan_memory()
{
lmem->ram_size = 0;
lmem->ram_pools = 0;
multiboot_hdr_t* mbt = (multiboot_hdr_t*)((u64)lmem->multiboot);
multiboot_mmap_t* mmap = (multiboot_mmap_t*)((u64)mbt->mmap_addr);
while((u64)mmap < mbt->mmap_addr + mbt->mmap_length)
{
if(mmap->type == 1)
{
ram_pool_t* pool;
if(lmem->ram_pools == MAX_RAM_POOLS)
break;
pool = &lmem->ram_pool[lmem->ram_pools++];
pool->start = mmap->base_addr;
pool->end = mmap->base_addr + mmap->length;
lmem->ram_size += mmap->length;
}
mmap = (multiboot_mmap_t*)((u64)mmap + mmap->size + 4);
}
kprintf("RAM size %f\n",((lmem->ram_size>>20)<<16)>>10);
for(u64 i = 0; i < lmem->ram_pools; i++)
{
kprintf("RAM %x - %x\n",lmem->ram_pool[i].start,
lmem->ram_pool[i].end);
}
}

61
kernel/multiboot.h Normal file
View file

@ -0,0 +1,61 @@
#ifndef __MULTIBOOT_H
#define __MULTIBOOT_H
#include "os.h"
typedef struct {
u32 flags;
u32 mem_lower;
u32 mem_upper;
u32 boot_device;
u32 cmd_line;
u32 mods_count;
u32 mods_addr;
u32 syms[4];
u32 mmap_length;
u32 mmap_addr;
u32 drives_length;
u32 drives_addr;
u32 config_table;
u32 boot_loader_name;
u32 apm_table;
u32 vbe_control_info;
u32 vbe_mode_info;
u16 vbe_mode;
u16 vbe_interface_seg;
u16 vbe_interface_off;
u16 vbe_interface_len;
u64 framebuffer_addr;
u32 framebuffer_pitch;
u32 framebuffer_width;
u32 framebuffer_height;
u8 framebuffer_bpp;
u8 framebuffer_type;
u8 color_info[5];
} __attribute__((packed)) multiboot_hdr_t;
#define MBT_MMAP_TYPE_RAM 1
typedef struct {
u32 size;
u64 base_addr;
u64 length;
u32 type;
} __packed multiboot_mmap_t;
void mbt_scan_memory();
#endif

133
kernel/os.h Normal file
View file

@ -0,0 +1,133 @@
#ifndef __OS_H
#define __OS_H
#define OS_NULL_SELECTOR 0x00
#define OS_CODE_SELECTOR 0x08
#define OS_DATA_SELECTOR 0x10
#define OS_PM86_MEM_SIZE_4K (1024*1024)
//#define OS_VIDEO_BUFFER 0xC10B8000
#define OS_VIDEO_BUFFER 0x00000000000B8000
#define __packed __attribute__((packed))
#define __align(N) __attribute__((aligned(N)))
#define __format_arg(N) __attribute__((format_arg(N)))
#define __phys
#define __virt
#define NULL (void*)0
#define KERNEL_SIZE 0x1000000
#define MAX_RAM_POOLS 8
#define MAX_LV_SSIZE 8
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;
typedef char i8;
typedef short i16;
typedef int i32;
typedef long i64;
typedef unsigned long size_t;
typedef unsigned long ulong;
typedef long ilong;
typedef struct {
u64 __phys start;
u64 __phys end;
} ram_pool_t;
typedef struct mblock_s {
struct mblock_s* prev;
struct mblock_s* next;
u64 size;
u32 data[1];
} mblock_t;
typedef struct {
u64* heap; //heap ptr
u64 heapsz; //heap size in 2 MB blocks
} mheap_t;
typedef struct {
//LOADER
u64 gdt_entry[8];
//Paging
u64* p_pml4; //[512]
u64* p_pdp; //[OS_MAX_MEM_GBS]
u64* p_dir; //[512*OS_MAX_MEM_GBS]
u64* p_table; //[512*512*OS_MAX_MEM_GBS]
//Loader
u64 elf_ptr;
u64 paging_size;
u64 multiboot;
u64 gdt_limit;
u64 kernel_phys_base;
u64 kernel_phys_page;
u64 kernel_phys_addr;
u64 kernel_virt_addr;
//KERNEL
//RAM
u64 ram_size;
u64 ram_pools;
ram_pool_t ram_pool[MAX_RAM_POOLS];
//lvalloc
u8* lv_start;
u64 lv_current;
u64 lv_sp;
u64 lv_stack[8];
//heap
mheap_t heap;
//video
u64 v_stride;
u64 v_width;
u64 v_height;
u8* v_mem;
u64 v_bpp;
u64 v_size;
u64 v_r_p;
u64 v_r_s;
u64 v_g_p;
u64 v_g_s;
u64 v_b_p;
u64 v_b_s;
//video text
u64 vf_chars;
u64 vf_wchar; //fixed point
u64 vf_hchar; //fixed point
u16* vf_encodings;
u8* vf_bitmaps;
//text
u64 vt_charw;
u64 vt_charh;
u64 vt_chars;
u64 vt_lines;
} __packed lmem_t;
extern lmem_t* lmem;
extern void x64_rax_n_stop(u64 rax);
#endif

131
kernel/paging.c Normal file
View file

@ -0,0 +1,131 @@
#include "paging.h"
#include "defines.h"
//1 table entry - 4KB, entire table - 2 MB
//1 dir entry - 2 MB, entire directory - 1 GB
//1 pdp entry - 1 GB, entire PDP dir - 512 GB
//1 PML4 entry - 512 GB, entire PML4 dir - 256 TB
/*
void page_map(u64 virt,u64 phys)
{
u32 table_idx,dir_idx,pdp_idx;
u64 addr;
table_idx = (virt>>12) & 0x7FFFFFF;
dir_idx = table_idx>>9;
pdp_idx = dir_idx>>9;
if(!(lmem->p_pdp[pdp_idx] & 3))
{
addr = (u64)((u32)&lmem->p_dir[dir_idx]);
//kprintf("addr %l\n",&addr);
lmem->p_pdp[pdp_idx] = (addr&0xFFFFFFFFFFFFF000)|3;
}
if(!(lmem->p_dir[dir_idx] & 3))
{
addr = (u64)((u32)&lmem->p_table[table_idx]);
lmem->p_dir[dir_idx] = (addr&0xFFFFFFFFFFFFF000)|3;
}
lmem->p_table[table_idx] = (phys&0xFFFFFFFFFFFFF000)|3;
}*/
// RESERVED PML4 PDP DIR TABLE OFFSET
//0000000000000000 000000000 001111111 000000000 000000000 000000000000
void page_map(void* __virt virt,void* __phys phys,size_t size)
{
u64 table_idx,dir_idx,pdp_idx;
u64 table_cnt,dir_cnt,pdp_cnt;
u64 vaddr,paddr;
vaddr = (u64)virt;
paddr = (u64)phys;
table_idx = (vaddr>>12) & 0x7FFFFFF;
dir_idx = table_idx>>9;
pdp_idx = dir_idx>>9;
table_cnt = ROUND2_UP(size,12) >> 12;
dir_cnt = ROUND1_ADD((table_cnt>>9));
pdp_cnt = ROUND1_ADD((dir_cnt>>9));
for(u64 i = 0; i < table_cnt; i++)
{
lmem->p_table[table_idx+i] =
((paddr+(i<<12))&0xFFFFFFFFFFFFF000) | PAGE_TABLE_FLAGS;
}
for(u64 i = 0; i < dir_cnt; i++)
{
u64 addr;
addr = (u64)(&lmem->p_table[(dir_idx+i)<<9]);
lmem->p_dir[dir_idx+i] = (addr&0xFFFFFFFFFFFFF000) | PAGE_TABLE_FLAGS;
}
for(u64 i = 0; i < pdp_cnt; i++)
{
u64 addr;
addr = (u64)(&lmem->p_dir[(pdp_idx+i)<<9]);
lmem->p_pdp[pdp_idx+i] = (addr&0xFFFFFFFFFFFFF000) | PAGE_TABLE_FLAGS;
}
}
void page_unmap(void* __virt virt,size_t size)
{
u64 table_idx,dir_idx,pdp_idx;
u64 table_cnt,dir_cnt,pdp_cnt;
u64 vaddr;
vaddr = (u64)virt;
table_idx = (vaddr>>12) & 0x7FFFFFF;
dir_idx = table_idx>>9;
pdp_idx = dir_idx>>9;
table_cnt = ROUND2_UP(size,12) >> 12;
dir_cnt = ROUND1_ADD((table_cnt>>9));
pdp_cnt = ROUND1_ADD((dir_cnt>>9));
for(u64 i = 0; i < table_cnt; i++)
lmem->p_table[table_idx+i] = 0;
for(u64 i = 0; i < dir_cnt; i++)
{
u64 j;
//Check if directory empty
for(j = 0; j < 512; j++)
{
if(lmem->p_table[((dir_idx+i)<<9)+j] & PAGE_TABLE_FLAGS)
break;
}
//Empty
if(j == 512) lmem->p_dir[dir_idx+i] = 0;
}
for(u64 i = 0; i < pdp_cnt; i++)
{
u64 j;
//Check if PDP empty
for(j = 0 ; j < 512; j++)
{
if(lmem->p_dir[((pdp_idx+i)<<9)+j] & PAGE_TABLE_FLAGS)
break;
}
//Empty
if(j == 512) lmem->p_pdp[pdp_idx+i] = 0;
}
}
u64 __phys page_v2p(void* __virt virt)
{
u64 table_idx,page;
table_idx = (((u64)virt)>>12) & 0x7FFFFFF;
page = lmem->p_table[table_idx];
if(page & PAGE_TABLE_FLAGS) return page & 0xFFFFFFFFFFFFF000;
return -1;
}

14
kernel/paging.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef __PAGING_H
#define __PAGING_H
#include "os.h"
#define PAGE_TABLE_RRESENT (1<<0)
#define PAGE_TABLE_READWRITE (1<<1)
#define PAGE_TABLE_FLAGS (PAGE_TABLE_RRESENT|PAGE_TABLE_READWRITE)
void page_map(void* __virt virt,void* __phys phys,size_t size);
void page_unmap(void* __virt virt,size_t size);
u64 __phys page_v2p(void* __virt virt);
#endif

251
kernel/pci.c Normal file
View file

@ -0,0 +1,251 @@
#include "pci.h"
#include "vga_terminal.h"
#include "stdlib.h"
#include "io.h"
typedef struct {
u32 device_count;
pci_device_t devices[MAX_PCI_DEVICES];
} pci_hardware_t;
static pci_hardware_t s_pci;
struct pci_class_s {
u32 len;
const char* name;
};
static struct pci_class_s s_classes[] = {
{2,"Unclassified"},
{9,"Mass Storage Controller"},
{9,"Network Controller"},
{3,"Display Controller"},
{4,"Multimedia Controller"},
{2,"Memory controller"},
{11,"Bridge Device"},
{6,"Simple Communication Controller"},
{7,"Base System Peripheral"},
{5,"Input Device Controller"},
{0,"Docking Station"},
{0,"Processor"},
{10,"Serial Bus Controller"},
{0,"Wireless Controller"},
{0,"Intelligent Controller"},
{0,"Satellite Communication Controller"},
{0,"Encryption Controller"},
{0,"Signal Processing Controller"},
{0,"Processing Accelerator"},
{0,"Non-Essential Instrumentation"}
};
static char* s_subclasses[] = {
"Non-VGA-Compatible devices",
"VGA-Compatible Device",
"SCSI Bus Controller",
"IDE Controller",
"Floppy Disk Controller",
"IPI Bus Controller",
"RAID Controller",
"ATA Controller",
"Serial ATA",
"Serial Attached SCSI",
"Non-Volatile Memory Controller",
"Ethernet Controller",
"Token Ring Controller",
"FDDI Controller",
"ATM Controller",
"ISDN Controller",
"WorldFip Controller",
"PICMG 2.14 Multi Computing",
"Infiniband Controller",
"Fabric Controller",
"VGA Compatible Controller",
"XGA Controller",
"3D Controller (Not VGA-Compatible)",
"Multimedia Video Controller",
"Multimedia Audio Controller",
"Computer Telephony Device",
"Audio Device",
"RAM Controller",
"Flash Controller",
"Host Bridge",
"ISA Bridge",
"EISA Bridge",
"MCA Bridge",
"PCI-to-PCI Bridge",
"PCMCIA Bridge",
"NuBus Bridge",
"CardBus Bridge",
"RACEway Bridge",
"PCI-to-PCI Bridge",
"InfiniBand-to-PCI Host Bridge",
"Serial Controller",
"Parallel Controller",
"Multiport Serial Controller",
"Modem",
"IEEE 488.1/2 (GPIB) Controller",
"Smart Card",
"PIC",
"DMA Controller",
"Timer",
"RTC Controller",
"PCI Hot-Plug Controller",
"SD Host controller",
"IOMMU",
"Keyboard Controller",
"Digitizer Pen",
"Mouse Controller",
"Scanner Controller",
"Gameport Controller",
"FireWire (IEEE 1394) Controller",
"ACCESS Bus",
"SSA",
"USB Controller",
"Fibre Channel",
"SMBus",
"InfiniBand",
"IPMI Interface",
"SERCOS Interface (IEC 61491)",
"CANbus"
};
u32 pci_read_config_word(u32 bus,u32 device,u32 function,u32 offset)
{
u32 address;
bus &= 0xFF; // 8 bit
device &= 0x1F; // 5 bit
function &= 0x07; // 3 bit
offset &= 0xFC; // 6 bit
address = 0x80000000UL|(bus<<16)|(device<<11)|(function<<8)|(offset);
outl(PCI_CONFIG_ADDRESS,address);
return inl(PCI_CONFIG_DATA);
}
u32 pci_read_config_word_dev(pci_device_t dev,u32 offset)
{
u32 address;
offset &= 0xFC; // 6 bit
address = 0x80000000|((dev&0xFFFF0000)>>8)|(offset);
outl(PCI_CONFIG_ADDRESS,address);
return inl(PCI_CONFIG_DATA);
}
const char* pci_get_class(u32 class)
{
if(class >= sizeof(s_classes)/sizeof(struct pci_class_s))
return "Unknown";
return s_classes[class].name;
}
const char* pci_get_subclass(u32 class,u32 subclass)
{
u32 i,index;
if(class >= sizeof(s_classes)/sizeof(struct pci_class_s))
return "Unknown";
if(subclass >= sizeof(s_subclasses)/sizeof(const char*))
return "Unknown";
else if(subclass == 0x80) return "Other";
index = 0;
for(i = 0; i < class; i++)
index += s_classes[i].len;
if(i == class && subclass >= s_classes[i].len) return "Unknown";
return s_subclasses[index+subclass];
}
void pci_dump()
{
for(u32 i = 0; i < s_pci.device_count; i++)
{
u32 class,subclass;
class = (s_pci.devices[i]>>8)&0xFF;
subclass = s_pci.devices[i] & 0xFF;
kprintf("%x\t%s\t%s\n",
s_pci.devices[i],
pci_get_class(class),
pci_get_subclass(class,subclass));
}
}
static void pci_add_device(u32 bus,u32 device,u32 func,
u32 class,u32 subclass)
{
pci_device_t dev;
dev = (bus<<24)|(device<<19)|(func<<16)|(class<<8)|(subclass);
if(s_pci.device_count < MAX_PCI_DEVICES)
s_pci.devices[s_pci.device_count++] = dev;
}
static void pci_scan_bus(u32 bus);
static void pci_scan_device(u32 bus,u32 dev,u32 func)
{
u32 class = pci_read_config_word(bus,dev,func,0x08) >> 16;
u32 hdr = (pci_read_config_word(bus,dev,func,0x0C) >> 16) & 0xFF;
if(class == 0x0604) //PCI-to-PCI bridge
{
pci_scan_bus((pci_read_config_word(
bus,dev,func,0x18) >> 8) & 0xFF);
}
if(hdr & 0x80 && func == 0) //Multifunction
{
for(u32 i = 1; i < 8; i++)
{
u32 vendor = pci_read_config_word(bus,dev,i,0x00) & 0xFFFF;
if(vendor != 0xFFFF)
pci_scan_device(bus,dev,i);
}
}
pci_add_device(bus,dev,func,class>>8,class&0xFF);
}
static void pci_scan_bus(u32 bus)
{
for(u32 i = 0; i < 32; i++)
{
u32 vendor = pci_read_config_word(bus,i,0,0x00) & 0xFFFF;
if(vendor != 0xFFFF)
pci_scan_device(bus,i,0);
}
}
void pci_detect_hardware()
{
s_pci.device_count = 0;
for(u32 i = 0; i < 256; i++)
pci_scan_bus(i);
}
pci_device_t pci_find_device(u32 class,u32 subclass)
{
u32 data = class<<8|subclass;
for(u32 i = 0; i < s_pci.device_count; i++)
{
if((s_pci.devices[i] & 0xFFFF) == data)
return s_pci.devices[i];
}
return 0;
}

24
kernel/pci.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef __PCI_H
#define __PCI_H
#include "os.h"
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
#define MAX_PCI_DEVICES 256
// bbbbbbbbdddddfffccccccccssssssss
typedef u32 pci_device_t;
u32 pci_read_config_word(u32 bus,u32 device,u32 function,u32 hword);
u32 pci_read_config_word_dev(pci_device_t dev,u32 hword);
void pci_dump();
void pci_detect_hardware();
//Returns device index
//-1 for NOTFOUND
pci_device_t pci_find_device(u32 class,u32 subclass);
#endif

45
kernel/pic.c Normal file
View file

@ -0,0 +1,45 @@
#include "pic.h"
void pic_init(int master,int slave)
{
outb(PIC1,ICW1);
outb(PIC2,ICW1);
outb(PIC1+1,master&0xFF);
outb(PIC2+1,slave&0xFF);
outb(PIC1+1,4);
outb(PIC2+1,2);
outb(PIC1+1,ICW4);
outb(PIC2+1,ICW4);
//Disable all IRQs
outb(PIC1+1,0xFF);
outb(PIC2+1,0xFF);
}
void pic_set_mask(int irq,int enabled)
{
u16 pic;
u8 mask;
if(irq >= 8)
{
pic = PIC2+1;
irq -= 8;
}
else pic = PIC1+1;
mask = inb(pic);
if(enabled) mask &= ~(1<<irq);
else mask |= (1<<irq);
outb(pic,mask);
}
void pic_send_eoi(int irq)
{
if(irq >= 8) outb(PIC2,0x20);
outb(PIC1,0x20);
}

16
kernel/pic.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef __PIC_H
#define __PIC_H
#include "io.h"
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
void pic_init(int master,int slave);
void pic_set_mask(int irq,int enabled);
void pic_send_eoi(int irq);
#endif

36
kernel/pit.c Normal file
View file

@ -0,0 +1,36 @@
#include "pit.h"
#include "pic.h"
#include "idt.h"
static u64 s_counter = 0;
void timer_interrupt()
{
if(s_counter) s_counter--;
pic_send_eoi(0);
}
void sleep(u64 msecs)
{
__asm("cli");
if(msecs < 55) msecs = 55;
s_counter = msecs/55;
__asm("sti");
//pic_set_mask(0,1);
do {
__asm("hlt"); //Wait for IRQ
} while(s_counter);
//pic_set_mask(0,0);
}
void pit_init()
{
//Setup IRQ
idt_set_handler(32,timer_interrupt,IDT_TYPE_INTR);
pic_set_mask(0,1);
//Init PIT
outb(0x43,0x36);
outb(0x40,0x00);
outb(0x40,0x00);
}

10
kernel/pit.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __PIT_H
#define __PIT_H
#include "io.h"
void sleep(u64 msecs);
void pit_init();
#endif

17
kernel/start.asm Normal file
View file

@ -0,0 +1,17 @@
use64
section .bss
align 16
resb 65536 ; 64 KiB stack
stack_top:
section .text
global _start
extern kmain
_start:
cli
mov rsp,stack_top
call kmain
cli
hlt

444
kernel/stdlib.c Normal file
View file

@ -0,0 +1,444 @@
#include "stdlib.h"
#include "vga_terminal.h"
#include "keyboard.h"
#include "string.h"
#include "va_list.h"
void iprint(i64 number)
{
//18446744073709551615
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number >= 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
s--;
while(s >= num) printchar(*s--);
}
void uprint(u64 number)
{
//18446744073709551615
char num[32];
char* s = num;
while(number >= 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
s--;
while(s >= num) printchar(*s--);
}
static char* xnums = "0123456789ABCDEF";
void xprint(u64 number)
{
//FFFFFFFFFFFFFFFF
char num[32];
char* s = num;
while(s-num < 15)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
s--;
while(s >= num) printchar(*s--);
}
void fprint(u64 number)
{
u64 val;
char num[64];
int i;
//decimal
i = 0;
val = number>>16;
while(val != 0)
{
num[i++] = '0'+(val%10);
val /= 10;
}
num[i++] = '0'+(val%10);
while(i != 0) printchar(num[--i]);
//fraction
i = 0;
val = number&0xFFFF;
printchar('.');
while(val != 0)
{
val *= 10;
printchar('0'+(val>>16));
val &= 0xFFFF;
}
}
void iprints(char* outs,i64 number)
{
//18446744073709551615
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number >= 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void uprints(char* outs,u64 number)
{
//18446744073709551615
char num[32];
char* s = num;
while(number >= 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void xprints(char* outs,u64 number)
{
//FFFFFFFFFFFFFFFF
char num[32];
char* s = num;
while(s-num < 15)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void kprint(char* str)
{
print(str);
}
void ksprintf(char* dst,size_t maxLen,const char* fmt,...)
{
va_list ap;
va_start(&ap);
u64 idx;
char* cur,*end,c;
char numbuf[64];
idx = 1;
cur = dst;
end = dst+maxLen;
while((c = *fmt++) && cur != end)
{
if(c == '%')
{
char* p = numbuf;
c = *fmt++;
if(c == 'd')
{
iprints(numbuf,(ilong)va_arg(&ap,idx++));
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'u')
{
uprints(numbuf,(ilong)va_arg(&ap,idx++));
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'p' || c == 'x')
{
xprints(numbuf,(ulong)va_arg(&ap,idx++));
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 's')
{
const char* str = (const char*)va_arg(&ap,idx++);
while((*cur++ = *str++))
if(cur == end) break;
cur--;
}
else if(c == '%')
{
if(cur != end) *cur++ = '%';
}
}
else
{
if(cur == end) break;
*cur++ = c;
}
}
if(cur == end)
*(end-1) = '\0';
}
void kprintf(const char* fmt,...)
{
va_list ap;
va_start(&ap);
u64 idx;
dbcs_t c;
idx = 1;
//while((c = *fmt++))
do
{
c = kchr2dbcs(fmt);
if(!c) break;
fmt += kchrlen(*fmt);
if(c == '%')
{
//c = *fmt++;
c = kchr2dbcs(fmt);
fmt += kchrlen(*fmt);
switch(c)
{
case 'd': iprint((i64)va_arg(&ap,idx++)); break;
case 'u': uprint((u64)va_arg(&ap,idx++)); break;
case 'p':
case 'x': xprint((u64)va_arg(&ap,idx++)); break;
case 'c': printchar((char)(va_arg(&ap,idx++))); break;
case 's': kprint((char*)(va_arg(&ap,idx++))); break;
case 'f': fprint((u64)(va_arg(&ap,idx++))); break;
case '%': printchar('%'); break;
}
}
else printchar(c);
} while(c);
}
u8 kgetch()
{
u8 key;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
key = keyboard_scan_code();
keyboard_reset_irq1_vars();
return key;
}
dbcs_t kgetc()
{
dbcs_t ascii;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
ascii = keyboard_sym();
keyboard_reset_irq1_vars();
return ascii;
}
void kgets(dbcs_t* buf,size_t cMax)
{
dbcs_t ch;
dbcs_t* ptr,*end;
ptr = buf;
end = buf + cMax;
*ptr = '\0';
while((ch = kgetc()) != '\n')
{
if(ch == '\b')
{
if(ptr != buf) *ptr-- = '\0';
printchar('\b');
}
else if(ptr != end-1)
{
*ptr++ = ch;
printchar(ch);
}
}
printchar('\n');
if(ptr == end) ptr--;
*ptr = '\0';
}
//static char* katoi_base = "0123456789ABCDEF";
static i64 _katoi(char* str,int base,size_t len)
{
char* end;
i64 i,pow;
i64 num;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == '-')
{
num *= -1;
break;
}
else if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == xnums[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
static u64 _katou(char* str,int base,u64 len)
{
char* end;
u64 pow,num;
i64 i;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == xnums[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
i64 katoi(char* str,int base)
{
return _katoi(str,base,kstrlen(str));
}
u64 katou(char* str,int base)
{
return _katou(str,base,kstrlen(str));
}
static u64 _kstrchr_delim(char* buf,u32 base)
{
u64 i,len;
char c;
len = 0;
while(*buf)
{
c = *buf;
for(i = 0; i < base; i++)
{
if(c == xnums[i]) break;
}
if(i == base && c != '-') break;
buf++;
len++;
}
return len;
}
void ksscanf(char* buf,char* fmt,...)
{
//ulong* argp;
va_list ap;
va_start(&ap);
u64 idx;
ulong len,maxLen;
union {
i64* iptr;
u64* uptr;
char* sptr;
} u;
char c,*stk;
idx = 2;
while((c = *fmt))
{
//kprintf("%c %c\n",c,*buf);
if(c == '%')
{
c = *++fmt;
switch(c)
{
case 'u':
case 'd':
len = _kstrchr_delim(buf,10);
u.iptr = (i64*)(va_arg(&ap,idx++));
*u.iptr = _katoi(buf,10,len);
buf += len; //we decrement because it will +1
break;
case 'p':
case 'x':
buf += 2; //Skip 0x part
len = _kstrchr_delim(buf,16);
u.iptr = (i64*)(va_arg(&ap,idx++));
*u.iptr = _katoi(buf,16,len);
buf += len; //we decrement because it will +1
break;
case 's':
stk = (char*)kstrchr(buf,*(fmt+1));
u.sptr = (char*)(va_arg(&ap,idx++));
maxLen = (ulong)(va_arg(&ap,idx++));
if(!stk)
{
u.sptr[0] = '\0';
break;
}
len = (u64)stk-(u64)buf;
if(len > maxLen) len = maxLen;
kmemcpy(u.sptr,buf,len);
u.sptr[len] = '\0';
buf += len;
break;
}
} else buf++;
fmt++;
}
}

45
kernel/stdlib.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef __STDLIB_H
#define __STDLIB_H
#include "os.h"
#include "vga_terminal.h"
#include "string.h"
//stdlib.h
extern void kmemcpy(void* dst,const void* src,size_t len);
extern int kmemcmp(const void* dst,const void* src,size_t len);
extern void kmemzero(void* dst,size_t len);
//termlib.h
#define kputc printchar
void iprint(i64 number);
void uprint(u64 number);
void xprint(u64 number);
void iprints(char* str,i64 number);
void uprints(char* str,u64 number);
void xprints(char* str,u64 number);
void kprint(char* str);
void ksprintf(char* dst,size_t maxLen,const char* fmt,...);
void kprintf(const char* fmt,...);
//termio.h
u8 kgetch(); //Wait for key scan code
dbcs_t kgetc(); //Wait for ASCII character
void kgets(dbcs_t* buf,size_t cMax);
i64 katoi(char* str,int base);
void ksscanf(char* buf,char* fmt,...);
#define _debug() \
kprintf("_debug at %s:%u\n",__FILE__,__LINE__); \
kgetc();
#endif

142
kernel/string.c Normal file
View file

@ -0,0 +1,142 @@
#include "string.h"
#include "stdlib.h"
size_t kstrlen(const char* str)
{
u32 len = 0;
while(*str++) len++;
return len;
}
void kstrcpy(char* dst,const char* src)
{
while((*dst++ = *src++)){}
}
void kstrncpy(char* dst,const char* src,size_t maxLen)
{
maxLen=-1;
while((*dst++ = *src++) && --maxLen){}
if(!maxLen) dst[maxLen] = '\0';
}
const char* kstrchr(const char* src,char chr)
{
while(*src)
{
if(*src == chr) return src;
src++;
}
return NULL;
}
const char* kstrrchr(const char* src,char chr)
{
const char* ptr;
ptr = src+kstrlen(src)-1;
while(ptr != src)
{
if(*ptr == chr) return ptr;
ptr--;
}
return NULL;
}
int kstrcmp(const char* src,const char* dst)
{
if(kstrlen(src) != kstrlen(dst)) return 1;
while(*src)
if(*src++ != *dst++) return 1;
return 0;
}
int kstrncmp(const char* haystack,char* needle)
{
return kmemcmp(haystack,needle,kstrlen(needle));
}
int kstrcasecmp(const char* src,const char* dst)
{
if(kstrlen(src) != kstrlen(dst)) return 1;
while(*src)
{
kprintf("%c %c\n",ktolower(*src),ktolower(*dst));
if(ktolower(*src++) != ktolower(*dst++)) return 1;
}
return 0;
}
char ktoupper(char c)
{
if(c >= 0x61 && c <= 0x7A) return c&0xDF;
return c;
}
char ktolower(char c)
{
if(c >= 0x41 && c <= 0x5A) return c|(1<<5);
return c;
}
size_t kchrlen(char cchr)
{
u8 chr = (u8)cchr;
if(chr & 0b10000000)
{
if((chr>>5) == 0b110) return 2;
else if((chr>>4) == 0b1110) return 3;
else if((chr>>5) == 0b11110) return 4;
}
return 1;
}
dbcs_t kchr2dbcs(const char* ptr)
{
const u8* chr = (u8*)ptr;
switch(kchrlen(chr[0]))
{
case 1: return chr[0]&0x7F;
case 2: return ((chr[0]&0x1F)<<6)|(chr[1]&0x3F);
case 3: return ((chr[0]&0x0F)<<12)|((chr[1]&0x3F)<<6)|(chr[2]&0x3F);
default: return 0x003F;
}
}
size_t kdbcslen(dbcs_t chr)
{
if(chr > 0x7FF) return 3;
else if(chr > 0x7F) return 2;
return 1;
}
void kdbcs2str(dbcs_t* dbcs,char* str,size_t maxStr)
{
char* end = str + maxStr - 1;
dbcs_t wc;
while((wc = *dbcs++) && str != end)
{
size_t len = kdbcslen(wc);
if((str+len) >= end) break;
switch(len)
{
case 1:
*str++ = wc&0x7F;
break;
case 2:
*str++ = 0b11000000|((wc>>6)&0x1F);
*str++ = 0b10000000|((wc)&0x3F);
break;
case 3:
*str++ = 0b11100000|((wc>>12)&0x0F);
*str++ = 0b10000000|((wc>>6)&0x3F);
*str++ = 0b10000000|((wc)&0x3F);
break;
default: *str++ = '?';
}
}
*str++ = '\0';
}

31
kernel/string.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef __STRING_H
#define __STRING_H
#include "os.h"
#define DBCS2SBCS(dbcs) ((char)(dbcs&0xFF))
typedef u16 dbcs_t;
size_t kstrlen(const char* str);
void kstrcpy(char* dst,const char* src);
void kstrncpy(char* dst,const char* src,size_t maxLen);
const char* kstrchr(const char* src,char chr);
const char* kstrrchr(const char* src,char chr);
int kstrcmp(const char* src,const char* dst);
int kstrncmp(const char* haystack,char* needle);
int kstrcasecmp(const char* src,const char* dst);
char ktoupper(char c);
char ktolower(char c);
size_t kchrlen(char chr);
dbcs_t kchr2dbcs(const char* chr);
size_t kdbcslen(dbcs_t chr);
void kdbcs2str(dbcs_t* dbcs,char* str,size_t maxStr);
#endif

41
kernel/va_list.asm Normal file
View file

@ -0,0 +1,41 @@
section .text
global va_start
global va_arg
va_start:
; RDI va_list
mov rax,rsp
mov rsp,rdi
add rsp,0x30
push r9
push r8
push rcx
push rdx
push rsi
push rdi
mov rsp,rax
ret
va_arg:
; RDI va_list
; RSI index
push rbx
mov rbx,rsi
shl rbx,3
cmp rsi,6
jge .va_stack
mov rax,[rdi+rbx]
pop rbx
ret
.va_stack:
sub rbx,0x30
add rbx,0x10
mov rax,[rbp+rbx]
pop rbx
ret

13
kernel/va_list.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef __VA_LIST_H
#define __VA_LIST_H
#include "os.h"
typedef struct {
u64 args[6];
} va_list;
extern void va_start(va_list*);
extern u64 va_arg(va_list*,u64);
#endif

175
kernel/vga_terminal.c Normal file
View file

@ -0,0 +1,175 @@
#include "vga_terminal.h"
//#include "paging.h"
#include "video.h"
#include "heap.h"
#include "string.h"
#include "stdlib.h"
#include "defines.h"
#include "bmp.h"
#include "os.h"
#include "io.h"
static u8 s_cCurAttr = DEFAULT_COLOR;
u32 s_iX;
u32 s_iY;
static u16* s_video_buffer = 0;
static int s_video_init = 0;
static void draw_char(u16 sym,u32 color);
static u32 vga_palette[] = {
0x000000,
0x0000AA,
0x00AA00,
0x00AAAA,
0xAA0000,
0xAA00AA,
0xAA5500,
0xAAAAAA,
0x555555,
0x5555FF,
0x55FF55,
0x55FFFF,
0xFF5555,
0xFF55FF,
0xFFFF55,
0xFFFFFF,
};
void vga_terminal_init()
{
s_video_buffer = (u16*)kmalloc(4000);
s_video_init = 1;
lmem->vt_chars = 80;
lmem->vt_lines = 25;
lmem->vt_charw = lmem->v_width/lmem->vt_chars;
lmem->vt_charh = lmem->v_height/lmem->vt_lines;
s_iX = 0;
s_iY = 0;
}
void update_cursor()
{
/*u16 pos;
pos = s_iY * 80 + s_iX;
outb(0x3D4, 0x0F);
outb(0x3D5, (u8) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (u8) ((pos >> 8) & 0xFF));*/
}
void cls()
{
if(!s_video_init) return;
//kmemzero((void*)s_video_buffer,sizeof(u16)*80*25);
video_clear();
s_iX = s_iY = 0;
update_cursor();
}
void shiftscreen();
static void draw_char(u16 sym,u32 color)
{
if(!sym && !color)
{
video_rect_zero(s_iX*lmem->vt_charw,s_iY*lmem->vt_charh,
lmem->vt_charw,lmem->vt_charh);
}
video_char(s_iX*lmem->vt_charw,s_iY*lmem->vt_charh,
lmem->vt_charw,lmem->vt_charh,color,sym);
}
void printchar(u16 c)
{
if(!s_video_init) return;
if(c == '\n' || c == '\r' || c == '\t' || c == '\b') // Control characters
{
if(c == '\r') s_iX = 0;
else if(c == '\n') s_iX = SCR_CHARS;
else if(c == '\t') s_iX = (s_iX + 8) & ~7;
else if(c == '\b')
{
if(s_iX) s_iX--;
else if(s_iY)
{
s_iY--;
s_iX = SCR_CHARS-1;
}
//Remove character
//SCR_TEXT_BUF[s_iY*SCR_CHARS+s_iX] = SCR_ENTRY(0,s_cCurAttr);
draw_char(0,0);
}
}
else // Text characters
{
//SCR_TEXT_BUF[s_iY*SCR_CHARS+s_iX++] = SCR_ENTRY(c,s_cCurAttr);
draw_char(c,vga_palette[s_cCurAttr]);
s_iX++;
}
if(s_iX > SCR_CHARS-1)
{
s_iX = 0;
if(s_iY < SCR_LINES-1)
s_iY++;
else shiftscreen();
}
update_cursor();
}
void printbmp(u8* bmp)
{
//scroll
//u64 scroll = s_iY
u32 h = *(u32*)(bmp+0x16);
h = MIN(h,lmem->v_height);
u64 lines = (h/lmem->vt_charh) + 1;
kprintf("lines %u\n",lines);
for(u64 i = 0; i < lines; i++) kputc('\n');
bmp_draw(s_iX*lmem->vt_charw,(s_iY-lines-1)*lmem->vt_charh,
0,h,bmp);
}
void shiftscreen()
{
u32 y;
if(!s_video_init) return;
video_line_zero(0,lmem->vt_charh);
for(y = 1; y < lmem->vt_lines; y++)
{
video_line_copy(y*lmem->vt_charh,(y-1)*lmem->vt_charh,
lmem->vt_charh);
}
video_line_zero(lmem->vt_charh*(lmem->vt_lines-1),
lmem->vt_charh);
}
void chg_color(u8 color)
{
s_cCurAttr = color;
}
void print(const char* str)
{
while(*str)
{
printchar(kchr2dbcs(str));
str += kchrlen(*str);
}
}
void move_to_next_char(){}
void move_to_next_line(){}
void locate(int h, int w)
{
s_iX = w;
s_iY = h;
}

68
kernel/vga_terminal.h Normal file
View file

@ -0,0 +1,68 @@
#ifndef __VGA_TERMINAL_H
#define __VGA_TERMINAL_H
#include "os.h"
#define SCR_CHARS 80
#define SCR_LINES 25
//#define SCR_TEXT_BUF ((u16*)0xB8000)
#define SCR_TEXT_BUF ((u16*)OS_VIDEO_BUFFER)
#define SCR_ENTRY(ch,col) ((col<<8)|ch)
#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 2
#define RED 4
#define GRAY 8
#define WHITE 15
#define MAGENTA 13
#define BG_BLACK (0<<4)
#define BG_BLUE (1<<4)
#define BG_GREEN (2<<4)
#define BG_RED (4<<4)
#define BG_GRAY (8<<4)
#define BG_WHITE (15<<4)
#define DEFAULT_COLOR BG_BLACK|7
enum vga_color {
VGA_COLOR_BLACK = 0,
VGA_COLOR_BLUE = 1,
VGA_COLOR_GREEN = 2,
VGA_COLOR_CYAN = 3,
VGA_COLOR_RED = 4,
VGA_COLOR_MAGENTA = 5,
VGA_COLOR_BROWN = 6,
VGA_COLOR_LIGHT_GREY = 7,
VGA_COLOR_DARK_GREY = 8,
VGA_COLOR_LIGHT_BLUE = 9,
VGA_COLOR_LIGHT_GREEN = 10,
VGA_COLOR_LIGHT_CYAN = 11,
VGA_COLOR_LIGHT_RED = 12,
VGA_COLOR_LIGHT_MAGENTA = 13,
VGA_COLOR_LIGHT_BROWN = 14,
VGA_COLOR_WHITE = 15,
};
static inline u8 vga_entry_color(enum vga_color fg, enum vga_color bg) {
return fg | bg << 4;
}
static inline u16 vga_entry(unsigned char uc, u8 color) {
return (u16) uc | (u16) color << 8;
}
void vga_terminal_init();
void cls();
void shiftscreen();
void printchar(u16 c);
void printbmp(u8* bmp);
void chg_color(u8 color);
void print(const char* str);
void locate(int h, int w);
#endif

140
kernel/video.c Normal file
View file

@ -0,0 +1,140 @@
#include "video.h"
#include "heap.h"
#include "paging.h"
#include "stdlib.h"
#include "defines.h"
#include "multiboot.h"
#include "string.h"
extern u8* x64_get_font();
void video_pixel(u64 x,u64 y,u32 color)
{
u64 off = (y*lmem->v_stride) + (x*lmem->v_bpp);
if(lmem->v_bpp == 3)
{
u32 dat = (*(u32*)&lmem->v_mem[off]) & 0xFF000000;
lmem->v_mem[off] = (color & 0x00FFFFFF) | dat;
}
else *(u32*)(lmem->v_mem+off) = color;
}
static u8* video_font_get_bitmap(u16 sym)
{
u64 i;
for(i = 0; i < lmem->vf_chars; i++)
if(lmem->vf_encodings[i] == sym) break;
if(i == lmem->vf_chars) return NULL;
return &lmem->vf_bitmaps[i<<4];
}
void video_char(u64 x,u64 y,u64 sizew,u64 sizeh,u32 color,u16 sym)
{
//h size is always twice
u64 f_w = (sizew<<32) / (8ULL<<16ULL);
u64 f_h = (sizeh<<32) / (16ULL<<16ULL);
u8* bmap;
bmap = video_font_get_bitmap(sym);
if(!bmap)
{
x64_rax_n_stop(0xDEADBEEF);
return;
}
u64 c_y = y;
for(u64 i = 0; i < 16; i++)
{
u64 c_x = x;
for(u64 j = 0; j < 8; j++)
{
if((bmap[i]>>(7-j)) & 1)
{
for(u64 k = 0; k < (f_w>>16); k++)
{
video_pixel(c_x+k,c_y,color);
for(u64 l = 1; l < (f_h>>16); l++)
video_pixel(c_x+k,c_y+l,color);
}
}
c_x = ((c_x<<16) + f_w) >> 16;
}
c_y = ((c_y<<16) + f_h) >> 16;
}
}
void video_rect_zero(u64 x,u64 y,u64 w,u64 h)
{
u64 len = w*lmem->v_bpp;
for(u32 i = 0; i < h; i++)
{
u32* line = (u32*)&lmem->v_mem[(y+i)*lmem->v_stride+(x*lmem->v_bpp)];
kmemzero(line,len);
}
}
void video_line_copy(u64 ysrc,u64 ydst,u64 height)
{
kmemcpy(lmem->v_mem+(ydst*lmem->v_stride),
lmem->v_mem+(ysrc*lmem->v_stride),
lmem->v_stride*height);
}
void video_line_zero(u64 y,u64 height)
{
kmemzero(lmem->v_mem+(y*lmem->v_stride),
height*lmem->v_stride);
}
void video_clear()
{
kmemzero(lmem->v_mem,lmem->v_size);
}
void video_swap()
{
//kmemcpy(lmem->v_mem,lmem->v_mem,lmem->v_size);
}
void video_init()
{
multiboot_hdr_t* hdr = (multiboot_hdr_t*)lmem->multiboot;
lmem->v_stride = hdr->framebuffer_pitch;
lmem->v_width = hdr->framebuffer_width;
lmem->v_height = hdr->framebuffer_height;
lmem->v_mem = (u8*)hdr->framebuffer_addr;
lmem->v_bpp = hdr->framebuffer_bpp>>3;
lmem->v_size = lmem->v_stride*lmem->v_height;
lmem->v_r_p = *((u8*)hdr+110);
lmem->v_r_s = *((u8*)hdr+111);
lmem->v_g_p = *((u8*)hdr+112);
lmem->v_g_s = *((u8*)hdr+113);
lmem->v_b_p = *((u8*)hdr+114);
lmem->v_b_s = *((u8*)hdr+115);
u64 size = lmem->v_stride*lmem->v_height;
for(u64 i = 0; i < (size>>12)+1; i++)
{
page_map((void*)((u64)lmem->v_mem+(i<<12)),
(void*)((u64)lmem->v_mem+(i<<12)),4096);
}
u8* font = x64_get_font();
lmem->vf_chars = *(u64*)font;
lmem->vf_wchar = (8ULL<<32ULL) / (lmem->v_width<<16);
lmem->vf_hchar = (16ULL<<32ULL) / (lmem->v_height<<16);
//lmem->vf_encodings = (u16*)(font + 8);
//lmem->vf_bitmaps = (u8*)ROUND2_UP(((u64)lmem->vf_encodings
// + (lmem->vf_chars<<1)),3);
lmem->vf_encodings = (u16*)kmalloc(lmem->vf_chars<<1);
lmem->vf_bitmaps = (u8*)kmalloc(lmem->vf_chars<<4);
kmemcpy(lmem->vf_encodings,font+8,lmem->vf_chars<<1);
kmemcpy(lmem->vf_bitmaps,font+8+(lmem->vf_chars<<1),lmem->vf_chars<<4);
//video_char(0,0,400,228,0x00FF00FF,kchr2dbcs("й"));
}

16
kernel/video.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef __VIDEO_H
#define __VIDEO_H
#include "os.h"
void video_pixel(u64 x,u64 y,u32 color);
void video_char(u64 x,u64 y,u64 sizew,u64 sizeh,u32 color,u16 sym);
void video_rect_zero(u64 x,u64 y,u64 w,u64 h);
void video_line_copy(u64 ysrc,u64 ydst,u64 height);
void video_line_zero(u64 y,u64 height);
void video_clear();
void video_swap();
void video_init();
#endif

12
kernel/x64font.asm Normal file
View file

@ -0,0 +1,12 @@
section .rdata
global x64_get_font
align 8
x64_font_bin:
incbin "font.bin"
section .text
x64_get_font:
mov rax,x64_font_bin
ret

18
kernel/x64idt.asm Normal file
View file

@ -0,0 +1,18 @@
section .text
global _idt_install
_idt_install:
mov rax,idt_base
mov qword [rax],rdi
mov rax,idt_limit
mov word [rax],si
mov rax,idt_desc
lidt [rax]
ret
section .data
align 16
idt_desc:
idt_limit dw 0
idt_base dq 0

89
kernel/x64ints.asm Normal file
View file

@ -0,0 +1,89 @@
section .text
extern idt_call_handler
%macro push_regs 0
pushfq
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
;push rsp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro pop_regs 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
;pop rsp
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
popfq
%endmacro
%macro int_handler 1
global int%1_handler
int%1_handler:
push_regs
mov rdi,%1
call idt_call_handler
pop_regs
iretq
%endmacro
int_handler 0
int_handler 1
int_handler 2
int_handler 3
int_handler 4
int_handler 5
int_handler 6
int_handler 7
int_handler 8
int_handler 9
int_handler 10
int_handler 11
int_handler 12
int_handler 13
int_handler 14
int_handler 15
int_handler 16
int_handler 17
int_handler 18
int_handler 19
int_handler 20
int_handler 21
int_handler 22
int_handler 23
int_handler 24
int_handler 25
int_handler 26
int_handler 27
int_handler 28
int_handler 29
int_handler 30
int_handler 31

80
kernel/x64io.asm Normal file
View file

@ -0,0 +1,80 @@
section .text
global inb
global outb
global inw
global outw
global inl
global outl
global _insw
global _outsw
global _insw256
global _outsw256
inb:
mov rdx,rdi
in al,dx
ret
outb:
mov rdx,rdi
mov rax,rsi
out dx,al
ret
inw:
mov rdx,rdi
in ax,dx
ret
outw:
mov rdx,rdi
mov rax,rsi
out dx,ax
ret
inl:
mov rdx,rdi
in eax,dx
ret
outl:
mov rdx,rdi
mov rax,rsi
out dx,eax
ret
_insw:
; 1 - RDI port
; 2 - RSI buf
; 3 - RDX count
mov rcx,rdx
mov rdx,rdi
mov rdi,rsi
rep insw
ret
_outsw:
; 1 - RDI port
; 2 - RSI buf
; 3 - RDX count
mov rcx,rdx
mov rdx,rdi
rep outsw
ret
_insw256:
; 1 - RDI port
; 2 - RSI buf
mov rdx,rdi
mov rdi,rsi
mov rcx,0x100
rep insw
ret
_outsw256:
; 1 - RDI port
; 2 - RSI buf
mov rdx,rdi
mov rcx,0x100
rep outsw
ret

56
kernel/x64stdlib.asm Normal file
View file

@ -0,0 +1,56 @@
section .text
global kmemcpy
global kmemcmp
global kmemzero
kmemcpy:
; RDI dst
; RSI src
; RDX size
mov rcx,rdx
shr rcx,3
rep movsq
mov rcx,rdx
and rcx,7
rep movsb
ret
kmemcmp:
mov rcx,rdx
shr rcx,3
jz .test1
.cmp8:
cmpsq
jnz .not_equal
loop .cmp8
.test1:
mov rcx,rdx
and rcx,7
.cmp1:
cmpsb
jnz .not_equal
loop .cmp1
jmp .equal
.not_equal:
xor eax,eax
inc eax
ret
.equal:
xor eax,eax
ret
kmemzero:
xor rax,rax
mov rcx,rsi
shr rcx,3
rep stosq
mov rcx,rsi
and rcx,7
rep stosb
ret

10
kernel/x64utils.asm Normal file
View file

@ -0,0 +1,10 @@
section .text
global x64_get_cr2
global x64_rax_n_stop
x64_get_cr2:
mov rax,cr2
ret
x64_rax_n_stop:
mov rax,rdi
jmp $

169
kernel_old/ahci.c Normal file
View file

@ -0,0 +1,169 @@
#include "ahci.h"
#include "pci.h"
#include "pit.h"
#include "io.h"
#include "paging.h"
#include "stdlib.h"
typedef struct {
u32 hba_phys;
hba_port_t* sata;
hba_port_t* atapi;
} ahci_t;
static ahci_t s_ahci;
static hba_mem_t* HBA;
static __align(4096) u16 buf[256];
void sata_identify()
{
hba_cmd_header_t* cmdhdr = (hba_cmd_header_t*)s_ahci.sata->clb;
hba_cmd_tbl_t* cmdtbl = (hba_cmd_tbl_t*)cmdhdr->ctba;
fis_reg_h2d_t* fis = (fis_reg_h2d_t*)&cmdtbl->cfis;
kprintf("cmdhdr %x cmdtbl %x fis %x\n",cmdhdr,cmdtbl,fis);
s_ahci.sata->is = 0xFFFFFFFF;
cmdhdr->cfl = sizeof(fis_reg_h2d_t)/sizeof(u32);
cmdhdr->w = 0;
cmdhdr->prdtl = 1;
kmemzero(cmdtbl, sizeof(hba_cmd_tbl_t) +
(cmdhdr->prdtl-1)*sizeof(hba_prdt_entry_t));
kmemzero(fis,sizeof(fis_reg_h2d_t));
/*fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = ATA_CMD_IDENTIFY;
fis->device = ATA_LBA_MODE; // Master*/
fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = 0xEC;
fis->lba0 = 0;
fis->lba1 = 0;
fis->lba2 = 0;
fis->device = ATA_LBA_MODE;
fis->lba3 = 0;
fis->lba4 = 0;
fis->lba5 = 0;
fis->countl = 1;
fis->counth = 0;
kmemzero(&cmdtbl->prdt_entry[0],sizeof(hba_prdt_entry_t));
cmdtbl->prdt_entry[0].dba = page_v2p((u32)buf);
cmdtbl->prdt_entry[0].dbc = 511; // 512 bytes
cmdtbl->prdt_entry[0].i = 0;
kprintf("s_ahci.sata->tfd %x\n",s_ahci.sata->tfd);
kprintf("s_ahci.sata->ci %x\n",s_ahci.sata->ci);
kprintf("s_ahci.sata->sact %x\n",s_ahci.sata->sact);
_debug();
//Wait before executing new commands
while(s_ahci.sata->tfd & (ATA_DEV_BUSY|ATA_DEV_DRQ))
{
kprintf("wait to issue cmd\n");
}
s_ahci.sata->ci = (1<<0);
while((s_ahci.sata->ci & (1<<0)) != 0)
{
if(s_ahci.sata->is & (1<<5))
{
kprintf("disk error\n");
return;
}
kprintf("wait\n");
}
kprintf("IDENTIFY command executed!\n");
kprintf("%x %x %u",buf,buf[83],*(u32*)&buf[60]);
}
void ahci_init()
{
pci_device_t ahci;
u32 bar;
//Use PCI
ahci = pci_find_device(0x01,0x06);
if(ahci == 0)
{
kprintf("AHCI not found!\n");
return;
}
bar = pci_read_config_word_dev(ahci,0x24);
s_ahci.hba_phys = bar & 0xFFFFFFF0;
kprintf("HBA %x\n",s_ahci.hba_phys);
//Identity map
page_map(s_ahci.hba_phys,s_ahci.hba_phys,
16384,PAGE_TABLE_READWRITE);
HBA = (hba_mem_t*)s_ahci.hba_phys;
HBA->ghc |= (1<<31); //Enable GHC.AE
if(HBA->cap & (1<<27))
{
kprintf("AHCI supports stagered spin-up\n");
}
//kprintf("pi %x\n",HBA->pi);
for(u32 i = 0; i < 32; i++)
{
hba_port_t* port = &HBA->ports[i];
if(!((HBA->pi>>i)&1)) continue;
switch(port->sig)
{
case SATA_SIG_ATA: s_ahci.sata = port; break;
case SATA_SIG_ATAPI: s_ahci.atapi = port; break;
}
//Initialize port
if(port->cmd & (SCMD_ST|SCMD_FR|SCMD_CR|SCMD_FRE)) //Isn't IDLE
{
port->cmd &= ~SCMD_ST;
while(port->cmd & SCMD_CR)
{
sleep(1000);
}
port->cmd &= ~SCMD_FRE;
while(port->cmd & SCMD_FR)
{
sleep(1000);
}
}
//Start it again
port->cmd |= SCMD_ST|SCMD_FRE;
//Clear SERR
port->serr = 0xFFFFFFFF;
port->ie = 0;
u32 data = port->is;
port->is = data;
}
HBA->is = 0;
page_map(s_ahci.sata->clb,s_ahci.sata->clb,
AHCI_CLB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.sata->fb,s_ahci.sata->fb,
AHCI_FB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.atapi->clb,s_ahci.sata->clb,
AHCI_CLB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.atapi->fb,s_ahci.sata->fb,
AHCI_FB_SIZE,PAGE_DIR_READWRITE);
//Initialize SATA and ATAPI
//sata_identify();
}

315
kernel_old/ahci.h Normal file
View file

@ -0,0 +1,315 @@
#ifndef __AHCI_H
#define __AHCI_H
#include "os.h"
#define SATA_SIG_ATA 0x00000101 // SATA drive
#define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
#define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge
#define SATA_SIG_PM 0x96690101 // Port multiplier
#define ATA_DEV_BUSY (1<<7)
#define ATA_DEV_DRQ (1<<3)
typedef struct {
u32 clb; // 0x00, command list base address, 1K-byte aligned
u32 clbu; // 0x04, command list base address upper 32 bits
u32 fb; // 0x08, FIS base address, 256-byte aligned
u32 fbu; // 0x0C, FIS base address upper 32 bits
u32 is; // 0x10, interrupt status
u32 ie; // 0x14, interrupt enable
u32 cmd; // 0x18, command and status
u32 rsv0; // 0x1C, Reserved
u32 tfd; // 0x20, task file data
u32 sig; // 0x24, signature
u32 ssts; // 0x28, SATA status (SCR0:SStatus)
u32 sctl; // 0x2C, SATA control (SCR2:SControl)
u32 serr; // 0x30, SATA error (SCR1:SError)
u32 sact; // 0x34, SATA active (SCR3:SActive)
u32 ci; // 0x38, command issue
u32 sntf; // 0x3C, SATA notification (SCR4:SNotification)
u32 fbs; // 0x40, FIS-based switch control
u32 rsv1[11]; // 0x44 ~ 0x6F, Reserved
u32 vendor[4]; // 0x70 ~ 0x7F, vendor specific
} hba_port_t;
typedef struct
{
// 0x00 - 0x2B, Generic Host Control
u32 cap; // 0x00, Host capability
u32 ghc; // 0x04, Global host control
u32 is; // 0x08, Interrupt status
u32 pi; // 0x0C, Port implemented
u32 vs; // 0x10, Version
u32 ccc_ctl; // 0x14, Command completion coalescing control
u32 ccc_pts; // 0x18, Command completion coalescing ports
u32 em_loc; // 0x1C, Enclosure management location
u32 em_ctl; // 0x20, Enclosure management control
u32 cap2; // 0x24, Host capabilities extended
u32 bohc; // 0x28, BIOS/OS handoff control and status
// 0x2C - 0x9F, Reserved
u8 rsv[116];
// 0xA0 - 0xFF, Vendor specific registers
u8 vendor[96];
// 0x100 - 0x10FF, Port control registers
hba_port_t ports[32];
} hba_mem_t;
typedef enum
{
FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device
FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host
FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host
FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
} fis_type_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_REG_H2D
u8 pmport:4; // Port multiplier
u8 rsv0:3; // Reserved
u8 c:1; // 1: Command, 0: Control
u8 command; // Command register
u8 featurel; // Feature register, 7:0
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 featureh; // Feature register, 15:8
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 icc; // Isochronous command completion
u8 control; // Control register
// DWORD 4
u8 rsv1[4]; // Reserved
} fis_reg_h2d_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_REG_D2H
u8 pmport:4; // Port multiplier
u8 rsv0:2; // Reserved
u8 i:1; // Interrupt bit
u8 rsv1:1; // Reserved
u8 status; // Status register
u8 error; // Error register
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 rsv2; // Reserved
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 rsv3[2]; // Reserved
// DWORD 4
u8 rsv4[4]; // Reserved
} fis_reg_d2h_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_DATA
u8 pmport:4; // Port multiplier
u8 rsv0:4; // Reserved
u8 rsv1[2]; // Reserved
// DWORD 1 ~ N
u32 data[1]; // Payload
} fis_data_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_PIO_SETUP
u8 pmport:4; // Port multiplier
u8 rsv0:1; // Reserved
u8 d:1; // Data transfer direction, 1 - device to host
u8 i:1; // Interrupt bit
u8 rsv1:1;
u8 status; // Status register
u8 error; // Error register
// DWORD 1
u8 lba0; // LBA low register, 7:0
u8 lba1; // LBA mid register, 15:8
u8 lba2; // LBA high register, 23:16
u8 device; // Device register
// DWORD 2
u8 lba3; // LBA register, 31:24
u8 lba4; // LBA register, 39:32
u8 lba5; // LBA register, 47:40
u8 rsv2; // Reserved
// DWORD 3
u8 countl; // Count register, 7:0
u8 counth; // Count register, 15:8
u8 rsv3; // Reserved
u8 e_status; // New value of status register
// DWORD 4
u16 tc; // Transfer count
u8 rsv4[2]; // Reserved
} fis_pio_setup_t;
typedef struct
{
// DWORD 0
u8 fis_type; // FIS_TYPE_DMA_SETUP
u8 pmport:4; // Port multiplier
u8 rsv0:1; // Reserved
u8 d:1; // Data transfer direction, 1 - device to host
u8 i:1; // Interrupt bit
u8 a:1; // Auto-activate. Specifies if DMA Activate FIS is needed
u8 rsved[2]; // Reserved
//DWORD 1&2
u64 DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
//DWORD 3
u32 rsvd; //More reserved
//DWORD 4
u32 DMAbufOffset; //Byte offset into buffer. First 2 bits must be 0
//DWORD 5
u32 TransferCount; //Number of bytes to transfer. Bit 0 must be 0
//DWORD 6
u32 resvd; //Reserved
} fis_dma_setup_t;
typedef struct
{
// 0x00
fis_dma_setup_t dsfis; // DMA Setup FIS
u8 pad0[4];
// 0x20
fis_pio_setup_t psfis; // PIO Setup FIS
u8 pad1[12];
// 0x40
fis_reg_d2h_t rfis; // Register Device to Host FIS
u8 pad2[4];
// 0x58
u64 sdbfis; // Set Device Bit FIS
// 0x60
u8 ufis[64];
// 0xA0
u8 rsv[0x100-0xA0];
} hba_fis_t;
typedef struct
{
// DW0
u8 cfl:5; // Command FIS length in DWORDS, 2 ~ 16
u8 a:1; // ATAPI
u8 w:1; // Write, 1: H2D, 0: D2H
u8 p:1; // Prefetchable
u8 r:1; // Reset
u8 b:1; // BIST
u8 c:1; // Clear busy upon R_OK
u8 rsv0:1; // Reserved
u8 pmp:4; // Port multiplier port
u16 prdtl; // Physical region descriptor table length in entries
// DW1
u32 prdbc; // Physical region descriptor byte count transferred
// DW2, 3
u32 ctba; // Command table descriptor base address
u32 ctbau; // Command table descriptor base address upper 32 bits
// DW4 - 7
u32 rsv1[4]; // Reserved
} hba_cmd_header_t;
typedef struct
{
u32 dba; // Data base address
u32 dbau; // Data base address upper 32 bits
u32 rsv0; // Reserved
// DW3
u32 dbc:22; // Byte count, 4M max
u32 rsv1:9; // Reserved
u32 i:1; // Interrupt on completion
} hba_prdt_entry_t;
typedef struct
{
// 0x00
u8 cfis[64]; // Command FIS
// 0x40
u8 acmd[16]; // ATAPI command, 12 or 16 bytes
// 0x50
u8 rsv[48]; // Reserved
// 0x80
hba_prdt_entry_t prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
} hba_cmd_tbl_t;
void sata_identify();
void ahci_init();
#define AHCI_CLB_SIZE ((sizeof(hba_cmd_header_t)*32)+4096)
#define AHCI_FB_SIZE ((sizeof(hba_fis_t)*32)+4096)
#define SCMD_ST (1<<0)
#define SCMD_CR (1<<15)
#define SCMD_FR (1<<14)
#define SCMD_FRE (1<<4)
#define ATA_LBA_MODE 0x40
#define ATA_CMD_IDENTIFY 0xEC
#endif

122
kernel_old/ata_pio.c Normal file
View file

@ -0,0 +1,122 @@
#include "ata_pio.h"
#include "io.h"
#include "pic.h"
#include "idt.h"
#include "pci.h"
#include "exceptions.h"
#include "stdlib.h"
typedef struct {
u8 buf[512];
u16 io_base;
u16 ctrl_base;
u32 slavebit;
u32 wait;
} ata_pio_t;
static ata_pio_t s_ata;
void ata_interrupt_master(int idx)
{
s_ata.wait = 0;
kprintf("interrupt happend\n");
}
void ata_wait()
{
__asm("cli");
s_ata.wait = 1;
__asm("sti");
do {
__asm("hlt");
} while(s_ata.wait);
}
void ata_init_drive(u8 drv,u8 slavebit)
{
u8 poll;
if(!slavebit)
{
s_ata.io_base = slavebit ? 0x170 : 0xC080;
s_ata.ctrl_base = 0x3E6;
}
else
{
s_ata.io_base = slavebit ? 0x168 : 0x1E8;
s_ata.ctrl_base = 0x366;
}
kprintf("s_ata.io_base %x\ns_ata.ctrl_base %x\n",
s_ata.io_base,s_ata.ctrl_base);
outb(s_ata.io_base + ATA_DRV,slavebit ? 0xB0 : 0xA0);
outb(s_ata.io_base + ATA_LBALO,0);
outb(s_ata.io_base + ATA_LBAMID,0);
outb(s_ata.io_base + ATA_LBAHI,0);
outb(s_ata.io_base + ATA_COMMAND,ATA_CMD_IDENTIFY);
if(inb(s_ata.io_base + ATA_STATUS) == 0) return;
// Poll status
while((poll=inb(s_ata.io_base + ATA_STATUS)) & ATA_STS_BSY)
{
if(poll == 0xFF)
{
kprintf("ATA Drive not found!\n");
return;
}
kprintf("polling 1 (%x)\n",inb(s_ata.io_base + ATA_STATUS));
}
if(inb(s_ata.io_base + ATA_LBAMID) | s_ata.io_base + ATA_LBAHI)
{
kprintf("Non-ATA\n");
return; // Non-ATA
}
// Wait DRQ
while((inb(s_ata.io_base + ATA_STATUS) & ATA_STS_DRQ) == 0)
{
kprintf("polling 2\n");
if(inb(s_ata.io_base + ATA_STATUS) & ATA_STS_ERR)
{
kprintf("ATA_STS_ERR\n");
return;
}
}
// Read data
_insw256(s_ata.io_base + ATA_DATA,s_ata.buf);
kprintf("LBA size %u\n",*(u32*)(&s_ata.buf[0xC0]));
}
void ata_init()
{
pci_device_t sata;
u32 irq;
u32 bar[6];
//Use PCI
sata = pci_find_device(0x01,0x06);
if(sata == 0)
{
kprintf("Serial ATA not found!\n");
return;
}
kprintf("SATA %x\n",sata);
for(u32 i = 0; i < 6; i++)
{
bar[i] = pci_read_config_word_dev(sata,0x10+(i<<2));
kprintf("bar%u %x\n",i,bar[i]);
}
irq = pci_read_config_word_dev(sata,0x3C)&0xFF;
kprintf("SATA irq %u\n",irq);
kprintf("SATA prog_if %x\n",(pci_read_config_word_dev(sata,0x08)&0x0000FF00)>>8);
pic_set_mask(14,1);
idt_setup(_int14_handler,ata_interrupt_master,
46,IDT_TYPE_INTERRUPT);
}

59
kernel_old/ata_pio.h Normal file
View file

@ -0,0 +1,59 @@
#ifndef __ATA_PIO_H
#define __ATA_PIO_H
#include "os.h"
#define ATA_MASTER_DRIVE 0xA0
#define ATA_SLAVE_DRIVE 0xB0
#define ATA_ERR_AMNF (1<<0)
#define ATA_ERR_TKZNF (1<<1)
#define ATA_ERR_ABRT (1<<2)
#define ATA_ERR_MCR (1<<3)
#define ATA_ERR_IDNF (1<<4)
#define ATA_ERR_MC (1<<5)
#define ATA_ERR_UNC (1<<6)
#define ATA_ERR_BBK (1<<7)
#define ATA_DRIVE_REG(lba,drv) (0x80|((drv&0x01)<<4)|((lba)&0x0F))
#define ATA_STS_ERR (1<<0)
#define ATA_STS_IDX (1<<1)
#define ATA_STS_CORR (1<<2)
#define ATA_STS_DRQ (1<<3)
#define ATA_STS_SRV (1<<4)
#define ATA_STS_FD (1<<5)
#define ATA_STS_RDY (1<<6)
#define ATA_STS_BSY (1<<7)
#define ATA_DCR_NIEN (1<<1)
#define ATA_DCR_SRST (1<<2)
#define ATA_DCR_HOB (1<<7)
#define ATA_PRIMARY_IO_BASE 0x1F0
#define ATA_PRIMARY_CTRL_BASE 0x3F6
#define ATA_SECONDARY_IO_BASE 0x170
#define ATA_SECONDARY_CTRL_BASE 0x376
// Port map
#define ATA_DATA 0
#define ATA_ERR 1
#define ATA_FEAT 1
#define ATA_SEC 2
#define ATA_LBALO 3
#define ATA_LBAMID 4
#define ATA_LBAHI 5
#define ATA_DRV 6
#define ATA_STATUS 7
#define ATA_COMMAND 7
// Commands
#define ATA_CMD_IDENTIFY 0xEC
void ata_init();
void ata_init_drive(u8 drv,u8 slavebit);
#endif

138
kernel_old/exceptions.c Normal file
View file

@ -0,0 +1,138 @@
#include "exceptions.h"
#include "vga_terminal.h"
#include "termlib.h"
#include "idt.h"
#include "pit.h"
#include "x86utils.h"
/* We need to implement those excpetions:
* 0 Division by zero
* 3 Breakpoint
* 6 Invalid opcode
* 7 Device not available
* 8 Double Fault
* 10 Invalid TSS
* 11 Segment not present
* 12 Stack segment fault
* 13 General protection fault
* 14 Page fault
*
*/
static void hang()
{
x86_print_regs();
while(1){__asm("hlt");}
}
extern void command_interpreter();
extern void _load_legacy_stack();
void _enter_rescue_mode()
{
_load_legacy_stack();
sleep(500);
command_interpreter();
}
void enter_rescue_mode(int skip_check)
{
if(!skip_check)
{
chg_color(VGA_COLOR_LIGHT_CYAN);
kprintf("Rollback to terminal? (y - yes, n - no): ");
u8 ans = kgetc();
if(ans == 'y' || skip_check)
{
kputc('\n');
chg_color(VGA_COLOR_MAGENTA);
_enter_rescue_mode();
}
chg_color(VGA_COLOR_MAGENTA);
}
else
{
cls();
kprintf("Terminal reloaded\n");
_enter_rescue_mode();
}
}
void exception0(int idx)
{
kprintf("[Exception] Division by zero\n");
hang();
}
void exception3(int idx)
{
kprintf("[Exception] Debug\n");
hang();
}
void exception6(int idx)
{
kprintf("[Exception] Invalid opcode\n");
hang();
}
void exception7(int idx)
{
kprintf("[Exception] Device not available\n");
hang();
}
void exception8(int idx)
{
kprintf("[Exception] Double fault\n");
hang();
}
void exception10(int idx)
{
kprintf("[Exception] Invalid TSS\n");
hang();
}
void exception11(int idx)
{
kprintf("[Exception] Segment not present\n");
hang();
}
void exception12(int idx)
{
kprintf("[Exception] Stack segment fault\n");
hang();
}
void exception13(int idx)
{
kprintf("[Exception] General protection fault\n");
hang();
}
void exception14(int idx)
{
kprintf("[Exception] Page fault\n");
x86_print_regs();
//Do we want to rollback in command interpreter
enter_rescue_mode(0);
while(1){__asm("hlt");}
}
void install_exceptions()
{
idt_setup(_int0_handler,exception0,0,IDT_TYPE_TRAP);
idt_setup(_int3_handler,exception3,3,IDT_TYPE_TRAP);
idt_setup(_int6_handler,exception6,6,IDT_TYPE_TRAP);
idt_setup(_int7_handler,exception7,7,IDT_TYPE_TRAP);
idt_setup(_int8_handler,exception8,8,IDT_TYPE_TRAP);
//idt_setup(_int9_handler,exception9,9,IDT_TYPE_TRAP);
idt_setup(_int10_handler,exception10,10,IDT_TYPE_TRAP);
idt_setup(_int11_handler,exception11,11,IDT_TYPE_TRAP);
idt_setup(_int12_handler,exception12,12,IDT_TYPE_TRAP);
idt_setup(_int13_handler,exception13,13,IDT_TYPE_TRAP);
idt_setup(_int14_handler,exception14,14,IDT_TYPE_TRAP);
}

9
kernel_old/exceptions.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef __EXCEPTIONS_H
#define __EXCEPTIONS_H
#include "os.h"
void enter_rescue_mode();
void install_exceptions();
#endif

39
kernel_old/gdt.c Normal file
View file

@ -0,0 +1,39 @@
#include "gdt.h"
static u64 gdt_table[GDT_MAX];
u64 gdt_create(u32 base,u32 limit,u32 type)
{
u64 desc;
u8 access_byte;
u8 flags;
access_byte = GDT_AB_PR|GDT_AB_S|GDT_AB_RW;
if(type == GDT_CODE)
{
access_byte |= GDT_AB_EX;
}
flags = GDT_FLAGS_GR|GDT_FLAGS_SZ;
desc = 0;
desc |= (u64)(limit & 0xFFFF) << 0;
desc |= (u64)(base & 0xFFFF) << 16;
desc |= (u64)((base>>16) & 0xFF) << 32;
desc |= (u64)(access_byte & 0xFF) << 40;
desc |= (u64)((limit>>16) & 0x0F) << 48;
desc |= (u64)(flags & 0x0F) << 52;
desc |= (u64)((base>>24) & 0xFF) << 56;
return desc;
}
void gdt_install()
{
// Protected Mode Flat Model
gdt_table[GDT_NULL] = gdt_create(0,0,0);
gdt_table[GDT_CODE] = gdt_create(0,0x000FFFFF,GDT_CODE);
gdt_table[GDT_DATA] = gdt_create(0,0x000FFFFF,GDT_DATA);
_gdt_install(gdt_table,sizeof(gdt_table)-1);
}

29
kernel_old/gdt.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef __GDT_H
#define __GDT_H
#include "os.h"
#define GDT_AB_PR (1<<7)
#define GDT_AB_PRIVL (1<<5)
#define GDT_AB_S (1<<4)
#define GDT_AB_EX (1<<3)
#define GDT_AB_DC (1<<2)
#define GDT_AB_RW (1<<1)
#define GDB_AB_AC (1<<0)
#define GDT_FLAGS_GR (1<<3)
#define GDT_FLAGS_SZ (1<<2)
enum {
GDT_NULL = 0,
GDT_CODE,
GDT_DATA,
GDT_MAX,
};
u64 gdt_create(u32 base,u32 limit,u32 type);
void gdt_install();
extern void _gdt_install(void* gdt,int size);
#endif

72
kernel_old/idt.c Normal file
View file

@ -0,0 +1,72 @@
#include "idt.h"
#include "termlib.h"
static u64 idt_table[256]; //256 entries lol
static idt_handler idt_handlers[256];
u64 idt_create(void* handler,int type)
{
u64 desc;
u32 addr;
addr = (u32)handler;
desc = 0;
desc |= (u64)(addr&0xFFFF) << 0;
desc |= (u64)(OS_CODE_SELECTOR&0xFFFF) << 16;
desc |= (u64)(type&0x0F) << 40;
desc |= (u64)(1) << 47;
desc |= (u64)(addr>>16) << 48;
return desc;
}
void idt_setup(void* int_handler,idt_handler handler,int idx,int type)
{
idt_table[idx] = idt_create(int_handler,type);
idt_handlers[idx] = handler;
}
static void* idt_get_addr(int i)
{
return (void*)(((u32)((idt_table[i]>>48)<<16)|(u32)(idt_table[i]&0xFFFF)));
}
int idt_irq_by_addr(void* addr)
{
int i;
for(i = 0; i < 256; i++)
if(idt_get_addr(i) == addr) return i;
return -1;
}
void idt_handler_entry(void* addr)
{
int idx;
idx = idt_irq_by_addr(addr);
if(idx == -1)
{
kprintf("No IDT entry some INT!\n");
return;
}
//Call handler
idt_handlers[idx](idx);
}
void idt_install()
{
int i;
for(i = 0; i < 256; i++) idt_table[i] = 0;
_idt_install(idt_table,sizeof(idt_table)-1);
}
void idt_enable_interrupts()
{
__asm("sti");
}

60
kernel_old/idt.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef __IDT_H
#define __IDT_H
#include "os.h"
typedef enum {
IDT_TYPE_TASK = 5,
IDT_TYPE_16_INTERRUPT = 6,
IDT_TYPE_16_TRAP = 7,
IDT_TYPE_INTERRUPT = 14,
IDT_TYPE_TRAP = 15,
} idt_type;
typedef void (*idt_handler)(int irq);
u64 idt_create(void* handler,int type);
void idt_setup(void* int_handler,idt_handler handler,int idx,int type);
int idt_irq_by_addr(void* addr);
void idt_handler_entry(void* addr);
void idt_install();
extern void _idt_install(void* idt,int limit);
void idt_enable_interrupts();
extern void _int0_handler();
extern void _int1_handler();
extern void _int2_handler();
extern void _int3_handler();
extern void _int4_handler();
extern void _int5_handler();
extern void _int6_handler();
extern void _int7_handler();
extern void _int8_handler();
extern void _int9_handler();
extern void _int10_handler();
extern void _int11_handler();
extern void _int12_handler();
extern void _int13_handler();
extern void _int14_handler();
extern void _int15_handler();
extern void _int16_handler();
extern void _int17_handler();
extern void _int18_handler();
extern void _int19_handler();
extern void _int20_handler();
extern void _int21_handler();
extern void _int22_handler();
extern void _int23_handler();
extern void _int24_handler();
extern void _int25_handler();
extern void _int26_handler();
extern void _int27_handler();
extern void _int28_handler();
extern void _int29_handler();
extern void _int30_handler();
extern void _int31_handler();
#endif

21
kernel_old/io.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef __IO_H
#define __IO_H
#include "os.h"
extern u8 inb(u16 port);
extern void outb(u16 port,u8 data);
extern u16 inw(u16 port);
extern void outw(u16 port,u16 data);
extern u32 inl(u16 port);
extern void outl(u16 port,u32 data);
extern void _insw(u16 port,u8* buffer,u32 count);
extern void _outsw(u16 port,u8* buffer,u32 count);
extern void _insw256(u16 port,u8* buffer);
extern void _outsw256(u16 port,u8* buffer);
#endif

151
kernel_old/keyboard.c Normal file
View file

@ -0,0 +1,151 @@
#include "keyboard.h"
#include "exceptions.h"
#include "idt.h"
#include "pic.h"
#include "pit.h"
#include "termlib.h"
#include "vga_terminal.h"
static u8 s_i8keycode = 0;
static u8 s_i8keycode2 = 0;
static u32 s_ctrlkeys = 0;
static u8 s_keymap[128] = {
0, 0x1B,
'1','2',
'3','4','5','6',
'7','8','9','0',
'-','=',
0x08,
0x09,
'Q','W','E','R',
'T','Y','U','I',
'O','P','[',']',
0x0A,0,
'A','S','D','F',
'G','H','J','K',
'L',';','\'','`',
0,
'\\',
'Z','X','C','V',
'B','N','M',',',
'.','/',
0,
'*',
0,
' ',
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,
};
static char* shift_numbers = "!@#$%^&*()_+";
static void check_keys()
{
if((s_ctrlkeys & (KEY_LSHIFT|KEY_LALT) == (KEY_LSHIFT|KEY_LALT))
&& s_i8keycode2 == 0x2C)
{
//If we're entering rescue mode, we must send EOI!
pic_send_eoi(1);
enter_rescue_mode(1);
}
}
static void _keyboard_ctrlkeys_update(u8 keychar,u8 event)
{
u8 ctrlkey;
ctrlkey = 0;
if(keychar == KEY_RSHIFT) ctrlkey = CTRLKEYS_RSHIFT;
else if(keychar == KEY_LSHIFT) ctrlkey = CTRLKEYS_LSHIFT;
else if(keychar == KEY_LALT) ctrlkey = CTRLKEYS_LALT;
if(event) s_ctrlkeys &= ~ctrlkey; //Released
else s_ctrlkeys |= ctrlkey; //Pressed
}
void keyboard_interrupt(int idx)
{
u8 status;
u8 keycode,keychar;
status = inb(0x64);
if(status & 1)
{
keycode = inb(0x60);
keychar = keycode & ~0x80;
s_i8keycode2 = keychar;
if(keychar == KEY_RSHIFT
|| keychar == KEY_LSHIFT
|| keychar == KEY_LALT)
{
_keyboard_ctrlkeys_update(keychar,keycode>>7);
s_i8keycode = 0;
}
else if(!(keycode & 0x80))
{
s_i8keycode = keychar;
//kprintf("%c",keyboard_ascii());
}
}
check_keys();
pic_send_eoi(1);
}
u8 keyboard_scan_code()
{
return s_i8keycode;
}
u8 keyboard_ascii()
{
u8 ascii;
if(s_i8keycode >= sizeof(s_keymap)) return 0;
ascii = s_keymap[s_i8keycode];
if(s_ctrlkeys & (CTRLKEYS_LSHIFT|CTRLKEYS_RSHIFT))
{
if((s_i8keycode >= 0x02) && (s_i8keycode <= 0x0D))
{
if(s_i8keycode >= 2)
ascii = shift_numbers[s_i8keycode-2];
}
if(ascii == '[') ascii = '{';
else if(ascii == ']') ascii = '}';
else if(ascii == '\\') ascii = '|';
else if(ascii == ';') ascii = ':';
else if(ascii == '\'') ascii = '"';
else if(ascii == ',') ascii = '<';
else if(ascii == '.') ascii = '>';
else if(ascii == '/') ascii = '?';
else if(ascii == '`') ascii = '~';
}
else if(ascii >= 0x41 && ascii <= 0x5A) ascii += 0x20;
return ascii;
}
void keyboard_reset_irq1_vars()
{
s_i8keycode = 0;
}
void keyboard_enable()
{
pic_set_mask(1,1);
}
void keyboard_disable()
{
pic_set_mask(1,0);
}
void keyboard_install()
{
pic_set_mask(1,1);
idt_setup(_int9_handler,keyboard_interrupt,33,IDT_TYPE_INTERRUPT);
}

50
kernel_old/keyboard.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef __KEYBOARD_H
#define __KEYBAORD_H
#include "os.h"
#define CTRLKEYS_LSHIFT (1<<0)
#define CTRLKEYS_RSHIFT (1<<1)
#define CTRLKEYS_LALT (1<<2)
typedef enum {
//Controls keys
KEY_LSHIFT = 0x2A,
KEY_RSHIFT = 0x36,
KEY_LALT = 0x38,
//Numpad
KEY_NP_7 = 0x47,
KEY_NP_8,
KEY_NP_9,
KEY_NP_MINUS,
KEY_NP_4,
KEY_NP_5,
KEY_NP_6,
KEY_NP_PLUS,
KEY_NP_DOT,
//Functions
KEY_F1 = 0x3B,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11 = 0x57,
KEY_F12
} kb_keys_t;
void keyboard_install();
u8 keyboard_scan_code();
u8 keyboard_ascii();
void keyboard_enable();
void keyboard_disable();
void keyboard_reset_irq1_vars();
#endif

142
kernel_old/kmain.c Normal file
View file

@ -0,0 +1,142 @@
#include "os.h"
#include "memory.h"
#include "vga_terminal.h"
#include "gdt.h"
#include "idt.h"
#include "pic.h"
#include "pit.h"
#include "pci.h"
#include "ahci.h"
#include "exceptions.h"
#include "paging.h"
#include "keyboard.h"
#include "x86utils.h"
#include "stdlib.h"
#include "string.h"
static char* xnums = "0123456789ABCDEF";
void command_interpreter()
{
char command[64];
while(1)
{
kputc('>');
kgets(command,sizeof(command));
if(!kstrncmp(command,"ram_map"))
{
ram_map_t* ram = ram_get_map();
kprintf("RAM size = %u\nRAM pools %u\n",
ram->ram_total_size,ram->ram_pool_count);
for(u32 i = 0; i < ram->ram_pool_count; i++)
{
kprintf("\t%p\t%p\n",ram->ram_pools[i].start,
ram->ram_pools[i].end);
}
}
else if(!kstrncmp(command,"page_map"))
{
u32 virt,phys,size;
ksscanf(command,"page_map %p %p %u",&virt,&phys,&size);
page_map(virt,phys,size,PAGE_TABLE_READWRITE);
}
else if(!kstrncmp(command,"page_unmap"))
{
u32 virt,size;
ksscanf(command,"page_unmap %p %u",&virt,&size);
page_unmap(virt,size);
}
else if(!kstrncmp(command,"page_v2p"))
{
u32 virt;
ksscanf(command,"page_v2p %p",&virt);
kprintf("VIRT %p -> PHYS %p\n",virt,page_v2p(virt));
}
else if(!kstrncmp(command,"dump"))
{
u32 lines,virt;
ksscanf(command,"dump %u %p",&lines,&virt);
for(u32 i = 0; i < lines; i++)
{
kprintf("%p: ",virt);
for(u32 j = 0; j < 16; j++)
{
u8 byte;
byte = *(u8*)(virt+j);
kprintf("%c%c ",xnums[byte>>8],xnums[byte&0x0F]);
}
kprintf("\n");
virt += 16;
}
}
else if(!kstrncmp(command,"pci_dump"))
{
pci_dump();
}
else if(!kstrncmp(command,"hang"))
{
while(1){__asm("nop");}
}
else if(!kstrncmp(command,"sata_identify"))
{
sata_identify();
}
}
}
void kernel_main(multiboot_hdr_t* mbt,int magic)
{
//Unmap first 16 MB
//Before we unmap first 16 MB, we need to know all about MBT
mbt_mmap_init(mbt);
page_unmap(0,1024*1024*16);
//Map video buffer
vga_terminal_init();
//Fix MBT address
cls();
chg_color(VGA_COLOR_MAGENTA);
vga_terminal_init();
kprintf("GRUB loaded Lenochka!\n");
kprintf("MBT %p magic %x\n",mbt,magic);
kprintf("%u KB RAM\n",ram_get_size()>>10);
chg_color(VGA_COLOR_WHITE);
kprintf("\nOS_VIDEO_BUFFER %x\n\n",OS_VIDEO_BUFFER);
chg_color(VGA_COLOR_MAGENTA);
kprintf("Installing GDT\n");
gdt_install();
for(int i = 0; i < 10; i++) kprintf("%d ",i);
kprintf("\nGDT Installed\n");
kprintf("Init PIC\n");
pic_init(0x20,0x28);
kprintf("Installing IDT\n");
idt_install();
for(int i = 0; i < 10; i++) kprintf("%d ",i);
kprintf("\nIDT Installed\n");
install_exceptions();
kprintf("Exceptions installed\n");
pit_init();
keyboard_install();
idt_enable_interrupts(); //IRQs and exceptions
pci_detect_hardware();
pci_dump();
ahci_init();
kprintf("\n\n");
command_interpreter();
while(1){__asm("hlt");}
}

36
kernel_old/memory.c Normal file
View file

@ -0,0 +1,36 @@
#include "memory.h"
static ram_map_t s_RAMmap;
void mbt_mmap_init(multiboot_hdr_t* mbt)
{
s_RAMmap.ram_total_size = 0;
s_RAMmap.ram_pool_count = 0;
multiboot_mmap_t* mmap = (multiboot_mmap_t*)mbt->mmap_addr;
while((u32)mmap < (u32)mbt->mmap_addr + mbt->mmap_length)
{
if(mmap->type == 1)
{
ram_pool_t* pool;
if(s_RAMmap.ram_pool_count == MAX_RAM_POOLS)
break;
pool = &s_RAMmap.ram_pools[s_RAMmap.ram_pool_count++];
pool->start = (u32)mmap->base_addr;
pool->end = pool->start + (u32)mmap->length;
s_RAMmap.ram_total_size += mmap->length;
}
mmap = (multiboot_mmap_t*)((u32)mmap + mmap->size + 4);
}
}
ram_map_t* ram_get_map()
{
return &s_RAMmap;
}
u32 ram_get_size()
{
return s_RAMmap.ram_total_size;
}

25
kernel_old/memory.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef __MEMORY_H
#define __MEMORY_H
#include "os.h"
#include "multiboot.h"
#define MAX_RAM_POOLS 32
typedef struct {
u32 __phys start;
u32 __phys end;
} ram_pool_t;
typedef struct {
u32 ram_total_size;
u32 ram_pool_count;
ram_pool_t ram_pools[MAX_RAM_POOLS];
} ram_map_t;
//It must be called before first 1 MB got unpaged
void mbt_mmap_init(multiboot_hdr_t* mbt);
ram_map_t* ram_get_map();
u32 ram_get_size();
#endif

101
kernel_old/multiboot.asm Normal file
View file

@ -0,0 +1,101 @@
MBALIGN equ 1 << 0
MEMINFO equ 1 << 1
FLAGS equ MBALIGN|MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC+FLAGS)
section .multiboot
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
section .bss
global page_directories
global page_tables
global legacy_esp
align 4096
page_directories resb 4096
page_tables resb 4194304
align 16
stack_bottom:
resb 32768 ; 32 KiB
stack_top:
legacy_esp resd 1
section .text
global _start
_start:
mov esp,(stack_bottom - 0xC0000000 + 0x7FFC)
push eax
push ebx
cld
; Our kernel will be mapped for 16M, or 4 dirs
mov edi,(page_directories - 0xC0000000 + 0xC00)
xor ecx,ecx
_dir_set:
xor edx,edx
mov eax,4096
mul ecx
add eax,(page_tables - 0xC0000000 + 0xC0000)
or eax,3 ; Present + RW
stosd
inc ecx
cmp ecx,4
jne _dir_set
; Setup tables - map from 0 to 16M
mov edi,(page_tables - 0xC0000000 + 0xC0000)
xor ebx,ebx ; Physical address
mov ecx,4096
_table_set:
mov eax,ebx
add eax,3
stosd
add ebx,4096
loop _table_set
; Identity map also first 4 MB
mov esi,(page_directories - 0xC0000000 + 0xC00)
mov edi,(page_directories - 0xC0000000)
mov cx,4
_copy_map:
lodsd
stosd
loop _copy_map
mov eax,(page_directories - 0xC0000000 + 0xC00)
mov ebx,(page_directories - 0xC0000000)
mov ecx,(page_tables - 0xC0000000 + 0xC0000)
; Enable paging
mov eax,(page_directories - 0xC0000000)
mov cr3,eax
mov eax,cr0
or eax,0x80010000
mov cr0,eax
mov eax,_paging_enter
jmp eax
_paging_enter:
extern kernel_main
add esp,0xC0000000
mov dword [legacy_esp],esp
;push eax
;push ebx
call kernel_main
add esp,8
cli
hlt
.end:

58
kernel_old/multiboot.h Normal file
View file

@ -0,0 +1,58 @@
#ifndef __MULTIBOOT_H
#define __MULTIBOOT_H
#include "os.h"
typedef struct {
u32 flags;
u32 mem_lower;
u32 mem_upper;
u32 boot_device;
u32 cmd_line;
u32 mods_count;
u32 mods_addr;
u32 syms[4];
u32 mmap_length;
u32 mmap_addr;
u32 drives_length;
u32 drives_addr;
u32 config_table;
u32 boot_loader_name;
u32 apm_table;
u32 vbe_control_info;
u32 vbe_mode_info;
u32 vbe_mode;
u32 vbe_interface_seg;
u32 vbe_interface_off;
u32 vbe_interface_len;
u32 framebuffer_addr;
u32 framebuffer_pitch;
u32 framebuffer_width;
u32 framebuffer_height;
u8 framebuffer_bpp;
u8 color_info[5];
} __attribute__((packed)) multiboot_hdr_t;
#define MBT_MMAP_TYPE_RAM 1
typedef struct {
u32 size;
u64 base_addr;
u64 length;
u32 type;
} __packed multiboot_mmap_t;
#endif

36
kernel_old/os.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef __OS_H
#define __OS_H
#define OS_NULL_SELECTOR 0x00
#define OS_CODE_SELECTOR 0x08
#define OS_DATA_SELECTOR 0x10
#define OS_PHYS_MAPPING 0x00100000
#define OS_VIRT_MAPPING 0xC0000000
#define OS_PM86_MEM_SIZE_4K (1024*1024)
#define OS_PHYS_ADDR(virt) (virt-OS_VIRT_MAPPING)
#define OS_VIDEO_BUFFER 0xC10B8000
#define OS_PROG_MAPPING 0x01000000
#define __packed __attribute__((packed))
#define __align(N) __attribute__((aligned(N)))
#define __phys
#define __virt
#define NULL (void*)0
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef char i8;
typedef short i16;
typedef long i32;
typedef long long i64;
typedef unsigned long size_t;
#endif

93
kernel_old/paging.c Normal file
View file

@ -0,0 +1,93 @@
#include "paging.h"
#include "termlib.h"
// Allocate some space for page directories & tables
//static u32 page_directories[PAGE_DIR_NUM] __align(4096);
//static u32 page_tables[PAGE_TABLE_NUM] __align(4096);
void page_map(u32 __virt virt,u32 __phys phys,u32 size,u32 flags)
{
u32 num_dirs,num_pages;
u32 dir_index,table_index;
u32 i;
num_pages = (size>>12) + ((size&0xFFF) ? 1 : 0);
num_dirs = (num_pages>>10) + ((num_pages&0x3FFF) ? 1 : 0);
table_index = virt>>12;
dir_index = table_index>>10;
//Make directories present
for(i = 0; i < num_dirs; i++)
{
if(!(page_directories[dir_index+i] & PAGE_DIR_PRESENT))
{
page_directories[dir_index+i] = PAGE_DIR_ENTRY(
OS_PHYS_ADDR( (u32)(&page_tables[(dir_index+i)<<10]) ),
PAGE_DIR_PRESENT
| PAGE_DIR_READWRITE
);
}
}
//Make tables present
for(i = 0; i < num_pages; i++)
{
page_tables[table_index+i] = PAGE_TABLE_ENTRY(
(u32)(phys+i*4096),
flags|PAGE_TABLE_PRESENT
);
}
}
extern void x86_reload_cr3();
void page_unmap(u32 __virt virt,u32 size)
{
u32 num_dirs,num_pages;
u32 dir_index,table_index;
u32 i,reload_cr3;
num_pages = (size>>12) + ((size&0xFFF) ? 1 : 0);
num_dirs = (num_pages>>10) + ((num_pages&0x3FFF) ? 1 : 0);
table_index = virt>>12;
dir_index = table_index>>10;
for(i = 0; i < num_pages; i++)
page_tables[table_index+i] = 0;
//Check directories
reload_cr3 = 0;
for(i = 0; i < num_dirs; i++)
{
u32 j;
for(j = 0; j < 1024; j++)
{
if(page_tables[((dir_index+i)<<10) + j] & PAGE_TABLE_PRESENT)
break;
}
//Directory empty
if(j == 1024)
{
page_directories[dir_index+i] = 0;
reload_cr3 = 1;
}
}
if(reload_cr3) x86_reload_cr3();
}
__phys u32 page_v2p(u32 __virt virt)
{
u32 index,dir_entry;
u32* table;
index = virt>>12;
dir_entry = page_directories[index>>10];
if(!(dir_entry & PAGE_DIR_PRESENT)) return 0;
table = (u32*)((dir_entry&0xFFFFF000) + OS_VIRT_MAPPING);
return table[index&0x3FF] & 0xFFFFF000;
}

37
kernel_old/paging.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef __PAGING_H
#define __PAGING_H
#include "os.h"
#define PAGE_DIR_PRESENT (1<<0)
#define PAGE_DIR_READWRITE (1<<1)
#define PAGE_DIR_USERMODE (1<<2)
#define PAGE_DIR_WRITECACHE (1<<3)
#define PAGE_DIR_NOCACHE (1<<4)
#define PAGE_DIR_ACCESSED (1<<5)
#define PAGE_DIR_PAGESIZE (1<<7)
#define PAGE_DIR_ENTRY(phys,flags) ((phys&0xFFFFF000)|flags)
#define PAGE_TABLE_PRESENT (1<<0)
#define PAGE_TABLE_READWRITE (1<<1)
#define PAGE_TABLE_USERMODE (1<<2)
#define PAGE_TABLE_WRITECACHE (1<<3)
#define PAGE_TABLE_CACHE (1<<4)
#define PAGE_TABLE_GLOBAL (1<<8)
#define PAGE_TABLE_ENTRY(phys,flags) ((phys&0xFFFFF000)|flags)
#define PAGE_DIR_NUM 1024
#define PAGE_TABLE_NUM OS_PM86_MEM_SIZE_4K
//Map physical address to virtual
void page_map(u32 __virt virt,u32 __phys phys,u32 size,u32 flags);
void page_unmap(u32 __virt virt,u32 size);
__phys u32 page_v2p(u32 __virt virt);
extern u32 page_directories[PAGE_DIR_NUM];
extern u32 page_tables[PAGE_TABLE_NUM];
#endif

251
kernel_old/pci.c Normal file
View file

@ -0,0 +1,251 @@
#include "pci.h"
#include "vga_terminal.h"
#include "stdlib.h"
#include "io.h"
typedef struct {
u32 device_count;
pci_device_t devices[MAX_PCI_DEVICES];
} pci_hardware_t;
static pci_hardware_t s_pci;
struct pci_class_s {
int len;
const char* name;
};
static struct pci_class_s s_classes[] = {
{2,"Unclassified"},
{9,"Mass Storage Controller"},
{9,"Network Controller"},
{3,"Display Controller"},
{4,"Multimedia Controller"},
{2,"Memory controller"},
{11,"Bridge Device"},
{6,"Simple Communication Controller"},
{7,"Base System Peripheral"},
{5,"Input Device Controller"},
{0,"Docking Station"},
{0,"Processor"},
{10,"Serial Bus Controller"},
{0,"Wireless Controller"},
{0,"Intelligent Controller"},
{0,"Satellite Communication Controller"},
{0,"Encryption Controller"},
{0,"Signal Processing Controller"},
{0,"Processing Accelerator"},
{0,"Non-Essential Instrumentation"}
};
static char* s_subclasses[] = {
"Non-VGA-Compatible devices",
"VGA-Compatible Device",
"SCSI Bus Controller",
"IDE Controller",
"Floppy Disk Controller",
"IPI Bus Controller",
"RAID Controller",
"ATA Controller",
"Serial ATA",
"Serial Attached SCSI",
"Non-Volatile Memory Controller",
"Ethernet Controller",
"Token Ring Controller",
"FDDI Controller",
"ATM Controller",
"ISDN Controller",
"WorldFip Controller",
"PICMG 2.14 Multi Computing",
"Infiniband Controller",
"Fabric Controller",
"VGA Compatible Controller",
"XGA Controller",
"3D Controller (Not VGA-Compatible)",
"Multimedia Video Controller",
"Multimedia Audio Controller",
"Computer Telephony Device",
"Audio Device",
"RAM Controller",
"Flash Controller",
"Host Bridge",
"ISA Bridge",
"EISA Bridge",
"MCA Bridge",
"PCI-to-PCI Bridge",
"PCMCIA Bridge",
"NuBus Bridge",
"CardBus Bridge",
"RACEway Bridge",
"PCI-to-PCI Bridge",
"InfiniBand-to-PCI Host Bridge",
"Serial Controller",
"Parallel Controller",
"Multiport Serial Controller",
"Modem",
"IEEE 488.1/2 (GPIB) Controller",
"Smart Card",
"PIC",
"DMA Controller",
"Timer",
"RTC Controller",
"PCI Hot-Plug Controller",
"SD Host controller",
"IOMMU",
"Keyboard Controller",
"Digitizer Pen",
"Mouse Controller",
"Scanner Controller",
"Gameport Controller",
"FireWire (IEEE 1394) Controller",
"ACCESS Bus",
"SSA",
"USB Controller",
"Fibre Channel",
"SMBus",
"InfiniBand",
"IPMI Interface",
"SERCOS Interface (IEC 61491)",
"CANbus"
};
u32 pci_read_config_word(u32 bus,u32 device,u32 function,u32 offset)
{
u32 address;
bus &= 0xFF; // 8 bit
device &= 0x1F; // 5 bit
function &= 0x07; // 3 bit
offset &= 0xFC; // 6 bit
address = 0x80000000UL|(bus<<16)|(device<<11)|(function<<8)|(offset);
outl(PCI_CONFIG_ADDRESS,address);
return inl(PCI_CONFIG_DATA);
}
u32 pci_read_config_word_dev(pci_device_t dev,u32 offset)
{
u32 address;
offset &= 0xFC; // 6 bit
address = 0x80000000|((dev&0xFFFF0000)>>8)|(offset);
outl(PCI_CONFIG_ADDRESS,address);
return inl(PCI_CONFIG_DATA);
}
const char* pci_get_class(u32 class)
{
if(class >= sizeof(s_classes)/sizeof(struct pci_class_s))
return "Unknown";
return s_classes[class].name;
}
const char* pci_get_subclass(u32 class,u32 subclass)
{
u32 i,index;
if(class >= sizeof(s_classes)/sizeof(struct pci_class_s))
return "Unknown";
if(subclass >= sizeof(s_subclasses)/sizeof(const char*))
return "Unknown";
else if(subclass == 0x80) return "Other";
index = 0;
for(i = 0; i < class; i++)
index += s_classes[i].len;
if(i == class && subclass >= s_classes[i].len) return "Unknown";
return s_subclasses[index+subclass];
}
void pci_dump()
{
for(u32 i = 0; i < s_pci.device_count; i++)
{
u32 class,subclass;
class = (s_pci.devices[i]>>8)&0xFF;
subclass = s_pci.devices[i] & 0xFF;
kprintf("%x\t%s\t%s\n",
s_pci.devices[i],
pci_get_class(class),
pci_get_subclass(class,subclass));
}
}
static void pci_add_device(u32 bus,u32 device,u32 func,
u32 class,u32 subclass)
{
pci_device_t dev;
dev = (bus<<24)|(device<<19)|(func<<16)|(class<<8)|(subclass);
if(s_pci.device_count < MAX_PCI_DEVICES)
s_pci.devices[s_pci.device_count++] = dev;
}
static void pci_scan_bus(u32 bus);
static void pci_scan_device(u32 bus,u32 dev,u32 func)
{
u32 class = pci_read_config_word(bus,dev,func,0x08) >> 16;
u32 hdr = (pci_read_config_word(bus,dev,func,0x0C) >> 16) & 0xFF;
if(class == 0x0604) //PCI-to-PCI bridge
{
pci_scan_bus((pci_read_config_word(
bus,dev,func,0x18) >> 8) & 0xFF);
}
if(hdr & 0x80 && func == 0) //Multifunction
{
for(u32 i = 1; i < 8; i++)
{
u32 vendor = pci_read_config_word(bus,dev,i,0x00) & 0xFFFF;
if(vendor != 0xFFFF)
pci_scan_device(bus,dev,i);
}
}
pci_add_device(bus,dev,func,class>>8,class&0xFF);
}
static void pci_scan_bus(u32 bus)
{
for(u32 i = 0; i < 32; i++)
{
u32 vendor = pci_read_config_word(bus,i,0,0x00) & 0xFFFF;
if(vendor != 0xFFFF)
pci_scan_device(bus,i,0);
}
}
void pci_detect_hardware()
{
s_pci.device_count = 0;
for(u32 i = 0; i < 256; i++)
pci_scan_bus(i);
}
pci_device_t pci_find_device(u32 class,u32 subclass)
{
u32 data = class<<8|subclass;
for(u32 i = 0; i < s_pci.device_count; i++)
{
if((s_pci.devices[i] & 0xFFFF) == data)
return s_pci.devices[i];
}
return 0;
}

24
kernel_old/pci.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef __PCI_H
#define __PCI_H
#include "os.h"
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
#define MAX_PCI_DEVICES 256
// bbbbbbbbdddddfffccccccccssssssss
typedef u32 pci_device_t;
u32 pci_read_config_word(u32 bus,u32 device,u32 function,u32 hword);
u32 pci_read_config_word_dev(pci_device_t dev,u32 hword);
void pci_dump();
void pci_detect_hardware();
//Returns device index
//-1 for NOTFOUND
pci_device_t pci_find_device(u32 class,u32 subclass);
#endif

45
kernel_old/pic.c Normal file
View file

@ -0,0 +1,45 @@
#include "pic.h"
void pic_init(int master,int slave)
{
outb(PIC1,ICW1);
outb(PIC2,ICW1);
outb(PIC1+1,master&0xFF);
outb(PIC2+1,slave&0xFF);
outb(PIC1+1,4);
outb(PIC2+1,2);
outb(PIC1+1,ICW4);
outb(PIC2+1,ICW4);
//Disable all IRQs
outb(PIC1+1,0xFF);
outb(PIC2+1,0xFF);
}
void pic_set_mask(int irq,int enabled)
{
u16 pic;
u8 mask;
if(irq >= 8)
{
pic = PIC2+1;
irq -= 8;
}
else pic = PIC1+1;
mask = inb(pic);
if(enabled) mask &= ~(1<<irq);
else mask |= (1<<irq);
outb(pic,mask);
}
void pic_send_eoi(int irq)
{
if(irq >= 8) outb(PIC2,0x20);
outb(PIC1,0x20);
}

16
kernel_old/pic.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef __PIC_H
#define __PIC_H
#include "io.h"
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
void pic_init(int master,int slave);
void pic_set_mask(int irq,int enabled);
void pic_send_eoi(int irq);
#endif

36
kernel_old/pit.c Normal file
View file

@ -0,0 +1,36 @@
#include "pit.h"
#include "pic.h"
#include "idt.h"
static u32 s_counter = 0;
void timer_interrupt(int idx)
{
if(s_counter) s_counter--;
pic_send_eoi(0);
}
void sleep(u32 msecs)
{
__asm("cli");
if(msecs < 55) msecs = 55;
s_counter = msecs/55;
__asm("sti");
//pic_set_mask(0,1);
do {
__asm("hlt"); //Wait for IRQ
} while(s_counter);
//pic_set_mask(0,0);
}
void pit_init()
{
//Setup IRQ
pic_set_mask(0,1);
idt_setup(_int15_handler,timer_interrupt,32,IDT_TYPE_INTERRUPT);
//Init PIT
outb(0x43,0x36);
outb(0x40,0x00);
outb(0x40,0x00);
}

10
kernel_old/pit.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __PIT_H
#define __PIT_H
#include "io.h"
void sleep(u32 msecs);
void pit_init();
#endif

398
kernel_old/stdlib.c Normal file
View file

@ -0,0 +1,398 @@
#include "stdlib.h"
#include "vga_terminal.h"
#include "keyboard.h"
#include "string.h"
void iprint(int number)
{
//4294967295
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
s--;
while(s >= num) printchar(*s--);
}
void uprint(u32 number)
{
//4294967295
char num[32];
char* s = num;
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
s--;
while(s >= num) printchar(*s--);
}
static char* xnums = "0123456789ABCDEF";
void xprint(u32 number)
{
//FFFFFFFF
char num[16];
char* s = num;
while(s-num < 7)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
s--;
while(s >= num) printchar(*s--);
}
void iprints(char* outs,int number)
{
//4294967295
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void uprints(char* outs,u32 number)
{
//4294967295
char num[32];
char* s = num;
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void xprints(char* outs,u32 number)
{
//FFFFFFFF
char num[16];
char* s = num;
while(s-num < 7)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void kprint(char* str)
{
while(*str) printchar(*str++);
}
void ksprintf(char* dst,u32 maxLen,const char* fmt,...)
{
u32* argp;
char* cur,*end,c;
char numbuf[64];
argp = ((u32*)&fmt)+1;
cur = dst;
end = dst+maxLen;
while((c = *fmt++) && cur != end)
{
if(c == '%')
{
char* p = numbuf;
c = *fmt++;
if(c == 'd')
{
iprints(numbuf,*(int*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'u')
{
uprints(numbuf,*(int*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'p' || c == 'x')
{
xprints(numbuf,*(u32*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 's')
{
const char* str = *(const char**)argp++;
while((*cur++ = *str++))
if(cur == end) break;
cur--;
}
else if(c == '%')
{
if(cur != end) *cur++ = '%';
}
}
else
{
if(cur == end) break;
*cur++ = c;
}
}
if(cur == end)
*(end-1) = '\0';
}
void kprintf(const char* fmt,...)
{
u32* argp;
char c;
argp = ((u32*)&fmt)+1;
while((c = *fmt++))
{
if(c == '%')
{
c = *fmt++;
switch(c)
{
case 'd': iprint(*(int*)argp++); break;
case 'u': uprint(*(u32*)argp++); break;
case 'p':
case 'x': xprint(*(u32*)argp++); break;
case 'c': printchar((char)(*(u32*)argp++)); break;
case 's': kprint((char*)(*(u32*)argp++)); break;
case '%': printchar('%'); break;
}
}
else printchar(c);
}
}
u8 kgetch()
{
u8 key;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
key = keyboard_scan_code();
keyboard_reset_irq1_vars();
return key;
}
u8 kgetc()
{
u8 ascii;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
ascii = keyboard_ascii();
keyboard_reset_irq1_vars();
return ascii;
}
void kgets(char* buf,size_t max)
{
u8 ch;
char* ptr,*end;
ptr = buf;
end = buf + max;
*ptr = '\0';
while((ch = kgetc()) != '\n')
{
if(ch == '\b')
{
if(ptr != buf) *ptr-- = '\0';
printchar('\b');
}
else if(ptr != end-1)
{
*ptr++ = ch;
printchar(ch);
}
}
printchar('\n');
if(ptr == end) ptr--;
*ptr = '\0';
}
//static char* katoi_base = "0123456789ABCDEF";
static i32 _katoi(char* str,int base,u32 len)
{
char* end;
i32 i,pow;
i32 num;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == '-')
{
num *= -1;
break;
}
else if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == xnums[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
static u32 _katou(char* str,int base,u32 len)
{
char* end;
u32 i,pow;
u32 num;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == xnums[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
i32 katoi(char* str,int base)
{
return _katoi(str,base,kstrlen(str));
}
u32 katou(char* str,int base)
{
return _katou(str,base,kstrlen(str));
}
static u32 _kstrchr_delim(char* buf,u32 base)
{
u32 i,len;
char c;
len = 0;
while(*buf)
{
c = *buf;
for(i = 0; i < base; i++)
{
if(c == xnums[i]) break;
}
if(i == base && c != '-') break;
buf++;
len++;
}
return len;
}
void ksscanf(char* buf,char* fmt,...)
{
u32* argp;
u32 len,maxLen;
union {
i32* iptr;
u32* uptr;
char* sptr;
} u;
char c,*stk;
argp = ((u32*)&fmt)+1;
while((c = *fmt))
{
//kprintf("%c %c\n",c,*buf);
if(c == '%')
{
c = *++fmt;
switch(c)
{
case 'u':
case 'd':
len = _kstrchr_delim(buf,10);
u.iptr = (i32*)(*(u32*)argp++);
*u.iptr = _katoi(buf,10,len);
buf += len; //we decrement because it will +1
break;
case 'p':
case 'x':
buf += 2; //Skip 0x part
len = _kstrchr_delim(buf,16);
u.iptr = (i32*)(*(u32*)argp++);
*u.iptr = _katoi(buf,16,len);
buf += len; //we decrement because it will +1
break;
case 's':
stk = kstrchr(buf,*(fmt+1));
u.sptr = (char*)(*(u32*)argp++);
maxLen = (*(u32*)argp++);
if(!stk)
{
u.sptr[0] = '\0';
break;
}
len = (u32)stk-(u32)buf;
if(len > maxLen) len = maxLen;
kmemcpy(u.sptr,buf,len);
u.sptr[len] = '\0';
buf += len;
break;
}
} else buf++;
fmt++;
}
}

44
kernel_old/stdlib.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef __STDLIB_H
#define __STDLIB_H
#include "os.h"
#include "vga_terminal.h"
//stdlib.h
extern void kmemcpy(void* dst,const void* src,u32 len);
extern int kmemcmp(const void* dst,const void* src,u32 len);
extern void kmemzero(void* dst,u32 len);
//termlib.h
#define kputc printchar
void iprint(int number);
void uprint(u32 number);
void xprint(u32 number);
void iprints(char* str,int number);
void uprints(char* str,u32 number);
void xprints(char* str,u32 number);
void kprint(char* str);
void ksprintf(char* dst,u32 maxLen,const char* fmt,...);
void kprintf(const char* fmt,...);
//termio.h
u8 kgetch(); //Wait for key scan code
u8 kgetc(); //Wait for ASCII character
void kgets(char* buf,size_t max);
i32 katoi(char* str,int base);
void ksscanf(char* buf,char* fmt,...);
#define _debug() \
kprintf("_debug at %s:%u\n",__FILE__,__LINE__); \
kgetc();
#endif

49
kernel_old/string.c Normal file
View file

@ -0,0 +1,49 @@
#include "string.h"
#include "stdlib.h"
u32 kstrlen(const char* str)
{
u32 len = 0;
while(*str++) len++;
return len;
}
void kstrcpy(char* dst,const char* src)
{
while((*dst++ = *src++)){}
}
void kstrncpy(char* dst,const char* src,u32 maxLen)
{
maxLen=-1;
while((*dst++ = *src++) && --maxLen){}
if(!maxLen) dst[maxLen] = '\0';
}
char* kstrchr(char* src,char chr)
{
while(*src)
{
if(*src == chr) return src;
src++;
}
return NULL;
}
char* kstrrchr(char* src,char chr)
{
char* ptr;
ptr = src+kstrlen(src)-1;
while(ptr != src)
{
if(*ptr == chr) return ptr;
ptr--;
}
return NULL;
}
int kstrncmp(const char* haystack,char* needle)
{
return kmemcmp(haystack,needle,kstrlen(needle));
}

16
kernel_old/string.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef __STRING_H
#define __STRING_H
#include "os.h"
u32 kstrlen(const char* str);
void kstrcpy(char* dst,const char* src);
void kstrncpy(char* dst,const char* src,u32 maxLen);
char* kstrchr(char* src,char chr);
char* kstrrchr(char* src,char chr);
int kstrncmp(const char* haystack,char* needle);
#endif

175
kernel_old/termio.c Normal file
View file

@ -0,0 +1,175 @@
#include "termio.h"
#include "keyboard.h"
#include "vga_terminal.h"
#include "string.h"
u8 kgetch()
{
u8 key;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
key = keyboard_scan_code();
keyboard_reset_irq1_vars();
return key;
}
u8 kgetc()
{
u8 ascii;
while(keyboard_scan_code() == 0)
{__asm("hlt");}
ascii = keyboard_ascii();
keyboard_reset_irq1_vars();
return ascii;
}
void kgets(char* buf,size_t max)
{
u8 ch;
char* ptr,*end;
ptr = buf;
end = buf + max;
*ptr = '\0';
while((ch = kgetc()) != '\n')
{
if(ch == '\b')
{
if(ptr != buf) *ptr-- = '\0';
printchar('\b');
}
else if(ptr != end-1)
{
*ptr++ = ch;
printchar(ch);
}
}
printchar('\n');
if(ptr == end) ptr--;
*ptr = '\0';
}
static char* katoi_base = "0123456789ABCDEF";
static i32 _katoi(char* str,int base,u32 len)
{
char* end;
i32 i,pow;
i32 num;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == '-')
{
num *= -1;
break;
}
else if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == katoi_base[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
static u32 _katou(char* str,int base,u32 len)
{
char* end;
u32 i,pow;
u32 num;
i = 0;
num = 0;
pow = 1;
end = str+len-1;
while(1)
{
if(*end == 'x') break;
for(i = 0; i < base; i++)
if(*end == katoi_base[i]) break;
num += i*pow;
pow *= base;
if(end == str) break;
end--;
}
return num;
}
i32 katoi(char* str,int base)
{
return _katoi(str,base,kstrlen(str));
}
u32 katou(char* str,int base)
{
return _katou(str,base,kstrlen(str));
}
static u32 _kstrchr_delim(char* buf,u32 base)
{
u32 i,len;
char c;
len = 0;
while(*buf)
{
c = *buf;
for(i = 0; i < base; i++)
{
if(c == katoi_base[i]) break;
}
if(i == base && c != '-') break;
buf++;
len++;
}
return len;
}
void ksscanf(char* buf,char* fmt,...)
{
u32* argp;
u32 len;
i32* iptr;
u32* uptr;
char c,*stk;
argp = ((u32*)&fmt)+1;
while((c = *fmt))
{
//kprintf("%c %c\n",c,*buf);
if(c == '%')
{
c = *++fmt;
switch(c)
{
case 'u':
case 'd':
len = _kstrchr_delim(buf,10);
iptr = (i32*)(*(u32*)argp++);
*iptr = _katoi(buf,10,len);
buf += len; //we decrement because it will +1
break;
case 'p':
case 'x':
buf += 2; //Skip 0x part
len = _kstrchr_delim(buf,16);
iptr = (i32*)(*(u32*)argp++);
*iptr = _katoi(buf,16,len);
buf += len; //we decrement because it will +1
}
} else buf++;
fmt++;
}
}

7
kernel_old/termio.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef __TERMIO_H
#define __TERMIO_H
#include "os.h"
#include "stdlib.h" //redirect to stdlib.h
#endif

201
kernel_old/termlib.c Normal file
View file

@ -0,0 +1,201 @@
#include "termlib.h"
#include "vga_terminal.h"
#include "string.h"
void iprint(int number)
{
//4294967295
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
s--;
while(s >= num) printchar(*s--);
}
void uprint(u32 number)
{
//4294967295
char num[32];
char* s = num;
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
s--;
while(s >= num) printchar(*s--);
}
const char* xnums = "0123456789ABCDEF";
void xprint(u32 number)
{
//FFFFFFFF
char num[16];
char* s = num;
while(s-num < 7)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
s--;
while(s >= num) printchar(*s--);
}
void iprints(char* outs,int number)
{
//4294967295
char num[32];
char* s = num;
int uns = 0;
if(number < 0)
{
uns = 1;
number *= -1;
}
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
if(uns) *s++ = '-';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void uprints(char* outs,u32 number)
{
//4294967295
char num[32];
char* s = num;
while(number > 10)
{
*s++ = '0'+(number%10);
number/=10;
}
*s++ = '0'+(number%10);
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void xprints(char* outs,u32 number)
{
//FFFFFFFF
char num[16];
char* s = num;
while(s-num < 7)
{
*s++ = xnums[(number%16)];
number/=16;
}
*s++ = xnums[(number%16)];
*s++ = 'x';
*s++ = '0';
while(s >= num) *outs++ = *--s;
*outs++ = '\0';
}
void kprint(char* str)
{
while(*str) printchar(*str++);
}
void ksprintf(char* dst,u32 maxLen,const char* fmt,...)
{
u32* argp;
char* cur,*end,c;
char numbuf[64];
argp = ((u32*)&fmt)+1;
cur = dst;
end = dst+maxLen;
while((c = *fmt++) && cur != end)
{
if(c == '%')
{
char* p = numbuf;
c = *fmt++;
if(c == 'd')
{
iprints(numbuf,*(int*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'u')
{
uprints(numbuf,*(int*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 'p' || c == 'x')
{
xprints(numbuf,*(u32*)argp++);
while((*cur++ = *p++))
if(cur == end) break;
cur--;
}
else if(c == 's')
{
const char* str = *(const char**)argp++;
while((*cur++ = *str++))
if(cur == end) break;
cur--;
}
}
else
{
if(cur == end) break;
*cur++ = c;
}
}
if(cur == end)
*(end-1) = '\0';
}
void kprintf(const char* fmt,...)
{
u32* argp;
char c;
argp = ((u32*)&fmt)+1;
while((c = *fmt++))
{
if(c == '%')
{
c = *fmt++;
switch(c)
{
case 'd': iprint(*(int*)argp++); break;
case 'u': uprint(*(u32*)argp++); break;
case 'p':
case 'x': xprint(*(u32*)argp++); break;
case 'c': printchar((char)(*(u32*)argp++)); break;
case 's': kprint((char*)(*(u32*)argp++)); break;
}
}
else printchar(c);
}
}

7
kernel_old/termlib.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef __TERMLIB_H
#define __TERMLIB_H
#include "os.h"
#include "stdlib.h" //redirect to stdlib.h
#endif

107
kernel_old/vga_terminal.c Normal file
View file

@ -0,0 +1,107 @@
#include "vga_terminal.h"
#include "paging.h"
#include "os.h"
#include "io.h"
static u8 s_cCurAttr = DEFAULT_COLOR;
u32 s_iX;
u32 s_iY;
void vga_terminal_init()
{
//Map 0xB8000 to 0xC100B8000
page_map(OS_VIDEO_BUFFER,0x000B8000,80*25,PAGE_TABLE_READWRITE);
}
void update_cursor()
{
u16 pos;
pos = s_iY * 80 + s_iX;
outb(0x3D4, 0x0F);
outb(0x3D5, (u8) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (u8) ((pos >> 8) & 0xFF));
}
void cls()
{
u32 i;
for(i = 0; i < SCR_CHARS*SCR_LINES; i++)
SCR_TEXT_BUF[i] = SCR_ENTRY(0,DEFAULT_COLOR);
s_iX = s_iY = 0;
update_cursor();
}
void shiftscreen();
void printchar(unsigned char c)
{
if(c == '\n' || c == '\r' || c == '\t' || c == '\b') // Control characters
{
if(c == '\r') s_iX = 0;
else if(c == '\n') s_iX = SCR_CHARS;
else if(c == '\t') s_iX = (s_iX + 8) & ~7;
else if(c == '\b')
{
if(s_iX) s_iX--;
else if(s_iY)
{
s_iY--;
s_iX = SCR_CHARS-1;
}
//Remove character
SCR_TEXT_BUF[s_iY*SCR_CHARS+s_iX] = SCR_ENTRY(0,s_cCurAttr);
}
}
else // Text characters
SCR_TEXT_BUF[s_iY*SCR_CHARS+s_iX++] = SCR_ENTRY(c,s_cCurAttr);
if(s_iX > SCR_CHARS-1)
{
s_iX = 0;
if(s_iY < SCR_LINES-1)
s_iY++;
else shiftscreen();
}
update_cursor();
}
void shiftscreen()
{
//cls();
u32 x,y;
for(y = 1; y < SCR_LINES; y++)
{
for(x = 0; x < SCR_CHARS; x++)
{
SCR_TEXT_BUF[(y-1)*SCR_CHARS+x]
= SCR_TEXT_BUF[y*SCR_CHARS+x];
}
}
for(x = 0; x < SCR_CHARS; x++)
{
SCR_TEXT_BUF[(SCR_LINES-1)*SCR_CHARS+x]
= SCR_ENTRY(0,DEFAULT_COLOR);
}
}
void chg_color(u8 color)
{
s_cCurAttr = color;
}
void print(const char* str)
{
while(*str) printchar(*str++);
}
void move_to_next_char(){}
void move_to_next_line(){}
void locate(int h, int w)
{
s_iX = w;
s_iY = h;
}

67
kernel_old/vga_terminal.h Normal file
View file

@ -0,0 +1,67 @@
#ifndef __VGA_TERMINAL_H
#define __VGA_TERMINAL_H
#include "os.h"
#define SCR_CHARS 80
#define SCR_LINES 25
//#define SCR_TEXT_BUF ((u16*)0xB8000)
#define SCR_TEXT_BUF ((u16*)OS_VIDEO_BUFFER)
#define SCR_ENTRY(ch,col) ((col<<8)|ch)
#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 2
#define RED 4
#define GRAY 8
#define WHITE 15
#define MAGENTA 13
#define BG_BLACK (0<<4)
#define BG_BLUE (1<<4)
#define BG_GREEN (2<<4)
#define BG_RED (4<<4)
#define BG_GRAY (8<<4)
#define BG_WHITE (15<<4)
#define DEFAULT_COLOR BG_BLACK|7
enum vga_color {
VGA_COLOR_BLACK = 0,
VGA_COLOR_BLUE = 1,
VGA_COLOR_GREEN = 2,
VGA_COLOR_CYAN = 3,
VGA_COLOR_RED = 4,
VGA_COLOR_MAGENTA = 5,
VGA_COLOR_BROWN = 6,
VGA_COLOR_LIGHT_GREY = 7,
VGA_COLOR_DARK_GREY = 8,
VGA_COLOR_LIGHT_BLUE = 9,
VGA_COLOR_LIGHT_GREEN = 10,
VGA_COLOR_LIGHT_CYAN = 11,
VGA_COLOR_LIGHT_RED = 12,
VGA_COLOR_LIGHT_MAGENTA = 13,
VGA_COLOR_LIGHT_BROWN = 14,
VGA_COLOR_WHITE = 15,
};
static inline u8 vga_entry_color(enum vga_color fg, enum vga_color bg) {
return fg | bg << 4;
}
static inline u16 vga_entry(unsigned char uc, u8 color) {
return (u16) uc | (u16) color << 8;
}
void vga_terminal_init();
void cls();
void shiftscreen();
void printchar(unsigned char c);
void chg_color(u8 color);
void print(const char* str);
void locate(int h, int w);
#endif

37
kernel_old/x86_utils.c Normal file
View file

@ -0,0 +1,37 @@
#include "x86utils.h"
#include "vga_terminal.h"
#include "termlib.h"
void x86_print_regs()
{
struct regs_s regs;
x86_get_regs(&regs);
chg_color(VGA_COLOR_WHITE);
kprintf(
"[========\t\tx86 register dump\t\t========]\n"
"\tEAX\t%x\tECX\t%x\n\tEDX\t%x\tEBX\t%x\n"
"\tESP\t%x\tEBP\t%x\n\tESI\t%x\tEDI\t%x\n"
"\n\tEIP\t%x\n"
"\tEFLAGS\t%x\n"
"\n\tCS %x DS %x SS %x\n"
"\tES %x FS %x GS %x\n"
"\n\tGDT\t%x\n\tIDT\t%x\n\tLDT\t%x\n\tTR\t%x\n"
"\n\tCR0\t%x\tCR2\t%x\n"
"\tCR3\t%x\tCR4\t%x\n"
"[========\t\tx86 register dump\t\t========]\n",
regs.eax,regs.ecx,regs.edx,regs.ebx,
regs.esp,regs.ebp,regs.esi,regs.edi,
regs.eip,
regs.eflags,
regs.cs,regs.ds,regs.ss,
regs.es,regs.fs,regs.gs,
regs.gdt,
regs.idt,
regs.ldt,
regs.tr,
regs.cr0,regs.cr2,
regs.cr3,regs.cr4
);
chg_color(VGA_COLOR_MAGENTA);
}

36
kernel_old/x86gdt.asm Normal file
View file

@ -0,0 +1,36 @@
section .text
global _gdt_install
_gdt_install:
push ebp
mov ebp,esp
; [ebp+0x08] = GDT table ptr
; [ebp+0x0C] = GDT limit
mov eax,dword [ebp+0x08]
mov dword [gdt_base],eax
mov eax,dword [ebp+0x0C]
mov word [gdt_limit],ax
lgdt [x86gdt]
; 0x00 - NULL desc
; 0x08 - CODE desc
; 0x10 - DATA desc
; Reloads segments
jmp 0x08:reload_cs
reload_cs:
mov ax,0x10
mov ds,ax
mov es,ax
mov ss,ax
mov gs,ax
mov fs,ax
mov esp,ebp
pop ebp
ret
section .data
x86gdt:
gdt_limit dw 0
gdt_base dd 0

Some files were not shown because too many files have changed in this diff Show more