From 63f7e530cc92569980ff1d12de3aefc9c028f1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Hord=C3=A9?= Date: Tue, 15 Jan 2019 01:15:58 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20chargement=20pmode=20complet=20jusqu'?= =?UTF-8?q?=C3=A0=20lancement=20du=20code=20pour=20la=20d=C3=A9compression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debug/boot.txt | 5 +- debug/gdbinit | 21 +++++-- include/setup.h | 6 +- include/system.h | 3 +- lib/gdt.c | 52 +++++++++++++++++ makefile | 14 ++--- system/makefile | 6 +- system/realmode/makefile | 9 ++- system/realmode/pmode.S | 40 +++++++++++++ system/realmode/setup.S | 2 +- system/realmode/setup.c | 93 ++++++++----------------------- system/system.c | 3 + system/{system.S => system_asm.S} | 4 +- 13 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 system/realmode/pmode.S rename system/{system.S => system_asm.S} (94%) diff --git a/debug/boot.txt b/debug/boot.txt index 976530d..c3b9e2a 100644 --- a/debug/boot.txt +++ b/debug/boot.txt @@ -1,7 +1,10 @@ target remote localhost:1234 set disassembly-flavor att -symbol-file ./system/realmode/setup.sym +add-symbol-file ./system/realmode/setup.sym 0x902f6 set architecture i8086 break *0x90200 cont clear *0x90200 +break main +cont +clear main diff --git a/debug/gdbinit b/debug/gdbinit index 83ad9d2..822e958 100644 --- a/debug/gdbinit +++ b/debug/gdbinit @@ -882,7 +882,12 @@ class Source(Dashboard.Module): if not gdb.selected_thread().is_stopped(): return [] # try to fetch the current line (skip if no line information) - sal = gdb.selected_frame().find_sal() + arch = gdb.parameter('architecture'); + if arch=="i8086": + realpc=int(gdb.parse_and_eval('$pc'))+int(gdb.parse_and_eval('$cs'))*16 + sal = gdb.find_pc_line(realpc) + else: + sal = gdb.selected_frame().find_sal() current_line = sal.line if current_line == 0: return [] @@ -962,7 +967,12 @@ instructions constituting the current statement are marked, if available.""" if not gdb.selected_thread().is_stopped(): return [] line_info = None + arch = gdb.parameter('architecture'); frame = gdb.selected_frame() # PC is here + if arch=="i8086": + realpc=frame.pc()+int(gdb.parse_and_eval('$cs'))*16 + else: + realpc=frame.pc() disassemble = frame.architecture().disassemble try: # try to fetch the function boundaries using the disassemble command @@ -971,21 +981,20 @@ instructions constituting the current statement are marked, if available.""" end = int(re.split('[ :]', output[-3][3:], 1)[0], 16) asm = disassemble(start, end_pc=end) # find the location of the PC - pc_index = next(index for index, instr in enumerate(asm) - if instr['addr'] == frame.pc()) + pc_index = next(index for index, instr in enumerate(asm) if instr['addr'] == realpc) start = max(pc_index - self.context, 0) end = pc_index + self.context + 1 asm = asm[start:end] # if there are line information then use it, it may be that # line_info is not None but line_info.last is None - line_info = gdb.find_pc_line(frame.pc()) + line_info = gdb.find_pc_line(realpc) line_info = line_info if line_info.last else None except (gdb.error, StopIteration): # if it is not possible (stripped binary or the PC is not present in # the output of `disassemble` as per issue #31) start from PC and # end after twice the context try: - asm = disassemble(frame.pc(), count=2 * self.context + 1) + asm = disassemble(realpc, count=2 * self.context + 1) except gdb.error as e: msg = '{}'.format(e) return [ansi(msg, R.style_error)] @@ -1046,7 +1055,7 @@ instructions constituting the current statement are marked, if available.""" format_string = '{}{}{}{}{}' indicator = ' ' text = ' ' + highlighter.process(text) - if addr == frame.pc(): + if addr == realpc: if not R.ansi: indicator = '>' addr_str = ansi(addr_str, R.style_selected_1) diff --git a/include/setup.h b/include/setup.h index b51e6cf..0ca2297 100644 --- a/include/setup.h +++ b/include/setup.h @@ -91,12 +91,10 @@ u8 testA20(void); void enableA20kbc(void); void enableA20fast(void); u8 enableA20(void); -void memset(void *dst, u8 val, u32 count, u32 size); -void memcpy(void *src, void *dst, u32 count, u32 size); -void initselectors(u32 executingoffset); +void memcpyto(void *src, void *dst, u32 count); void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes * desc); void initgdt(); void maskinterrupts(void); void initcoprocessor(void); -void initpmode(u32 offset); +void initpmode(); void main(void); diff --git a/include/system.h b/include/system.h index 3c16033..9a6e597 100644 --- a/include/system.h +++ b/include/system.h @@ -1,4 +1,5 @@ /*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ -extern restart; +extern restart; +int main(u8* info); diff --git a/lib/gdt.c b/lib/gdt.c index 899e7f3..f299569 100644 --- a/lib/gdt.c +++ b/lib/gdt.c @@ -6,9 +6,61 @@ #include "types.h" #include "memory.h" + /* registre gdt */ +static struct gdtr gdtreg; + +/* table de GDT */ +static gdtdes gdt[GDT_SIZE]; + /* TSS */ static struct tss tss0; +/*******************************************************************************/ +/* Créé un descripteur GDT */ + +void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes * desc) +{ + desc->lim0_15 = (limite & 0xffff); + desc->base0_15 = (base & 0xffff); + desc->base16_23 = (base & 0xff0000) >> 16; + desc->acces = acces; + desc->lim16_19 = (limite & 0xf0000) >> 16; + desc->flags = (flags & 0xf); + desc->base24_31 = (base & 0xff000000) >> 24; + return; +} + +/*******************************************************************************/ +/* Initialise la GDT */ + +void initgdt(u32 offset) +{ + makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[0]); /* descripteur nul */ + makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING0 | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[1]); /* code -> SEL_KERNEL_CODE */ + makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[2]); /* pile -> SEL_KERNEL_STACK */ + makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING3 | SEG_CONFORMING | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[3]); /* code -> SEL_USER_CODE */ + makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[4]); /* pile -> SEL_USER_STACK */ + makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[5]); /* data -> SEL_KERNEL_DATA */ + makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[6]); /* data -> SEL_USER_DATA */ + + tss0.trapflag = 0x00; + tss0.iomap = 0x00; + tss0.esp0 = 0x6000; + tss0.ss0 = SEL_TSS; + + makegdtdes(&tss0, 0x67, SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED, 0x00, &gdt[7]); /* descripteur de tss */ + + /* initialise le registre gdt */ + gdtreg.limite = GDT_SIZE * sizeof(gdtdes); + gdtreg.base = GDT_ADDR; + /* recopie de la GDT a son adresse */ + memcpy(&gdt, (u8 *) gdtreg.base, gdtreg.limite, 1); + /* chargement du registre GDT */ + lgdt(gdtreg); + /* initialisation des segments */ + initselectors(offset); +} + /*******************************************************************************/ /* Initialise les selecteurs avec la GDT */ diff --git a/makefile b/makefile index bb87f50..8c670db 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -DEBUG=exec gnome-terminal --geometry=120x40+1+1 -x ./debug/debug.sh +DEBUG=exec gnome-terminal --geometry=120x55+1+1 -x ./debug/debug.sh REMOVE=rm -f INSTALL=sudo apt-get install COPY=cp @@ -81,15 +81,15 @@ backup: clean cd .. tar cf - Source\ C | gzip -f - > backup.tar.gz -test: programs bits32 harddisk qemu +test: tools programs bits32 harddisk qemu -test64: programs bits64 uefi qemu64 +test64: tools programs bits64 uefi qemu64 retest: littleclean test retest64: littleclean test64 -testbochs: programs bits32 harddisk bochs-debug +testbochs: tools programs bits32 harddisk bochs-debug view: hexdump -C ./final/harddisk.img.final|head -c10000 @@ -104,15 +104,15 @@ redebug64: littleclean debug-system64 kernel: debug-kernel -debug-boot: programs bits32 harddisk qemu-debug +debug-boot: tools programs bits32 harddisk qemu-debug sleep 2 $(DEBUG) ./debug/boot.txt -debug-system: programs bits32 harddisk qemu-debug +debug-system: tools programs bits32 harddisk qemu-debug sleep 2 $(DEBUG) ./debug/system.txt -debug-system64: programs bits64 uefi qemu-debug64 +debug-system64: tools programs bits64 uefi qemu-debug64 sleep 2 $(DEBUG) ./debug/system.txt diff --git a/system/makefile b/system/makefile index ad77049..3121d83 100755 --- a/system/makefile +++ b/system/makefile @@ -34,7 +34,7 @@ togit: clean indent piggy.o: piggy.S $(ASM) $@ $^ -system: systemc.o system.o ../lib/libs.o +system: system.o system_asm.o ../lib/libs.o $(LINK) -T system.ld system.o ../lib/libs.o $(OBJDEBUG) system system.sym $(NM) system > system.map @@ -51,10 +51,10 @@ piggy.S: system.bin.gz realmode/setup.bin: make -C realmode -systemc.o: system.c +system.o: system.c $(GCC) $@ $^ -system.o: system.S +system_asm.o: system_asm.S $(ASM) $@ $^ clean: diff --git a/system/realmode/makefile b/system/realmode/makefile index 0ff652c..88f9fbf 100644 --- a/system/realmode/makefile +++ b/system/realmode/makefile @@ -1,4 +1,4 @@ -GCC=gcc -O0 -g -nostdinc -ffreestanding -Wall -Wstrict-prototypes -fno-stack-protector -march=i386 -m16 -mpreferred-stack-boundary=2 -mregparm=3 -fno-pic -fno-strict-aliasing -mno-mmx -mno-sse -w -I ../../include -c +GCC=gcc -O0 -g -nostdinc -ffreestanding -Wall -Wstrict-prototypes -fno-stack-protector -march=i386 -m16 -fno-pic -fno-strict-aliasing -mno-mmx -mno-sse -w -I ../../include -c ASM=gcc -O0 -m16 -march=i386 -fno-pic -D__ASSEMBLY__ -I ../ -I ../../include -c -o LINK=ld -m elf_i386 -n CONVERT=dos2unix @@ -13,8 +13,8 @@ $(eval VERSION=$(shell git describe --tags)) all: setup.bin sync -setup: setupc.o setup.o - $(LINK) -T setup.ld setupc.o setup.o +setup: setupc.o setup.o setup32.o + $(LINK) -T setup.ld setupc.o setup.o setup32.o setup.bin: setup $(OBJCOPY) $^ $@ @@ -27,6 +27,9 @@ setupc.o: setup.c setup.o: setup.S $(ASM) $@ $^ +setup32.o: pmode.S + $(ASM) $@ $^ + clean: $(REMOVE) setup $(REMOVE) *.o diff --git a/system/realmode/pmode.S b/system/realmode/pmode.S new file mode 100644 index 0000000..8c0cbe3 --- /dev/null +++ b/system/realmode/pmode.S @@ -0,0 +1,40 @@ +#include "memory.h" +#include "gdt.h" +.text +.code16 + +.global gotopmode +gotopmode: + jmp 1f +1: + xorl %eax,%eax + movl %ds,%ax + shl $0x4,%eax + add %eax,(2f) + movl %cr0, %eax + orb $0x01, %al + movl %eax, %cr0 + .byte 0x66, 0xea +2: .long pmode + .word SEL_KERNEL_CODE + +.code32 +.section ".text32","ax" +.global pmode +pmode: + movw $SEL_KERNEL_DATA, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movl $KERNEL_CODE_ADDR, %ebx + movw $SEL_KERNEL_STACK, %ax + movw %ax, %ss + movl $KERNEL_STACK_ADDR, %esp + xor %eax,%eax + xor %ecx,%ecx + xor %edx,%edx + xor %esi,%esi + xor %edi,%edi + xor %ebp,%ebp + jmp *%ebx diff --git a/system/realmode/setup.S b/system/realmode/setup.S index 7fb5b42..98a00bb 100644 --- a/system/realmode/setup.S +++ b/system/realmode/setup.S @@ -123,7 +123,7 @@ setup_move_size: .word 0x8000 # size to move, when setup is not code32_start: # here loaders can put a different # start address for 32-bit code. - .long 0x100000 # 0x100000 = default for big kernel + .long LOAD_PHYSICAL_ADDR # 0x100000 = default for big kernel ramdisk_image: .long 0 # address of loaded ramdisk image # Here the loader puts the 32-bit diff --git a/system/realmode/setup.c b/system/realmode/setup.c index 759e70f..3b55d84 100644 --- a/system/realmode/setup.c +++ b/system/realmode/setup.c @@ -175,86 +175,37 @@ u8 enableA20(void) int loops = LOOPS_A20_ENABLE; int kbcerr; while (loops--) { - if (testA20()) - return 1; + if (!testA20()) + return NULL; kbcerr = empty8042(); - if (testA20()) - return 1; + if (!testA20()) + return NULL; if (!kbcerr) { enableA20kbc(); - if (testA20()) - return 1; + if (!testA20()) + return NULL; } enableA20fast(); - if (testA20()) + if (!testA20()) return NULL; } return 1; } -/*******************************************************************************/ -/* Copie un octet une ou plusieurs fois en mémoire */ - -void memset(void *dst, u8 val, u32 count, u32 size) -{ - u8 *d = (u8 *) dst; - if (size > 0) - size--; - for (; count != 0; count--) - { - *(d++) = val; - d += size; - } -} - /*******************************************************************************/ /* Copie une portion de mémoire vers une autre */ -void memcpy(void *src, void *dst, u32 count, u32 size) +void memcpyto(void *src, void *dst, u32 count) { - u8 *s = (u8 *) src; - u8 *d = (u8 *) dst; - if (size > 0) - size--; - for (; count != 0; count--) - { - *(d++) = *(s++); - d += size; - } + asm("push %%es\n\ + cld\n\ + xor %%eax,%%eax\n\ + mov %%ax,%%es\n\ + rep movsb\n\ + pop %%es"::"S" (src), "D" (dst), "c" (count):); } -/*******************************************************************************/ -/* Initialise les selecteurs avec la GDT */ - -void initselectors(u32 executingoffset) -{ - asm(" movl %%cr0, %%eax \n \ - orb $0x00000001, %%eax \n \ - movl %%eax, %%cr0 \n \ - ljmp %[code], $raz\n\ - raz:\n \ - .code32\n\ - movw %[data], %%ax \n \ - movw %%ax, %%ds \n \ - movw %%ax, %%es \n \ - movw %%ax, %%fs \n \ - movw %%ax, %%gs \n \ - movl %[offset], %%ebx \n \ - movw %[stack], %%ax \n \ - movw %%ax, %%ss \n \ - movl %[stackoff], %%esp \n \ - xor %%eax,%%eax\n\ - xor %%ebx,%%ebx\n\ - xor %%ecx,%%ecx\n\ - xor %%edx,%%edx\n\ - xor %%esi,%%esi\n\ - xor %%edi,%%edi\n\ - xor %%ebp,%%ebp\n\ - jmp %%ebx\n\ - .code16gcc"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset)); -} - /*******************************************************************************/ /* Créé un descripteur GDT */ @@ -278,16 +229,16 @@ void initgdt() makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[0]); /* descripteur nul */ makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING0 | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[1]); /* code -> SEL_KERNEL_CODE */ makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[2]); /* pile -> SEL_KERNEL_STACK */ - makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING3 | SEG_CONFORMING | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[3]); /* code -> SEL_USER_CODE */ - makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[4]); /* pile -> SEL_USER_STACK */ + makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[3]); /* LIBRE */ + makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[4]); /* LIBRE */ makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[5]); /* data -> SEL_KERNEL_DATA */ - makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[6]); /* data -> SEL_USER_DATA */ - makegdtdes(0x0, 0x67, SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED, 0x00, &gdt[7]); /* descripteur de tss */ + makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[6]); /* LIBRE */ + makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[7]); /* LIBRE */ /* initialise le registre gdt */ gdtreg.limite = GDT_SIZE * sizeof(gdtdes); gdtreg.base = GDT_ADDR; /* recopie de la GDT a son adresse */ - memcpy(&gdt, (u8 *) gdtreg.base, gdtreg.limite, 1); + memcpyto(&gdt, (u8 *) gdtreg.base, gdtreg.limite); /* chargement du registre GDT */ lgdt(gdtreg); } @@ -311,7 +262,7 @@ void initcoprocessor(void) iodelay(); } -void initpmode(u32 offset) +void initpmode() { if (enableA20()) { showstr("impossible d'ouvrir la ligne A20...\n"); @@ -319,7 +270,7 @@ void initpmode(u32 offset) } maskinterrupts(); initgdt(); - initselectors(offset); + gotopmode(); } void main(void) @@ -334,5 +285,5 @@ void main(void) showstr(" -Initialisation du coprocesseur\r\n"); initcoprocessor(); showstr(" -Passage en mode protege\r\n"); - initpmode(0x10000); + initpmode(); } diff --git a/system/system.c b/system/system.c index 22f59a1..ccc19e2 100644 --- a/system/system.c +++ b/system/system.c @@ -15,6 +15,7 @@ #include "shell.h" #include "syscall.h" #include "memory.h" +#include "system.h" static u8 warnmsg[] = "\033[150C\033[8D\033[37m\033[1m[ \033[36mNON\033[37m ]\033[0m"; @@ -59,6 +60,8 @@ int main(u8* info) logo(); print("\033[37m\033[0m -Initilisation de la memoire virtuelle"); + initgdt(&&next); +next: initpaging(); remap_memory(VESA_FBMEM); ok(); diff --git a/system/system.S b/system/system_asm.S similarity index 94% rename from system/system.S rename to system/system_asm.S index 04ea3f4..7ab7bca 100644 --- a/system/system.S +++ b/system/system_asm.S @@ -8,9 +8,8 @@ .code32 .section ".text" .global start +.extern main start: - ljmp $SEL_KERNEL_CODE,$suite -suite: movw $SEL_KERNEL_DATA, %ax movw %ax, %ds movw %ax, %es @@ -26,3 +25,4 @@ suite: xor %esi,%esi xor %edi,%edi xor %ebp,%ebp + call main