From 32af566aece9d9a06756522a9edff90fcd0e8532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Hord=C3=A9?= Date: Tue, 1 Jan 2019 13:30:06 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20ajout=20de=20mkpiggy=20du=20noyau=20Lin?= =?UTF-8?q?ux=20et=20mise=20en=20place=20d'un=20noyau=20composite=20bas?= =?UTF-8?q?=C3=A9=20sur=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/gdt.h | 11 +- include/memory.h | 9 +- lib/gdt.c | 89 +++------- system/makefile | 40 +++-- system/realmode/makefile | 2 +- system/realmode/setup.S | 365 +++++++++++++++++++++++++++++++++++++++ system/realmode/setup.c | 146 +++++++++++++++- system/system.S | 30 ++++ system/system.c | 3 - system/system.ld | 6 +- tools/makefile | 2 +- tools/mkpiggy.c | 82 +++++++++ 12 files changed, 688 insertions(+), 97 deletions(-) create mode 100644 system/system.S create mode 100644 tools/mkpiggy.c diff --git a/include/gdt.h b/include/gdt.h index 92393e1..3b9a508 100644 --- a/include/gdt.h +++ b/include/gdt.h @@ -1,5 +1,3 @@ -#include - /* Ordre imposé par SYSENTER */ #define SEL_KERNEL_CODE 0x8 /* Selecteur code du kernel */ #define SEL_KERNEL_STACK 0x10 /* Selecteur pile du kernel */ @@ -7,7 +5,6 @@ #define SEL_USER_STACK 0x20 /* Selecteur pile utilisateur */ #define SEL_KERNEL_DATA 0x28 /* Selecteur data du kernel */ #define SEL_USER_DATA 0x30 /* Selecteur data utilisateur */ - #define SEL_TSS 0x38 /* Selecteur TSR */ #define GDT_SIZE 0x8 /* Nombre de descripteurs */ @@ -39,6 +36,10 @@ #define SEG_NORMAL 0b00010000 /* Segment normal pile/data/code (0 pour système) */ +#ifndef _ASSEMBLY + +#include "types.h" + typedef struct gdtdes { u16 lim0_15; @@ -78,7 +79,7 @@ typedef struct tss } __attribute__ ((packed)); void inittr(void); -void initgdt(u32 offset); +void initgdt(); void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes * desc); u32 getdesbase(u16 sel); @@ -90,3 +91,5 @@ u8 getdesbit3(u16 sel); u32 getdesdpl(u16 sel); u16 getdesalign(u16 sel); void setTSS(u32 ss, u32 sp); + +#endif diff --git a/include/memory.h b/include/memory.h index cb7c673..1fe8596 100644 --- a/include/memory.h +++ b/include/memory.h @@ -1,9 +1,6 @@ /*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ -#include "types.h" -#include "queue.h" - #ifndef _MEMORY # define _MEMORY @@ -66,6 +63,11 @@ # define setCR3(addr) \ asm volatile ("mov %[memaddr], %%eax; mov %%eax, %%cr3"::[memaddr] "m" (addr) ); +#ifndef _ASSEMBLY + +#include "types.h" +#include "queue.h" + /* Malloc, pour l'attribution de mémoire en heap */ typedef struct tmalloc { @@ -138,3 +140,4 @@ typedef TAILQ_HEAD(page_s, page) page_t; u32 virtual_getpagesfree(); #endif +#endif diff --git a/lib/gdt.c b/lib/gdt.c index 5ef9389..899e7f3 100644 --- a/lib/gdt.c +++ b/lib/gdt.c @@ -6,44 +6,31 @@ #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; /*******************************************************************************/ -/* Initialise la GDT */ +/* Initialise les selecteurs avec la GDT */ -void initgdt(u32 offset) +void initselectors(u32 executingoffset) { - 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); + asm(" 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"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset)); } /*******************************************************************************/ @@ -51,6 +38,10 @@ void initgdt(u32 offset) void setTSS(u32 ss, u32 sp) { + + tss0.trapflag = 0x00; + tss0.iomap = 0x00; + tss0.ss0 = SEL_TSS; tss0.esp0 = sp; tss0.ss0 = ss; } @@ -63,26 +54,6 @@ void inittr(void) ltr(SEL_TSS); } -/*******************************************************************************/ -/* Initialise les selecteurs avec la GDT */ - -void initselectors(u32 executingoffset) -{ - asm(" 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 \ - ljmp %[code], $raz \n \ - raz: \n \ - pushl %%ebx \n \ - ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset)); -} - /*******************************************************************************/ /* récupère la base d'un descripteur GDT */ @@ -212,17 +183,3 @@ u32 getdessize(u16 sel) else return (((entry[index].flags & 0x08) > 0) ? 32 : 16); } -/*******************************************************************************/ -/* 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; -} diff --git a/system/makefile b/system/makefile index 1629084..6d6573a 100755 --- a/system/makefile +++ b/system/makefile @@ -1,36 +1,56 @@ GCC=gcc -O0 -g -nostdinc -ffreestanding -fno-builtin -Wall -w -I ../include -m32 -fno-pie -no-pie -c -o -ASM=gcc -nostdinc -ffreestanding -fno-builtin -m32 -c -fno-pie -no-pie -LINK=ld -m elf_i386 -n -o +ASM=gcc -nostdinc -ffreestanding -fno-builtin -m32 -c -fno-pie -no-pie -I ../include -c -o +LINK=ld -m elf_i386 -n CONVERT=dos2unix INDENT=indent -nhnl -l75 -ppi3 -ts8 -bls -nbc -di8 -nbad -nbap -nsob -i8 -bl -bli0 -ncdw -nce -cli8 -cbi0 -npcs -cs -saf -sai -saw -nprs -lp -npsl REMOVE=rm -f CHANGEPERM=chmod 644 NM=nm -ZOFFSET=sed -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' -VOFFSET=sed -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p' +OBJCOPY=objcopy -O binary -R .note -R .comment -S +ZOFFSET=sed -n -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' +VOFFSET=sed -n -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p' +COMP=gzip -5 all: system.sys -system.sys: realmode/setup.bin system.bin - $(NM) system.bin|$VOFFSET>voffset.h - $(NM) setup.bin|$ZOFFSET>zoffset.h +system.sys: system.bin voffset.h zoffset.h realmode/setup.bin tools/build setup.bin system.bin zoffset.h system.sys sync +voffset.h: system + $(NM) system|$(VOFFSET)>voffset.h + +zoffset.h: system + $(NM) system|$(ZOFFSET)>zoffset.h + togit: clean indent -system.bin: system.o ../lib/libs.o +system: systemc.o system.o ../lib/libs.o $(LINK) -T system.ld system.o ../lib/libs.o +system.bin: system + $(OBJCOPY) $^ $@ + +system.bin.gz: system.bin + cat $^|$(COMP) > $@ + +piggy.s: system.bin.gz + realmode/setup.bin: make -C realmode -system.o: +systemc.o: system.c $(GCC) $@ $^ +system.o: system.S + $(ASM) $@ $^ + clean: - make -C realmode clean + make -C realmode clean + $(REMOVE) system $(REMOVE) *.o + $(REMOVE) *.gz + $(REMOVE) *.h $(REMOVE) *.out $(REMOVE) *.bin $(REMOVE) *.sys diff --git a/system/realmode/makefile b/system/realmode/makefile index cc0b945..313d537 100644 --- a/system/realmode/makefile +++ b/system/realmode/makefile @@ -1,6 +1,6 @@ GCC=gcc -O0 -g -nostdinc -ffreestanding -fno-builtin -Wall -w -I ../../include -m16 -fomit-frame-pointer -fno-pic -mno-mmx -mno-sse -mno-80387 -mno-fp-ret-in-387 -c -o ASM=gcc -nostdinc -ffreestanding -fno-builtin -m16 -fomit-frame-pointer -fno-pic -mno-mmx -mno-sse -mno-80387 -mno-fp-ret-in-387 -c -o -LINK=ld -m elf_i386 -n -o +LINK=ld -m elf_i386 -n CONVERT=dos2unix INDENT=indent -nhnl -l75 -ppi3 -ts8 -bls -nbc -di8 -nbad -nbap -nsob -i8 -bl -bli0 -ncdw -nce -cli8 -cbi0 -npcs -cs -saf -sai -saw -nprs -lp -npsl REMOVE=rm -f diff --git a/system/realmode/setup.S b/system/realmode/setup.S index ed6bd64..fbd181f 100644 --- a/system/realmode/setup.S +++ b/system/realmode/setup.S @@ -1,3 +1,368 @@ /*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ +/* Modifié depuis header.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Based on bootsect.S and setup.S + * modified by more people than can be counted + * + * Rewritten as a common file by H. Peter Anvin (Apr 2007) + * + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment + * addresses must be multiplied by 16 to obtain their respective linear + * addresses. To avoid confusion, linear addresses are written using leading + * hex while segment addresses are written as segment:offset. + * + */ + +#include "voffset.h" +#include "zoffset.h" + +SEGBOOT = 0x07C0 +SEGSYS = 0x1000 +STACK_SIZE = 1024 + + .code16 + .section ".bstext", "ax" + + .global bootsectstart +bootsectstart: + ljmp $SEGBOOT, $start2 + +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + xorw %sp, %sp + sti + cld + movw $msgtxt, %si +msg: + lodsb + andb %al, %al + jz dienow + movb $0xe, %ah + movw $7, %bx + int $0x10 + jmp msg +dienow: + xorw %ax, %ax + int $0x16 + int $0x19 + ljmp $0xf000,$0xfff0 + .section ".bsdata", "a" +msgtxt: + .ascii "Utilisez un chargeur de demarrage !\r\n\r\n" + .byte 0 + + .section ".header", "a" + .globl sentinel +sentinel: .byte 0xff, 0xff + + .globl hdr +hdr: +setup_sects: .byte 0 /* Filled in by build.c */ +root_flags: .word ROOT_RDONLY +syssize: .long 0 /* Filled in by build.c */ +ram_size: .word 0 /* Obsolete */ +vid_mode: .word SVGA_MODE +root_dev: .word 0 /* Filled in by build.c */ +boot_flag: .word 0xAA55 + + # offset 512, entry point + + .globl _start +_start: + .byte 0xeb # short (2-byte) jump + .byte setup-1f +1: + .ascii "HdrS" # header signature + .word 0x020d # header version number (>= 0x0105) or else old loadlin-1.5 will fail) + .globl realmode_swtch +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word SEGSYS # obsolete and meaningless, but just + # in case something decided to "use" it + .word kernel_version-512 # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). Don't + # change it. + +type_of_loader: .byte 0 # 0 means ancient bootloader, newer + # bootloaders know to change this. + # See Documentation/x86/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: + .byte LOADED_HIGH # The kernel is to be loaded high + +setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup + # to 0x90000 then just before jumping + # into the kernel. However, only the + # loader knows how much data behind + # us also needs to be loaded. + +code32_start: # here loaders can put a different + # start address for 32-bit code. + .long 0x100000 # 0x100000 = default for big kernel + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .long 0 # obsolete + +heap_end_ptr: .word _end+STACK_SIZE-512 + # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +ext_loader_ver: + .byte 0 # Extended boot loader version +ext_loader_type: + .byte 0 # Extended boot loader type + +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +initrd_addr_max: .long 0x7fffffff + # (Header version 0x0203 or later) + # The highest safe address for + # the contents of an initrd + # The current kernel allows up to 4 GB, + # but leave it at 2 GB to avoid + # possible bootloader bugs. + +kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment + #required for protected mode + #kernel +relocatable_kernel: .byte 0 +min_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment + +xloadflags: + .word 0 +cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, + #added with boot protocol + #version 2.06 + +hardware_subarch: .long 0 # subarchitecture, added with 2.07 + # default to 0 for normal x86 PC +hardware_subarch_data: .quad 0 +payload_offset: .long ZO_input_data +payload_length: .long ZO_z_input_len +setup_data: .quad 0 # 64-bit physical pointer to + # single linked list of + # struct setup_data + +pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr + +# +# Getting to provably safe in-place decompression is hard. Worst case +# behaviours need to be analyzed. Here let's take the decompression of +# a gzip-compressed kernel as example, to illustrate it: +# +# The file layout of gzip compressed kernel is: +# +# magic[2] +# method[1] +# flags[1] +# timestamp[4] +# extraflags[1] +# os[1] +# compressed data blocks[N] +# crc[4] orig_len[4] +# +# ... resulting in +18 bytes overhead of uncompressed data. +# +# (For more information, please refer to RFC 1951 and RFC 1952.) +# +# Files divided into blocks +# 1 bit (last block flag) +# 2 bits (block type) +# +# 1 block occurs every 32K -1 bytes or when there 50% compression +# has been achieved. The smallest block type encoding is always used. +# +# stored: +# 32 bits length in bytes. +# +# fixed: +# magic fixed tree. +# symbols. +# +# dynamic: +# dynamic tree encoding. +# symbols. +# +# +# The buffer for decompression in place is the length of the uncompressed +# data, plus a small amount extra to keep the algorithm safe. The +# compressed data is placed at the end of the buffer. The output pointer +# is placed at the start of the buffer and the input pointer is placed +# where the compressed data starts. Problems will occur when the output +# pointer overruns the input pointer. +# +# The output pointer can only overrun the input pointer if the input +# pointer is moving faster than the output pointer. A condition only +# triggered by data whose compressed form is larger than the uncompressed +# form. +# +# The worst case at the block level is a growth of the compressed data +# of 5 bytes per 32767 bytes. +# +# The worst case internal to a compressed block is very hard to figure. +# The worst case can at least be bounded by having one bit that represents +# 32764 bytes and then all of the rest of the bytes representing the very +# very last byte. +# +# All of which is enough to compute an amount of extra data that is required +# to be safe. To avoid problems at the block level allocating 5 extra bytes +# per 32767 bytes of data is sufficient. To avoid problems internal to a +# block adding an extra 32767 bytes (the worst case uncompressed block size) +# is sufficient, to ensure that in the worst case the decompressed data for +# block will stop the byte before the compressed data for a block begins. +# To avoid problems with the compressed data's meta information an extra 18 +# bytes are needed. Leading to the formula: +# +# extra_bytes = (uncompressed_size >> 12) + 32768 + 18 +# +# Adding 8 bytes per 32K is a bit excessive but much easier to calculate. +# Adding 32768 instead of 32767 just makes for round numbers. +# +# Above analysis is for decompressing gzip compressed kernel only. Up to +# now 6 different decompressor are supported all together. And among them +# xz stores data in chunks and has maximum chunk of 64K. Hence safety +# margin should be updated to cover all decompressors so that we don't +# need to deal with each of them separately. Please check +# the description in lib/decompressor_xxx.c for specific information. +# +# extra_bytes = (uncompressed_size >> 12) + 65536 + 128 +# +# LZ4 is even worse: data that cannot be further compressed grows by 0.4%, +# or one byte per 256 bytes. OTOH, we can safely get rid of the +128 as +# the size-dependent part now grows so fast. +# +# extra_bytes = (uncompressed_size >> 8) + 65536 + +#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 65536) +#if ZO_z_output_len > ZO_z_input_len +# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \ + ZO_z_input_len) +#else +# define ZO_z_extract_offset ZO_z_extra_bytes +#endif + +/* + * The extract_offset has to be bigger than ZO head section. Otherwise when + * the head code is running to move ZO to the end of the buffer, it will + * overwrite the head code itself. + */ +#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset +# define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095) +#else +# define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095) +#endif + +#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset) + +#define VO_INIT_SIZE (VO__end - VO__text) +#if ZO_INIT_SIZE > VO_INIT_SIZE +# define INIT_SIZE ZO_INIT_SIZE +#else +# define INIT_SIZE VO_INIT_SIZE +#endif + +init_size: .long INIT_SIZE # kernel initialization size +handover_offset: .long 0 # Filled in by build.c + +# End of setup header ##################################################### + + .section ".entrytext", "ax" +setup: +# Force %es = %ds + movw %ds, %ax + movw %ax, %es + cld + movw %ss, %dx + cmpw %ax, %dx # %ds == %ss? + movw %sp, %dx + je 2f # -> assume %sp is reasonably set + + # Invalid %ss, make up a new stack + movw $_end, %dx + testb $CAN_USE_HEAP, loadflags + jz 1f + movw heap_end_ptr, %dx +1: addw $STACK_SIZE, %dx + jnc 2f + xorw %dx, %dx # Prevent wraparound + +2: # Now %dx should point to the end of our stack space + andw $~3, %dx # dword align (might as well...) + jnz 3f + movw $0xfffc, %dx # Make sure we're not zero +3: movw %ax, %ss + movzwl %dx, %esp # Clear upper half of %esp + sti # Now we should have a working stack + +# We will have entered with %cs = %ds+0x20, normalize %cs so +# it is on par with the other segments. + pushw %ds + pushw $6f + lretw +6: + +# Check signature at end of setup + cmpl $0x5a5aaa55, setup_sig + jne setup_bad + +# Zero the bss + movw $__bss_start, %di + movw $_end+3, %cx + xorl %eax, %eax + subw %di, %cx + shrw $2, %cx + rep; stosl + +# Jump to C code (should not return) + calll main + +# Setup corrupt somehow... +setup_bad: + movl $setup_corrupt, %eax + calll puts + # Fall through... + + .globl die + .type die, @function +die: + hlt + jmp die + + .size die, .-die + + .section ".initdata", "a" +setup_corrupt: + .byte 7 + .string "Signature du systeme non trouvee...\n" diff --git a/system/realmode/setup.c b/system/realmode/setup.c index f579f49..19227f8 100644 --- a/system/realmode/setup.c +++ b/system/realmode/setup.c @@ -4,6 +4,8 @@ #include "types.h" #include "asm.h" #include "setup.h" +#include "gdt.h" +#include "memory.h" struct params { entrye820 *e820_table; @@ -11,7 +13,14 @@ struct params { u8 kbflag; } params; + /* registre gdt */ +static struct gdtr gdtreg; + +/* table de GDT */ +static gdtdes gdt[GDT_SIZE]; + #define EFLAGS_CF 0x00000001 +#define CR0_PE 0x00000001 #define LOOPS_8042 100000 #define FF_8042 32 #define LOOPS_A20_ENABLE 255 @@ -205,13 +214,142 @@ u8 enableA20(void) 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) +{ + u8 *s = (u8 *) src; + u8 *d = (u8 *) dst; + if (size > 0) + size--; + for (; count != 0; count--) + { + *(d++) = *(s++); + d += size; + } +} + + +/*******************************************************************************/ +/* Initialise les selecteurs avec la GDT */ + +void initselectors(u32 executingoffset) +{ + asm(" movl %%cr0, %%eax \n \ + orb $CR0_PE, %%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"::[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 */ + +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() +{ + 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 */ + makegdtdes(0x0, 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); +} + +void maskinterrupts(void) +{ + cli(); + outb(0x80, 0x70); /* Disable NMI */ + iodelay(); + outb(0xff, 0xa1); /* Mask all interrupts on the secondary PIC */ + idelay(); + outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */ + iodelay(); +} + +void initcoprocessor(void) +{ + outb(0, 0xf0); + iodelay(); + outb(0, 0xf1); + iodelay(); +} + +void initpmode(u32 offset) +{ + if (enableA20()) { + showstr("impossible d'ouvrir la ligne A20...\n"); + hlt(); + } + maskinterrupts(); + initgdt(); + initselectors(offset); +} + void main(void) { showstr("Chargement de COS2000 - mode reel"); - initparams(); - initheap(); + /* initparams(); */ initmemory(); initkeyboard(); - initvideo(); - initpmode(); + /* initvideo(); */ + initcoprocessor(); + initpmode(0x10000); } diff --git a/system/system.S b/system/system.S new file mode 100644 index 0000000..832063a --- /dev/null +++ b/system/system.S @@ -0,0 +1,30 @@ +/*******************************************************************************/ +/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ +/* */ + +#define _ASSEMBLY + +#include "memory.h" +#include "gdt.h" + +.code32 +.section ".text" +.global startup_32 +startup_32: + ljmp SEL_KERNEL_CODE,$suite +suite: + movw SEL_KERNEL_DATA, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw SEL_KERNEL_STACK, %ax + movw %ax, %ss + movl KERNEL_STACK_ADDR, %esp + xor %eax,%eax + xor %ebx,%ebx + xor %ecx,%ecx + xor %edx,%edx + xor %esi,%esi + xor %edi,%edi + xor %ebp,%ebp diff --git a/system/system.c b/system/system.c index ba38d80..22f59a1 100644 --- a/system/system.c +++ b/system/system.c @@ -14,7 +14,6 @@ #include "gdt.h" #include "shell.h" #include "syscall.h" -#include "multiboot2.h" #include "memory.h" static u8 warnmsg[] = @@ -60,8 +59,6 @@ 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.ld b/system/system.ld index c1143fc..c1bdb87 100644 --- a/system/system.ld +++ b/system/system.ld @@ -1,16 +1,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) -OUPUT(system.bin) +OUTPUT(system) ENTRY(start) SECTIONS { . = 0x100000; - .boot ALIGN(8) : - { - *(.multiboot) - } .text ALIGN(16): { *(.text) } diff --git a/tools/makefile b/tools/makefile index 70832f5..04c0792 100755 --- a/tools/makefile +++ b/tools/makefile @@ -1,4 +1,4 @@ -CC=gcc -I . -o +CC=gcc -DCONFIG_X86_32 -I . -o SRCS= $(wildcard *.c) EXECS= $(SRCS:.c=) CONVERT=dos2unix diff --git a/tools/mkpiggy.c b/tools/mkpiggy.c new file mode 100644 index 0000000..ab7b9f6 --- /dev/null +++ b/tools/mkpiggy.c @@ -0,0 +1,82 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * H. Peter Anvin + * + * ----------------------------------------------------------------------- + * + * Outputs a small assembly wrapper with the appropriate symbols defined. + * + */ + +#include +#include +#include +#include +#include <./le_byteshift.h> + +int main(int argc, char *argv[]) +{ + uint32_t olen; + long ilen; + FILE *f = NULL; + int retval = 1; + + if (argc < 2) { + fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); + goto bail; + } + + /* Get the information for the compressed kernel image first */ + + f = fopen(argv[1], "r"); + if (!f) { + perror(argv[1]); + goto bail; + } + + + if (fseek(f, -4L, SEEK_END)) { + perror(argv[1]); + } + + if (fread(&olen, sizeof(olen), 1, f) != 1) { + perror(argv[1]); + goto bail; + } + + ilen = ftell(f); + olen = get_unaligned_le32(&olen); + + printf(".section \".rodata..compressed\",\"a\",@progbits\n"); + printf(".globl z_input_len\n"); + printf("z_input_len = %lu\n", ilen); + printf(".globl z_output_len\n"); + printf("z_output_len = %lu\n", (unsigned long)olen); + + printf(".globl input_data, input_data_end\n"); + printf("input_data:\n"); + printf(".incbin \"%s\"\n", argv[1]); + printf("input_data_end:\n"); + + retval = 0; +bail: + if (f) + fclose(f); + return retval; +}