diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8f643951dc5bd6130e30be07e804b681a818a60 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +AS := as +LD := ld -m elf_x86_64 + +LDFLAG := -Ttext 0x0 -s --oformat binary + +image : linux.img + +linux.img : tools/build bootsect setup kernel/system + ./tools/build bootsect setup kernel/system > $@ + +tools/build : tools/build.c + gcc -o $@ $< + +kernel/system : + cd kernel; make system; cd .. + +bootsect : bootsect.o + $(LD) $(LDFLAG) -o $@ $< + +bootsect.o : bootsect.S + $(AS) -o $@ $< + +setup : setup.o + $(LD) $(LDFLAG) -e _start_setup -o $@ $< + +setup.o : setup.S + $(AS) -o $@ $< +clean: + rm *.o + rm bootsect + rm setup + rm tools/build + rm linux.img + cd kernel; make clean; cd .. + diff --git a/bootsect.S b/bootsect.S new file mode 100644 index 0000000000000000000000000000000000000000..b3fa63ecd646433a19e47411b2808cb9e7fe4ced --- /dev/null +++ b/bootsect.S @@ -0,0 +1,211 @@ +SYSSIZE = 2426 + +SETUPLEN = 4 + +BOOTSEG = 0x7c0 + +INITSEG = 0x9000 + +SETUPSEG = 0x9020 + +SYSSEG = 0x1000 + +ENDSEG = SYSSEG + SYSSIZE + +ROOT_DEV = 0x000 + +.code16 +.text + +.global _start +_start: + + jmpl $BOOTSEG, $start2 + +start2: + movw $BOOTSEG, %ax + movw %ax, %ds + movw $INITSEG, %ax + movw %ax, %es + movw $256, %cx + subw %si, %si + subw %di, %di + + rep + movsw + + jmpl $INITSEG, $go + +go: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0xFF00, %sp + +load_setup: + movw $0x0000, %dx + movw $0x0002, %cx + movw $0x0200, %bx + movb $0x02, %ah + movb $SETUPLEN, %al + int $0x13 + jnc ok_load_setup + movw $0x0000, %dx + movw $0x0000, %ax + int $0x13 + jmp load_setup + +ok_load_setup: + movb $0x00, %dl + movw $0x0800, %ax + int $0x13 + movb $0x00, %ch + movw %cx, %cs:sectors + movw $INITSEG, %ax + movw %ax, %es + + movw $SYSSEG, %ax + movw %ax, %es + call read_it + call kill_motor + + movw %cs:root_dev, %ax + cmpw $0, %ax + jne root_defined + movw %cs:sectors, %bx + movw $0x0208, %ax + cmpw $15, %bx + je root_defined + movw $0x021c, %ax + cmpw $18, %bx + je root_defined +undef_root: + jmp undef_root +root_defined: + mov %ax, %cs:root_dev + + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + movw $0x600, %ax + movw $0x700, %bx + movw $0x0, %cx + movw $0x184f,%dx + int $0x10 + + movw $msg, %ax + movw %ax, %bp + movw $0x01301, %ax + movw $0x0c, %bx + movw $23, %cx + movw $0, %dx + int $0x010 + + jmpl $SETUPSEG, $0 + +sread: + .word 1+SETUPLEN +head: + .word 0 +track: + .word 0 +read_it: + movw %es, %ax + testw $0x0fff, %ax +die: + jne die + xor %bx, %bx +rp_read: + movw %es, %ax + cmpw $ENDSEG, %ax + jb ok1_read + ret +ok1_read: + movw %cs:sectors, %ax + subw sread, %ax + movw %ax, %cx + shlw $9, %cx + addw %bx, %cx + jnc ok2_read + je ok2_read + xorw %ax, %ax + subw %bx, %ax + shrw $9, %ax +ok2_read: + call read_track + movw %ax, %cx + addw sread, %ax + cmpw %cs:sectors, %ax + jne ok3_read + movw $1, %ax + subw head, %ax + jne ok4_read + incw track +ok4_read: + movw %ax, head + xorw %ax, %ax +ok3_read: + movw %ax, sread + shlw $9, %cx + addw %cx, %bx + jnc rp_read + movw %es, %ax + addw $0x1000, %ax + movw %ax, %es + xorw %bx, %bx + jmp rp_read + +read_track: + pushw %ax + pushw %bx + pushw %cx + pushw %dx + movw track, %dx + movw sread, %cx + incw %cx + movb %dl, %ch + movw head, %dx + movb %dl, %dh + movb $0, %dl + andw $0x0100, %dx + movb $2, %ah + int $0x13 + jc bad_rt + popw %dx + popw %cx + popw %bx + popw %ax + ret +bad_rt: + movw $0x0, %ax + movw $0x0, %dx + int $0x13 + popw %dx + popw %cx + popw %bx + popw %ax + jmp read_track + +kill_motor: + pushw %dx + movw $0x3f2, %dx + movb $0, %al + outb %al, %dx + popw %dx + ret + +sectors: + .word 0 + +msg: +.byte 13, 10 +.ascii "Linux is booting..." +.byte 13, 10 +.org 508 +root_dev: + .word ROOT_DEV +boot_flag: + .word 0xaa55 + diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..01e3c1053b3aea084937954741da1ef48aeb41ab --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,16 @@ +GCC := gcc +CCFLAG := -mcpu=i386 -I../include -nostdinc -Wall -fomit-frame-pointer -c +LDFLAG := -Ttext 0x0 -s --oformat binary +INCDIR := ../include +OBJS := head.o + +system: $(OBJS) + $(LD) $(LDFLAG) -e startup_32 -o $@ $^ + +head.o : head.S + $(GCC) -traditional -c -o $@ $< + +clean : + rm *.o + rm system + diff --git a/kernel/head.S b/kernel/head.S new file mode 100644 index 0000000000000000000000000000000000000000..170f2c34066c1efb7d67af23f1bd782045da33c9 --- /dev/null +++ b/kernel/head.S @@ -0,0 +1,73 @@ +.code32 +.text +.globl startup_32 +startup_32: + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movl $0x18, %eax + movw %ax, %gs + + call setup_idt + int $0x80 + + movl $0x18, %eax + movw %ax, %gs + movl $0x0, %edi + movb $0xf, %ah + movb $0x42, %al + movw %ax, %gs:(%edi) + +loop: + jmp loop + +setup_idt: + leal ignore_int, %edx + movl $0x00080000, %eax + movw %dx, %ax + movw $0x8e00, %dx + leal idt, %edi + movl $256, %ecx +rp_sidt: + movl %eax, (%edi) + movl %edx, 4(%edi) + addl $8, %edi + decl %ecx + jne rp_sidt + lidt idt_descr + ret + +ignore_int: + /* we do not have function _printk now, so trick it */ + pushl %eax + pushl %ecx + pushl %edx + pushw %ds + pushw %es + pushw %fs + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + /* call _printk */ + movl $0x96, %edi + movb $'I', %al + movb $0x0c, %ah + movw %ax, %gs:(%edi) + popw %fs + popw %es + popw %ds + popl %edx + popl %ecx + popl %eax + iret + +.align 4 +.word 0 +idt_descr: + .word 256*8-1 + .long idt + +idt: + .fill 256, 8, 0 diff --git a/setup.S b/setup.S new file mode 100644 index 0000000000000000000000000000000000000000..a30a5dddefa27dd240c1ee8bb247b8d60b9186d0 --- /dev/null +++ b/setup.S @@ -0,0 +1,188 @@ +INITSEG = 0x9000 +SYSSEG = 0x1000 +SETUPSEG = 0x9020 + +.code16 +.text +.globl _start_setup + +_start_setup: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + movw $setup_msg, %ax + movw %ax, %bp + movw $0x01301, %ax + movw $0x0c, %bx + movw $16, %cx + movb $3, %dh + movb $0, %dl + int $0x010 + + movw $INITSEG, %ax + movw %ax, %ds + movb $0x03, %ah + xor %bh, %bh + int $0x10 + movw %dx, (0) + movb $0x88, %ah + int $0x15 + movw %ax, (2) + + movb $0x0f, %ah + int $0x10 + movw %bx, (4) + movw %ax, (6) + movb $0x12, %ah + movb $0x10, %bl + int $0x10 + movw %ax, (8) + movw %bx, (10) + movw %cx, (12) + + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + rep + movsb + + /* get hd1 data */ + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + rep + movsb + + movw $0x1500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + cmpb $3, %ah + je is_disk1 +no_disk1: + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + movw $0x00, %ax + rep + stosb +is_disk1: + /* prepare for protection mode */ + cli + + movw $0x0000, %ax + cld +do_move: + movw %ax, %es + addw $0x1000, %ax + cmpw $0x9000, %ax + jz end_move + movw %ax, %ds + subw %di, %di + subw %si, %si + movw $0x8000, %cx + rep + movsw + jmp do_move + +end_move: + movw $0xb800, %ax + movw %ax, %gs + movb $0xf, %ah + movb $0x41, %al + movl $0x100, %edi + movw %ax, %gs:(%di) + + movw $SETUPSEG, %ax + movw %ax, %ds + lidt idt_48 + lgdt gdt_48 + + call empty_8042 + movb $0xD1, %al + outb %al, $0x64 + call empty_8042 + movb $0xDF, %al + outb %al, $0x60 + call empty_8042 + + movb $0x11, %al + outb %al, $0x20 + .word 0x00eb, 0x00eb + outb %al, $0xA0 + .word 0x00eb, 0x00eb + movb $0x20, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x28, %al + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0x04, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x02, %al + outb %al, $0xA1 + + .word 0x00eb, 0x00eb + movb $0x01, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0xff, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + + movl %cr0, %eax + xorb $1, %al + movl %eax, %cr0 + + .byte 0x66, 0xea + .long 0x0 + .word 0x8 + +empty_8042: + .word 0x00eb, 0x00eb + inb $0x64, %al + testb $2, %al + jnz empty_8042 + ret + +gdt: + .word 0,0,0,0 + + .word 0x07ff + .word 0x0000 + .word 0x9A00 + .word 0x00C0 + + .word 0x07ff + .word 0x0000 + .word 0x9200 + .word 0x00c0 + + .word 0xffff + .word 0x8000 + .word 0x920b + .word 0x00c0 +idt_48: + .word 0 + .word 0,0 +gdt_48: + .word 0x800 + .word 512+gdt, 0x9 + +setup_msg: + .ascii "setup is running" + diff --git a/tools/build.c b/tools/build.c new file mode 100644 index 0000000000000000000000000000000000000000..e321f9f64b88a93c0e413c15d7b065cfb464fa5b --- /dev/null +++ b/tools/build.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MINIX_HEADER 32 +#define GCC_HEADER 1024 + +#define SYS_SIZE 0x2000 + +#define DEFAULT_MAJOR_ROOT 3 +#define DEFAULT_MINOR_ROOT 6 + +#define SETUP_SECTS 4 + +#define STRINGIFY(x) #x + +#define ARG_LEN 4 + +void die(char * str) +{ + fprintf(stderr, "%s\n", str); + exit(1); +} + +void usage(void) +{ + die("Usage: build bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char **argv) +{ + int i, c, id; + char buf[1024]; + char major_root, minor_root; + struct stat sb; + + if ((argc != ARG_LEN) && (argc != ARG_LEN + 1)) + usage(); + + if (argc == ARG_LEN + 1) + { + if (strcmp(argv[ARG_LEN], "FLOPPY")) + { + if (stat(argv[ARG_LEN], &sb)) + { + perror(argv[ARG_LEN]); + die("Couldn't stat root device"); + } + major_root = sb.st_rdev & 0xff00; + minor_root = sb.st_rdev & 0x00ff; + } + else + { + major_root = 0; + minor_root = 0; + } + } + else + { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + if ((major_root != 2) && (major_root != 3) && (major_root != 0)) + { + fprintf(stderr, "Illegal root device (major = %d)\n", major_root); + die("Bad root device --- major #"); + } + + for (i = 0; i < sizeof(buf); i++) + buf[i] = 0; + + if ((id = open(argv[1], O_RDONLY, 0)) < 0) + die("Unable to open 'boot'"); + + i = read(id, buf, sizeof(buf)); + fprintf(stderr, "Boot sector %d bytes.\n", i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); + + buf[508] = (char) minor_root; + buf[509] = (char) major_root; + i = write(1, buf, 512); + if (i != 512) + die("Write call failed"); + close(id); + + if ((id = open(argv[2], O_RDONLY, 0)) < 0) + die("Unable to open 'setup'"); + + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + + close(id); + + if (i > SETUP_SECTS * 512) + die("Setup exceeds" STRINGIFY(SETUP_SECTS) " sectors - rewrite build/boot/setup"); + fprintf(stderr, "Setup is %d bytes.\n", i); + for (c = 0; c < sizeof(buf); c++) + buf[c] ='\0'; + while (i < SETUP_SECTS * 512) + { + c = SETUP_SECTS * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + + if (write(1, buf, c) != c) + die("Write call failed"); + i+=c; + } + + if ((id = open(argv[3], O_RDONLY, 0)) < 0) + die("Unable to open 'system'"); + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + close(id); + fprintf(stderr, "System is %d bytes.\n", i); + if (i > SYS_SIZE * 16) + die("System is too big"); + + return 0; +} +