📄 head.s
字号:
pushl $7 /* vector */ jmp int_handvec8: /* error code */ pushl $8 /* vector */ jmp int_handvec9: pushl $0 /* error code */ pushl $9 /* vector */ jmp int_handvec10: /* error code */ pushl $10 /* vector */ jmp int_handvec11: /* error code */ pushl $11 /* vector */ jmp int_handvec12: /* error code */ pushl $12 /* vector */ jmp int_handvec13: /* error code */ pushl $13 /* vector */ jmp int_handvec14: /* error code */ pushl $14 /* vector */ jmp int_handvec15: pushl $0 /* error code */ pushl $15 /* vector */ jmp int_handvec16: pushl $0 /* error code */ pushl $16 /* vector */ jmp int_handvec17: /* error code */ pushl $17 /* vector */ jmp int_handvec18: pushl $0 /* error code */ pushl $18 /* vector */ jmp int_handvec19: pushl $0 /* error code */ pushl $19 /* vector */ jmp int_handint_hand: pushl %eax pushl %ebx pushl %ecx pushl %edx pushl %edi pushl %esi pushl %ebp /* original stack pointer */ leal 20(%esp), %eax pushl %eax pushl %esp /* pointer to structure on the stack */ call inter addl $8, %esp popl %ebp popl %esi popl %edi popl %edx popl %ecx popl %ebx popl %eax iret/* * The interrupt descriptor table has room for 32 idt's */.align 4.word 0idt_descr: .word 20*8-1 # idt contains 32 entries .long 0idt: .fill 20,8,0 # idt is uninitializedgdt_descr: .word gdt_end - gdt - 1 .long 0.align 4.globl gdt, gdt_endgdt: .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* not used */ .quad 0x00cf9a000000ffff /* 0x10 main 4gb code at 0x000000 */ .quad 0x00cf92000000ffff /* 0x18 main 4gb data at 0x000000 */ .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .byte 0x00, 0x9b # code read/exec/accessed .byte 0x00, 0x00 # granularity = bytes .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .byte 0x00, 0x93 # data read/write/accessed .byte 0x00, 0x00 # granularity = bytesgdt_end:.data.macro ptes64 start, count=64.quad \start + 0x0000000 + 0xE3.quad \start + 0x0200000 + 0xE3.quad \start + 0x0400000 + 0xE3.quad \start + 0x0600000 + 0xE3.quad \start + 0x0800000 + 0xE3.quad \start + 0x0A00000 + 0xE3.quad \start + 0x0C00000 + 0xE3.quad \start + 0x0E00000 + 0xE3.if \count-1ptes64 "(\start+0x01000000)",\count-1.endif.endm.macro maxdepth depth=1.if \depth-1maxdepth \depth-1.endif.endmmaxdepth.balign 4096.globl pd0pd0: ptes64 0x0000000000000000.balign 4096.globl pd1pd1: ptes64 0x0000000040000000.balign 4096.globl pd2pd2: ptes64 0x0000000080000000.balign 4096.globl pd3pd3: ptes64 0x00000000C0000000.balign 4096.globl pdppdp: .long pd0 + 1 .long 0 .long pd1 + 1 .long 0 .long pd2 + 1 .long 0 .long pd3 + 1 .long 0.previous#define RSTART startup_32 .globl query_pcbiosquery_pcbios: /* Save the caller save registers */ pushl %ebx pushl %esi pushl %edi pushl %ebp call 1f1: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* Compute the reloc address */ leal RSTART@GOTOFF(%ebx), %esi /* Fixup real code pointer */ movl %esi, %eax shrl $4, %eax movw %ax, 2 + realptr@GOTOFF(%ebx) /* Fixup protected code pointer */ leal prot@GOTOFF(%ebx), %eax movl %eax, protptr@GOTOFF(%ebx) /* Compute the gdt fixup */ movl %esi, %eax shll $16, %eax # Base low movl %esi, %ecx shrl $16, %ecx andl $0xff, %ecx movl %esi, %edx andl $0xff000000, %edx orl %edx, %ecx /* Fixup the gdt */ andl $0x0000ffff, REAL_CS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_CS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_CS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_CS + 4 + gdt@GOTOFF(%ebx) andl $0x0000ffff, REAL_DS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_DS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_DS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_DS + 4 + gdt@GOTOFF(%ebx) /* Fixup the gdt_descr */ leal gdt@GOTOFF(%ebx), %eax movl %eax, 2 + gdt_descr@GOTOFF(%ebx) lidt idt_real@GOTOFF(%ebx) /* Don't disable the a20 line */ /* Load 16bit data segments, to ensure the segment limits are set */ movl $REAL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs /* Compute the stack base */ leal stack@GOTOFF(%ebx), %ecx /* Compute the address of meminfo */ leal mem_info@GOTOFF(%ebx), %edi /* switch to 16bit mode */ ljmp $REAL_CS, $1f - RSTART1: .code16 /* Disable Paging and protected mode */ /* clear the PG & PE bits of CR0 */ movl %cr0,%eax andl $~((1 << 31)|(1<<0)),%eax movl %eax,%cr0 /* make intersegment jmp to flush the processor pipeline * and reload %cs:%eip (to clear upper 16 bits of %eip). */ ljmp *(realptr - RSTART)real: /* we are in real mode now * set up the real mode segment registers : %ds, %ss, %es, %gs, %fs */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* Adjust the stack pointer */ movl %ecx, %eax shrl $4, %eax movw %ax, %ss subl %ecx, %esp /* Save my base pointer */ pushl %ebx /* Setup %ds to point to my data area */ shrl $4, %edi movl %edi, %ds /* Enable interrupts or BIOS's go crazy */ sti# Get memory size (extended mem, kB)#define SMAP 0x534d4150 xorl %eax, %eax movl %eax, (E88) movl %eax, (E801) movl %eax, (E820NR)# Try three different memory detection schemes. First, try# e820h, which lets us assemble a memory map, then try e801h,# which returns a 32-bit memory size, and finally 88h, which# returns 0-64m# method E820H:# the memory map from hell. e820h returns memory classified into# a whole bunch of different types, and allows memory holes and# everything. We scan through this memory map and build a list# of the first 32 memory areas, which we return at [E820MAP].# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htmmeme820: xorl %ebx, %ebx # continuation counter movw $E820MAP, %di # point into the whitelist # so we can have the bios # directly write into it.jmpe820: movl $0x0000e820, %eax # e820, upper word zeroed movl $SMAP, %edx # ascii 'SMAP' movl $20, %ecx # size of the e820rec pushw %ds # data record. popw %es int $0x15 # make the call jc bail820 # fall to e801 if it fails cmpl $SMAP, %eax # check the return is `SMAP' jne bail820 # fall to e801 if it fails# cmpl $1, 16(%di) # is this usable memory?# jne again820 # If this is usable memory, we save it by simply advancing %di by # sizeof(e820rec). #good820: movb (E820NR), %al # up to 32 entries cmpb $E820MAX, %al jnl bail820 incb (E820NR) movw %di, %ax addw $E820ENTRY_SIZE, %ax movw %ax, %diagain820: cmpl $0, %ebx # check to see if jne jmpe820 # %ebx is set to EOFbail820:# method E801H:# memory size is in 1k chunksizes, to avoid confusing loadlin.# we store the 0xe801 memory size in a completely different place,# because it will most likely be longer than 16 bits.meme801: stc # fix to work around buggy xorw %cx,%cx # BIOSes which dont clear/set xorw %dx,%dx # carry on pass/error of # e801h memory size call # or merely pass cx,dx though # without changing them. movw $0xe801, %ax int $0x15 jc mem88 cmpw $0x0, %cx # Kludge to handle BIOSes jne e801usecxdx # which report their extended cmpw $0x0, %dx # memory in AX/BX rather than jne e801usecxdx # CX/DX. The spec I have read movw %ax, %cx # seems to indicate AX/BX movw %bx, %dx # are more reasonable anyway...e801usecxdx: andl $0xffff, %edx # clear sign extend shll $6, %edx # and go from 64k to 1k chunks movl %edx, (E801) # store extended memory size andl $0xffff, %ecx # clear sign extend addl %ecx, (E801) # and add lower memory into # total size.# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or# 64mb, depending on the bios) in ax.mem88: movb $0x88, %ah int $0x15 movw %ax, (E88)#ifdef APM_OFF# check for APM BIOS movw $0x5300, %ax # APM BIOS installation check xorw %bx, %bx int $0x15 jc done_apm_bios # error -> no APM BIOS cmpw $0x504d, %bx # check for "PM" signature jne done_apm_bios # no signature -> no APM BIOS movw $0x5304, %ax # Disconnect first just in case xorw %bx, %bx int $0x15 # ignore return code movw $0x5301, %ax # Real Mode connect xorw %bx, %bx int $0x15 jc done_apm_bios # error movw $0x5308, %ax # Disable APM mov $0xffff, %bx xorw %cx, %cx int $0x15done_apm_bios:#endif /* O.k. the BIOS query is done switch back to protected mode */ cli /* Restore my saved variables */ popl %ebx /* Get an convinient %ds */ movw %cs, %ax movw %ax, %ds /* Load the global descriptor table */ addr32 lgdt gdt_descr - RSTART /* Turn on protected mode */ /* Set the PE bit in CR0 */ movl %cr0,%eax orl $(1<<0),%eax movl %eax,%cr0 /* flush the prefetch queue, and relaod %cs:%eip */ data32 ljmp *(protptr - RSTART)prot: .code32 /* Reload other segment registers */ movl $KERNEL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %fs movl %eax, %gs movl %eax, %ss /* Adjust the stack pointer */ leal stack@GOTOFF(%ebx), %eax addl %eax, %esp /* Restore the caller saved registers */ popl %ebp popl %edi popl %esi popl %ebx movl $1, %eax retrealptr: .word real - RSTART .word 0x0000protptr: .long 0 .long KERNEL_CSidt_real: .word 0x400 - 1 # idt limit ( 256 entries) .word 0, 0 # idt base = 0L.datazerobss: .long 1clear_display: .long 1.previous.data.balign 16 .globl mem_infomem_info: . = . + MEMINFO_SIZE.previous.bss.balign 16stack: . = . + 4096stack_top:.previous
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -