Леночка
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