📄 startmpcc.s
字号:
/* #defines because ljmp wants a number, probably gas bug *//* .equ KERN_CODE_SEG,_pmcs-_gdt */#define KERN_CODE_SEG 0x08 .equ KERN_DATA_SEG,_pmds-_gdt/* .equ REAL_CODE_SEG,_rmcs-_gdt */#define REAL_CODE_SEG 0x18 .equ REAL_DATA_SEG,_rmds-_gdt .equ CR0_PE,1#ifdef GAS291#define DATA32 data32;#define ADDR32 addr32;#define LJMPI(x) ljmp x#else#define DATA32 data32#define ADDR32 addr32/* newer GAS295 require #define LJMPI(x) ljmp *x */#define LJMPI(x) ljmp x#endif#define PIC1_VBS 0x08 /* PIC1 interrupts start at vector 64 */#define PIC2_VBS 0x70 /* PIC1 interrupts start at vector 112 *//* * NOTE: if you write a subroutine that is called from C code (gcc/egcs), * then you only have to take care of %ebx, %esi, %edi and %ebp. These * registers must not be altered under any circumstance. All other registers * may be clobbered without any negative side effects. If you don't follow * this rule then you'll run into strange effects that only occur on some * gcc versions (because the register allocator may use different registers). * * All the data32 prefixes for the ljmp instructions are necessary, because * the assembler emits code with a relocation address of 0. This means that * all destinations are initially negative, which the assembler doesn't grok, * because for some reason negative numbers don't fit into 16 bits. The addr32 * prefixes are there for the same reasons, because otherwise the memory * references are only 16 bit wide. Theoretically they are all superfluous. * One last note about prefixes: the data32 prefixes on all call _real_to_prot * instructions could be removed if the _real_to_prot function is changed to * deal correctly with 16 bit return addresses. I tried it, but failed. *//**************************************************************************START - Where all the fun begins....**************************************************************************//* this must be the first thing in the file because we enter from the top */ .global _start .code32_start: cli /* load new IDT and GDT */ lgdt gdtarg lidt Idt_Reg /* flush prefetch queue, and reload %cs:%eip */ ljmp $KERN_CODE_SEG,$1f1: /* reload other segment registers */ movl $KERN_DATA_SEG,%eax movl %eax,%ds movl %eax,%es movl %eax,%ss movl $stktop,%esp /* program the PITs in order to stop them */ mov $0x30,%al out %al,$0x43 out %al,$0x40 mov $0x70,%al out %al,$0x43 out %al,$0x41 mov $0xf0,%al out %al,$0x43 out %al,$0x42 call main /* fall through */ .globl exitexit:2: ljmp $KERN_CODE_SEG,$2b/**************************************************************************MEMSIZE - Determine size of extended memory**************************************************************************/ .globl memsizememsize:#if 0 pushl %ebx pushl %esi pushl %edi call _prot_to_real .code16 movw $0xe801,%ax stc int $0x15 jc 1f andl $0xffff,%eax andl $0xffff,%ebx shll $6,%ebx addl %ebx,%eax jmp 2f1: movw $0x8800,%ax int $0x15 andl $0xffff,%eax2: movl %eax,%esi DATA32 call _real_to_prot .code32 movl %esi,%eax popl %edi popl %esi popl %ebx#else mov $32768,%eax#endif ret/**************************************************************************XSTART - Transfer control to the kernel just loaded**************************************************************************/ .code16 .globl _int08_handler_int08_handler: movb $0x20, %al outb %al, $0x20 iret .globl _int10_handler_int10_handler: cmp $0x3, %ah jnz _int10_04 mov $0x0, %dx mov $0x0, %cx iret_int10_04: cmp $0x4, %ah jnz _int10_05 mov $0x0, %ah iret_int10_05: cmp $0x5, %ah jnz _int10_08 mov $0x0, %al iret_int10_08: cmp $0x8, %ah jnz _int10_0D mov $0x20, %al mov $0x7, %ah iret_int10_0D: cmp $0xD, %ah jnz _int10_0F mov $0x0, %al iret_int10_0F: cmp $0xF, %ah jnz _int10_XX mov $0xb, %al mov $80, %ah mov $0, %bh_int10_XX: iret .globl _int11_handler_int11_handler: mov $0x22, %ax iret .globl _int12_handler_int12_handler: mov $640, %ax iret .globl _int13_handler_int13_handler: clc mov $0, %ah iret .globl _int14_handler_int14_handler: iret .globl _int15_handler_int15_handler: cmp $0xe801,%ax jz _int15_008 cmp $0x0, %ah jz _int15_000 cmp $0x1, %ah jz _int15_000 cmp $0x2, %ah jz _int15_000 cmp $0x3, %ah jz _int15_000 cmp $0xf, %ah jz _int15_000 cmp $0x21, %ah jz _int15_000 cmp $0x40, %ah jz _int15_000 cmp $0x41, %ah jz _int15_000 cmp $0x42, %ah jz _int15_000 cmp $0x43, %ah jz _int15_000 cmp $0x44, %ah jz _int15_000 cmp $0x80, %ah jz _int15_001 cmp $0x81, %ah jz _int15_001 cmp $0x82, %ah jz _int15_002 cmp $0x83, %ah jz _int15_003 cmp $0x84, %ah jz _int15_000 cmp $0x85, %ah jz _int15_004 cmp $0x86, %ah jz _int15_003 cmp $0x87, %ah jz _int15_005 cmp $0x88, %ah jz _int15_006 cmp $0x89, %ah jz _int15_005 cmp $0x90, %ah jz _int15_007 cmp $0xc0, %ah jz _int15_000 cmp $0xc1, %ah jz _int15_000 cmp $0xc2, %ah jz _int15_000 cmp $0xc3, %ah jz _int15_000 cmp $0xc4, %ah jz _int15_000 iret_int15_000: mov $0x86, %ah stc iret_int15_001: mov $0, %bx mov $0, %cx iret_int15_002: mov $0, %bx iret_int15_003: clc iret_int15_004: mov $0, %al iret_int15_005: mov $0, %ah clc cmp $0, %ah iret_int15_006: mov $0xf000, %ax iret_int15_007: stc iret_int15_008: clc mov $1024, %dx /* dx -> extended memory size (in 64K chuncks) */ mov $640, %cx /* cx -> conventional memory size (in 1 Kbytes chuncks) */ iret .globl _int16_handler_int16_handler: cmp $0x0, %ah jnz _int16_01 mov $0x20, %al mov $0x39, %ah iret_int16_01: cmp $0x1, %ah jnz _int16_02 iret_int16_02: cmp $0x2, %ah jnz _int16_05 mov $0, %al iret_int16_05: cmp $0x5, %ah jnz _int16_10 mov $0, %al iret_int16_10: cmp $0x10, %ah jnz _int16_11 mov $0x20, %al mov $0x39, %ah iret_int16_11: cmp $0x11, %ah jnz _int16_12 iret_int16_12: cmp $0x12, %ah jnz _int16_XX mov $0, %ax iret_int16_XX: iret .globl _int17_handler_int17_handler: mov $0xd0, %ah iret .globl _int19_handler_int19_handler: hlt iret .globl _int1A_handler_int1A_handler: stc iret .code32 .globl xstartxstart: /* reprogram the PICs so that interrupt are masked */ movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/ outb %al,$0x20 movb $PIC1_VBS, %al outb %al,$0x21 movb $0x4,%al outb %al,$0x21 movb $0x1,%al outb %al,$0x21 movb $0xff,%al outb %al,$0x21 movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/ outb %al,$0xa0 movb $PIC2_VBS, %al outb %al,$0xa1 movb $0x2,%al outb %al,$0xa1 movb $0x1,%al outb %al,$0xa1 movb $0xff,%al outb %al,$0xa1 pushl %ebp movl %esp,%ebp pushl %ebx pushl %esi pushl %edi movl 8(%ebp),%eax movl %eax,_execaddr movl 12(%ebp),%ebx movl 16(%ebp),%ecx /* bootp record (32bit pointer) */ addl $28,%ecx /* ip, udp header */ shll $12,%ecx shrw $12,%cx call _prot_to_real .code16/* MP: add int10 handler */ push %eax push %ebx push %es mov $0,%ax mov %ax,%es mov %cs,%ax shl $16,%eax ADDR32 mov $(_int08_handler-_start),%ax mov $0x20,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int10_handler-_start),%ax mov $0x40,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int11_handler-_start),%ax mov $0x44,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int12_handler-_start),%ax mov $0x48,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int13_handler-_start),%ax mov $0x4c,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int14_handler-_start),%ax mov $0x50,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int15_handler-_start),%ax mov $0x54,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int16_handler-_start),%ax mov $0x58,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int17_handler-_start),%ax mov $0x5c,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int19_handler-_start),%ax mov $0x64,%ebx mov %eax,%es:(%bx) ADDR32 mov $(_int1A_handler-_start),%ax mov $0x68,%ebx mov %eax,%es:(%bx) pop %es pop %ebx pop %eax/* */ pushl %ecx /* bootp record */ pushl %ebx /* file header */ movl $((RELOC<<12)+(1f-RELOC)),%eax pushl %eax ADDR32 LJMPI(_execaddr-_start)1: addw $8,%sp /* XXX or is this 10 in case of a 16bit "ret" */ DATA32 call _real_to_prot .code32 popl %edi popl %esi popl %ebx popl %ebp ret_execaddr: .long 0#ifdef IMAGE_MULTIBOOT/**************************************************************************XEND - Restart Etherboot from the beginning (from protected mode)**************************************************************************/ .globl xendxend: cs lidt idtarg_realmode-_start+RELOC cs lgdt gdtarg-_start+RELOC#ifdef GAS291 ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */#else ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */#endif /* GAS291 */1: .code16 movw $REAL_DATA_SEG,%ax movw %ax,%ds movw %ax,%ss movw %ax,%es /* clear the PE bit of CR0 */ movl %cr0,%eax andl $0!CR0_PE,%eax movl %eax,%cr0 /* make intersegment jmp to flush the processor pipeline * and reload %cs:%eip (to clear upper 16 bits of %eip). */ DATA32 ljmp $(RELOC)>>4,$2f-_start2: /* we are in real mode now * set up the real mode segment registers : %ds, %ss, %es */ movw %cs,%ax movw %ax,%ds movw %ax,%es movw %ax,%ss xorl %esp,%esp ADDR32 movw initsp-RELOC,%sp movw $0,%ax movw %ax,%fs movw %ax,%gs sti jmp _start .code32#endif /* IMAGE_MULTIBOOT */.global get_csget_cs: xorl %eax,%eax movw %cs,%ax ret.global get_dsget_ds: xorl %eax,%eax movw %ds,%ax ret.global getspgetsp: movl %esp,%eax /* GET STACK POINTER */ subl $4, %eax /* ACCOUNT FOR RETURN ADDRESS ON */ ret.global get_gdtbaseget_gdtbase: sub $8,%esp /* ALLOCATE ROOM ON THE STACK */ sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */ mov 2(%esp),%eax /* READ GDT BASE ADDRESS */ mov $KERN_DATA_SEG,%dx /* ASSUME UNIVERSAL DS. */ add $8,%esp /* RESTORE STACK */ ret /* DONE */.global get_gdtsizeget_gdtsize: sub $8,%esp /* ALLOCATE ROOM ON THE STACK */ sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */ xor %eax,%eax mov 2(%esp),%eax /* READ GDT BASE ADDRESS */ mov (%ESP),%ax shr $3,%ax add $8,%esp /* RESTORE STACK */ ret /* DONE */.global get_idtbaseget_idtbase: sub $8,%esp sidt (%esp,1) /* STORE IIDT REGISTER ON STACK */ mov 2(%esp),%eax mov $KERN_DATA_SEG,%dx add $8,%esp ret.global get_lwget_lw: xor %edx,%edx mov 8(%esp),%eax mov 4(%esp),%dx ret /**************************************************************************SETJMP - Save stack context for non-local goto**************************************************************************/ .globl setjmpsetjmp: mov 4(%esp),%ecx mov 0(%esp),%edx mov %edx,0(%ecx) mov %ebx,4(%ecx) mov %esp,8(%ecx) mov %ebp,12(%ecx) mov %esi,16(%ecx) mov %edi,20(%ecx) mov %eax,24(%ecx) mov $0,%eax ret/**************************************************************************LONGJMP - Non-local jump to a saved stack context**************************************************************************/ .globl longjmplongjmp: mov 4(%esp),%edx mov 8(%esp),%eax mov 0(%edx),%ecx mov 4(%edx),%ebx mov 8(%edx),%esp mov 12(%edx),%ebp mov 16(%edx),%esi mov 20(%edx),%edi cmp $0,%eax jne 1f mov $1,%eax1: mov %ecx,0(%esp) ret/**************************************************************************_REAL_TO_PROT - Go from REAL mode to Protected Mode**************************************************************************/ .globl _real_to_prot_real_to_prot: .code16 cli cs ADDR32 lgdt gdtarg-_start movl %cr0,%eax orl $CR0_PE,%eax movl %eax,%cr0 /* turn on protected mode */ /* flush prefetch queue, and reload %cs:%eip */ DATA32 ljmp $KERN_CODE_SEG,$1f1: .code32 /* reload other segment registers */ movl $KERN_DATA_SEG,%eax movl %eax,%ds movl %eax,%es movl %eax,%ss addl $RELOC,%esp /* Fix up stack pointer */ xorl %eax,%eax movl %eax,%fs movl %eax,%gs popl %eax /* Fix up return address */ addl $RELOC,%eax pushl %eax ret/**************************************************************************_PROT_TO_REAL - Go from Protected Mode to REAL Mode**************************************************************************/ .globl _prot_to_real_prot_to_real: .code32 popl %eax subl $RELOC,%eax /* Adjust return address */ pushl %eax subl $RELOC,%esp /* Adjust stack pointer */#ifdef GAS291 ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */#else ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */#endif /* GAS291 */1: .code16 movw $REAL_DATA_SEG,%ax movw %ax,%ds movw %ax,%ss movw %ax,%es movw %ax,%fs movw %ax,%gs cli /* clear the PE bit of CR0 */ movl %cr0,%eax andl $0!CR0_PE,%eax movl %eax,%cr0 /* make intersegment jmp to flush the processor pipeline * and reload %cs:%eip (to clear upper 16 bits of %eip). */ DATA32 ljmp $(RELOC)>>4,$2f-_start2: /* we are in real mode now * set up the real mode segment registers : %ds, $ss, %es */ movw %cs,%ax movw %ax,%ds movw %ax,%es movw %ax,%ss#if 0 sti#endif DATA32 ret /* There is a 32 bit return address on the stack */ .code32/**************************************************************************GLOBAL DESCRIPTOR TABLE**************************************************************************/ .align 4Idt_Reg: .word 0x3ff .long 0 .align 4_gdt:gdtarg:Gdt_Table: .word 0x27 /* limit */ .long _gdt /* addr */ .word 0_pmcs: /* 32 bit protected mode code segment */ .word 0xffff,0 .byte 0,0x9f,0xcf,0_pmds: /* 32 bit protected mode data segment */ .word 0xffff,0 .byte 0,0x93,0xcf,0_rmcs: /* 16 bit real mode code segment */ .word 0xffff,(RELOC&0xffff) .byte (RELOC>>16),0x9b,0x00,(RELOC>>24)_rmds: /* 16 bit real mode data segment */ .word 0xffff,(RELOC&0xffff) .byte (RELOC>>16),0x93,0x00,(RELOC>>24) .align 4RUN_GDT: /* POINTER TO GDT IN RAM */ .byte 0x7f,0 /* [BSP_GDT_NUM*8]-1 */ .long Gdt_Table .align 4 .section ".rodata"err_not386: .ascii "Etherboot/32 requires 386+" .byte 0x0d, 0x0aerr_not386_end:days: .long 0irq_num: .long .data .align 4 .org 2048.global stktopstktop: .long.section ".armando"/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -