diff --git a/include/setup.h b/include/setup.h new file mode 100644 index 0000000..12130ef --- /dev/null +++ b/include/setup.h @@ -0,0 +1,41 @@ +/*******************************************************************************/ +/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ +/* */ +#include "types.h" + +typedef struct entrye820 { + u64 addr; + u64 size; + u32 type; +} entrye820 __attribute__((packed)); + +typedef struct miniregs { + union { + struct { + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; + u32 esi; + u32 edi; + u32 ebp; + u32 eflags; + }; + struct { + u16 ax, hax; + u16 bx, hbx; + u16 cx, hcx; + u16 dx, hdx; + u16 si, hsi; + u16 di, hdi; + u16 bp, hbp; + u16 flags, hflags; + }; + struct { + u8 bl, bh, hbx2, hbx3; + u8 dl, dh, hdx2, hdx3; + u8 cl, ch, hcx2, hcx3; + u8 al, ah, hax2, hax3; + }; + }; +} miniregs __attribute__ ((packed)); diff --git a/system/makefile b/system/makefile index e4519e3..1629084 100755 --- a/system/makefile +++ b/system/makefile @@ -1,34 +1,35 @@ GCC=gcc -O0 -g -nostdinc -ffreestanding -fno-builtin -Wall -w -I ../include -m32 -fno-pie -no-pie -c -o -GCCREAL=gcc -O0 -g -nostdinc -ffreestanding -fno-builtin -Wall -w -I ../include -m16 -fomit-frame-pointer -fno-pic -mno-mmx -mno-sse -mstack-alignment=4 -mno-80387 -mno-fp-ret-in-387 -c -o ASM=gcc -nostdinc -ffreestanding -fno-builtin -m32 -c -fno-pie -no-pie LINK=ld -m elf_i386 -n -o 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' all: system.sys -system.sys: setup.bin system.bin +system.sys: realmode/setup.bin system.bin + $(NM) system.bin|$VOFFSET>voffset.h + $(NM) setup.bin|$ZOFFSET>zoffset.h tools/build setup.bin system.bin zoffset.h system.sys sync togit: clean indent system.bin: system.o ../lib/libs.o - $(LINK) -T linker.lds multiboot.o system.o ../lib/libs.o + $(LINK) -T system.ld system.o ../lib/libs.o -setup.bin: setup.o - $(LINK) $@ $^ - $(OBJDUMP) - -setup.o: - $(GCCREAL) $@ $^ +realmode/setup.bin: + make -C realmode system.o: $(GCC) $@ $^ clean: + make -C realmode clean $(REMOVE) *.o $(REMOVE) *.out $(REMOVE) *.bin @@ -38,6 +39,7 @@ clean: sync indent: + make -C realmode indent $(CHANGEPERM) *.c $(CONVERT) *.c $(INDENT) *.c diff --git a/system/realmode/makefile b/system/realmode/makefile new file mode 100644 index 0000000..cc0b945 --- /dev/null +++ b/system/realmode/makefile @@ -0,0 +1,36 @@ +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 +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 + +all: setup.bin + sync + +setup.bin: setupc.o setup.o + $(LINK) -T setup.ld setupc.o setup.o + $(OBJDUMP) + +setupc.o: setup.c + $(GCC) $@ $^ + +setup.o: setup.S + $(ASM) $@ $^ + +clean: + $(REMOVE) *.o + $(REMOVE) *.out + $(REMOVE) *.bin + $(REMOVE) *.sys + $(REMOVE) *.s + $(REMOVE) *.c~ + sync + +indent: + $(CHANGEPERM) *.c + $(CONVERT) *.c + $(INDENT) *.c + $(REMOVE) *.c~ + sync diff --git a/system/realmode/setup.S b/system/realmode/setup.S new file mode 100644 index 0000000..ed6bd64 --- /dev/null +++ b/system/realmode/setup.S @@ -0,0 +1,3 @@ +/*******************************************************************************/ +/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ +/* */ diff --git a/system/realmode/setup.c b/system/realmode/setup.c new file mode 100644 index 0000000..f579f49 --- /dev/null +++ b/system/realmode/setup.c @@ -0,0 +1,217 @@ +/*******************************************************************************/ +/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ +/* */ +#include "types.h" +#include "asm.h" +#include "setup.h" + +struct params { + entrye820 *e820_table; + u32 e820_numbers; + u8 kbflag; +} params; + +#define EFLAGS_CF 0x00000001 +#define LOOPS_8042 100000 +#define FF_8042 32 +#define LOOPS_A20_ENABLE 255 +#define LOOPS_DELAY 32768 +#define SMAP 0x534d4150 + +#define interrupt(num, regs) ({\ + asm("pushal\n\ + mov %[eflagsregs],%%eax\n\ + pushl %%eax\n\ + popfl\n\ + mov %[eaxregs],%%eax\n\ + mov %[ebxregs],%%ebx\n\ + mov %[ecxregs],%%ecx\n\ + mov %[edxregs],%%edx\n\ + mov %[esiregs],%%esi\n\ + mov %[ediregs],%%edi\n\ + mov %[ebpregs],%%ebp\n\ + int %[numregs]\n\ + pushfl\n\ + popl %%eax\n\ + mov %%eax,%[eflagsregs]\n\ + mov %%eax,%[eaxregs]\n\ + mov %%ebx,%[ebxregs]\n\ + mov %%ecx,%[ecxregs]\n\ + mov %%edx,%[edxregs]\n\ + mov %%esi,%[esiregs]\n\ + mov %%edi,%[ediregs]\n\ + mov %%ebp,%[ebpregs]\n\ + popal":[eaxregs] "+m" (regs.eax),[ebxregs] "+m" (regs.ebx),[ecxregs] "+m" (regs.ecx),[edxregs] "+m" (regs.edx),[esiregs] "+m" (regs.esi),[ediregs] "+m" (regs.edi),[ebpregs] "+m" (regs.ebp),[eflagsregs] "+m" (regs.eflags):[numregs] "i" (num):);}) + + +u8 initmemory(void) +{ + u32 count = 0; + miniregs reg; + entrye820 *desc = params.e820_table; + static struct entrye820 buf; + do { + reg.ax = 0xe820; + reg.cx = sizeof(buf); + reg.edx = SMAP; + reg.di = &buf; + interrupt(0x15, reg); + if (reg.eflags & EFLAGS_CF) + break; + if (reg.eax != SMAP) + { + count = 0; + break; + } + *desc++ = buf; + count++; + } while (reg.ebx && count < ARRAY_SIZE(params.e820_table)); + return params.e820_numbers= count; +} + +void showchar(u8 achar) +{ + miniregs reg; + reg.bx = 0x0007; + reg.cx = 0x0001; + reg.ah = 0x0e; + reg.al = achar; + interrupt(0x10, reg); /* INT 10 - VIDEO - TELETYPE OUTPUT */ +} + +void showstr(u8 *str) +{ + while (*str!='\000') + showchar(*str++); +} + +u8 gettime(void) +{ + miniregs reg; + reg.ah = 0x02; + interrupt(0x1a, reg); /* TIME - GET REAL-TIME CLOCK TIME (AT,XT286,PS) */ + return reg.dh; +} + +u8 waitchar(void) +{ + miniregs reg; + reg.ah = 0x00; + interrupt(0x16, reg); /* INT 16 - KEYBOARD - GET KEYSTROKE */ + return reg.al; +} + +void initkeyboard(void) +{ + miniregs reg; + reg.ah = 0x02; + interrupt(0x16, reg); /* INT 16 - KEYBOARD - GET SHIFT FLAGS */ + params.kbflag=reg.al; + reg.ah = 0x03; + reg.al = 0x05; + reg.bx = 0x00; + interrupt(0x16, reg); /* INT 16 - KEYBOARD - SET TYPEMATIC RATE AND DELAY */ +} + +u8 empty8042(void) +{ + u8 status; + u32 loops = LOOPS_8042; + u8 ffs = FF_8042; + while (loops--) { + iodelay(); + status = inb(0x64); + if (status == 0xff) { + if (!--ffs) + return NULL; + } + if (status & 1) { + io_delay(); + (void)inb(0x60); + } else if (!(status & 2)) { + return 1; + } + } + return NULL; +} + +void iodelay(void) +{ + //asm("outb %%al,$0x80" ::); + for(u32 loop=LOOPS_DELAY;loop>0;loop--) nop(); +} + + +u8 testA20(void) +{ + asm("xorw %%cx, %%cx\n\ + decw %%cx\n\ + movw %%cx, %%gs\n\ + movw $0x4000, %%cx\n\ + movw %%fs:(0x200), %%ax\n\ + pushw %%ax\n\ + 1:\n\ + incw %%ax\n\ + movw %%ax, %%fs:(0x200)\n\ + call iodelay\n\ + cmpw %%gs:(0x210), %%ax\n\ + loope 1b\n\ + popw %%fs:(0x200)\n\ + xor %%ax,%%ax\n\ + je 2f\n\ + mov $0x1,%%ax\n\ + 2:":::"ax","cx"); +} + +void enableA20kbc(void) +{ + empty8042(); + outb(0xd1, 0x64); + empty8042(); + outb(0xdf, 0x60); + empty8042(); + outb(0xff, 0x64); + empty8042(); +} + +void enableA20fast(void) +{ + u8 port; + port = inb(0x92); + port |= 0x02; + port &= ~0x01; + outb(port, 0x92); +} + +u8 enableA20(void) +{ + int loops = LOOPS_A20_ENABLE; + int kbcerr; + while (loops--) { + if (testA20()) + return 1; + kbcerr = empty8042(); + if (testA20()) + return 1; + if (!kbcerr) { + enableA20kbc(); + if (testA20()) + return 1; + } + enableA20fast(); + if (testA20()) + return NULL; + } + return 1; +} + +void main(void) +{ + showstr("Chargement de COS2000 - mode reel"); + initparams(); + initheap(); + initmemory(); + initkeyboard(); + initvideo(); + initpmode(); +} diff --git a/system/realmode/setup.ld b/system/realmode/setup.ld new file mode 100644 index 0000000..96a6c75 --- /dev/null +++ b/system/realmode/setup.ld @@ -0,0 +1,64 @@ +/* + * setup.ld + * + * Linker script for the i386 setup code + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{ + . = 0; + .bstext : { *(.bstext) } + .bsdata : { *(.bsdata) } + + . = 495; + .header : { *(.header) } + .entrytext : { *(.entrytext) } + .inittext : { *(.inittext) } + .initdata : { *(.initdata) } + __end_init = .; + + .text : { *(.text) } + .text32 : { *(.text32) } + + . = ALIGN(16); + .rodata : { *(.rodata*) } + + .videocards : { + video_cards = .; + *(.videocards) + video_cards_end = .; + } + + . = ALIGN(16); + .data : { *(.data*) } + + .signature : { + setup_sig = .; + LONG(0x5a5aaa55) + } + + + . = ALIGN(16); + .bss : + { + __bss_start = .; + *(.bss) + __bss_end = .; + } + . = ALIGN(16); + _end = .; + + /DISCARD/ : { *(.note*) } + + /* + * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility: + */ + . = ASSERT(_end <= 0x8000, "Setup too big!"); + . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); + /* Necessary for the very-old-loader check to work... */ + . = ASSERT(__end_init <= 5*512, "init sections too big!"); + +} diff --git a/system/linker.lds b/system/system.ld similarity index 100% rename from system/linker.lds rename to system/system.ld