Леночка
This commit is contained in:
commit
00318a6b5e
193 changed files with 81446 additions and 0 deletions
124
Makefile
Normal file
124
Makefile
Normal 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
BIN
bdf2bin
Normal file
Binary file not shown.
95
bdf2bin.c
Normal file
95
bdf2bin.c
Normal 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
226
bochsout.txt
Normal 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
8
boot/grub/grub.cfg
Normal 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
2
build.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
make lenochka.elf && make mount && make update && make unmount
|
||||||
26
bx_enh_dbg.ini
Normal file
26
bx_enh_dbg.ini
Normal 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
2
export.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
export PATH="$HOME/opt/cross/bin:$PATH"
|
||||||
BIN
font.bin
Normal file
BIN
font.bin
Normal file
Binary file not shown.
276
kernel/ahci.c
Normal file
276
kernel/ahci.c
Normal 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
326
kernel/ahci.h
Normal 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
51
kernel/bmp.c
Normal 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
8
kernel/bmp.h
Normal 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
10
kernel/defines.h
Normal 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
137
kernel/disk.c
Normal 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
50
kernel/disk.h
Normal 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
141
kernel/exceptions.c
Normal 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
9
kernel/exceptions.h
Normal 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
331
kernel/fat.c
Normal 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
102
kernel/fat.h
Normal 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
86
kernel/file.c
Normal 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
9
kernel/file.h
Normal 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
194
kernel/heap.c
Normal 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
12
kernel/heap.h
Normal 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
91
kernel/idt.c
Normal 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
17
kernel/idt.h
Normal 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
21
kernel/io.h
Normal 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
174
kernel/keyboard.c
Normal 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
52
kernel/keyboard.h
Normal 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
250
kernel/kmain.c
Normal 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
38
kernel/lvalloc.c
Normal 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
15
kernel/lvalloc.h
Normal 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
36
kernel/multiboot.c
Normal 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
61
kernel/multiboot.h
Normal 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
133
kernel/os.h
Normal 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
131
kernel/paging.c
Normal 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
14
kernel/paging.h
Normal 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
251
kernel/pci.c
Normal 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
24
kernel/pci.h
Normal 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
45
kernel/pic.c
Normal 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
16
kernel/pic.h
Normal 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
36
kernel/pit.c
Normal 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
10
kernel/pit.h
Normal 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
17
kernel/start.asm
Normal 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
444
kernel/stdlib.c
Normal 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
45
kernel/stdlib.h
Normal 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
142
kernel/string.c
Normal 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
31
kernel/string.h
Normal 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
41
kernel/va_list.asm
Normal 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
13
kernel/va_list.h
Normal 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
175
kernel/vga_terminal.c
Normal 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
68
kernel/vga_terminal.h
Normal 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
140
kernel/video.c
Normal 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
16
kernel/video.h
Normal 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
12
kernel/x64font.asm
Normal 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
18
kernel/x64idt.asm
Normal 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
89
kernel/x64ints.asm
Normal 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
80
kernel/x64io.asm
Normal 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
56
kernel/x64stdlib.asm
Normal 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
10
kernel/x64utils.asm
Normal 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
169
kernel_old/ahci.c
Normal 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
315
kernel_old/ahci.h
Normal 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
122
kernel_old/ata_pio.c
Normal 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
59
kernel_old/ata_pio.h
Normal 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
138
kernel_old/exceptions.c
Normal 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
9
kernel_old/exceptions.h
Normal 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
39
kernel_old/gdt.c
Normal 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
29
kernel_old/gdt.h
Normal 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
72
kernel_old/idt.c
Normal 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
60
kernel_old/idt.h
Normal 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
21
kernel_old/io.h
Normal 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
151
kernel_old/keyboard.c
Normal 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
50
kernel_old/keyboard.h
Normal 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
142
kernel_old/kmain.c
Normal 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
36
kernel_old/memory.c
Normal 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
25
kernel_old/memory.h
Normal 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
101
kernel_old/multiboot.asm
Normal 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
58
kernel_old/multiboot.h
Normal 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
36
kernel_old/os.h
Normal 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
93
kernel_old/paging.c
Normal 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
37
kernel_old/paging.h
Normal 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
251
kernel_old/pci.c
Normal 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
24
kernel_old/pci.h
Normal 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
45
kernel_old/pic.c
Normal 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
16
kernel_old/pic.h
Normal 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
36
kernel_old/pit.c
Normal 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
10
kernel_old/pit.h
Normal 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
398
kernel_old/stdlib.c
Normal 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
44
kernel_old/stdlib.h
Normal 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
49
kernel_old/string.c
Normal 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
16
kernel_old/string.h
Normal 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
175
kernel_old/termio.c
Normal 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
7
kernel_old/termio.h
Normal 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
201
kernel_old/termlib.c
Normal 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
7
kernel_old/termlib.h
Normal 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
107
kernel_old/vga_terminal.c
Normal 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
67
kernel_old/vga_terminal.h
Normal 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
37
kernel_old/x86_utils.c
Normal 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(®s);
|
||||||
|
|
||||||
|
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
36
kernel_old/x86gdt.asm
Normal 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
Loading…
Add table
Reference in a new issue