📄 dosstart.s
字号:
//2:// lodsb// andb %al, %al// jz 2f//// call 1f //prtchr// jmp 2b////2:// ret////# Space printing//prtsp2: call prtspc # Print double space//prtspc: movb $0x20, %al # Print single space (note: fall-thru)////# Part of above routine, this one just prints ascii al//prtchr://1:// pushw %ax// pushw %cx// movw $7,%bx// movw $0x01, %cx// movb $0x0e, %ah// int $0x10// popw %cx// popw %ax// ret////beep:// movb $0x07, %al// jmp 1b //prtchr a20_control_begin_string: .ascii "\r\nkernel grub.exe: Trying to turn on A20 gate ...\r\n\0$"a20_control_ok_string: .ascii "\r\nkernel grub.exe: A20 gate turned on OK!\r\n\0$"a20_control_fail_string: .ascii "\r\nkernel grub.exe: A20 gate not responding!\r\n\0$"#include "a20.inc"# Read the cmos clock. Return the seconds in algettime: pushw %cx movb $0x02, %ah int $0x1a movb %dh, %al # %dh contains the seconds andb $0x0f, %al movb %dh, %ah movb $0x04, %cl shrb %cl, %ah aad popw %cx ret# Descriptor tables## NOTE: The intel manual says gdt should be sixteen bytes aligned for# efficiency reasons. However, there are machines which are known not# to boot with misaligned GDTs, so alter this at your peril! If you alter# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two# empty GDT entries (one for NULL and one reserved).## NOTE: On some CPUs, the GDT must be 8 byte aligned. This is# true for the Voyager Quad CPU card which will not boot without# This directive. 16 byte aligment is recommended by intel.# .align 16gdt: .fill GDT_ENTRY_BOOT_CS,8,0 .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) .word 0 # base address = 0 .word 0x9A00 # code read/exec .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit) .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) .word 0 # base address = 0 .word 0x9200 # data read/write .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit)gdt_end: .align 4 .word 0 # alignment byteidt_48: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L .word 0 # alignment bytegdt_48: .word gdt_end - gdt - 1 # gdt limit .word 0, 0 # gdt base (filled in later)# Include video setup & detection code#;#include "video.S"# Setup signature -- must be lastsetup_sig1: .word SIG1setup_sig2: .word SIG2# After this point, there is some free space which is used by the video mode# handling code to store the temporary mode table (not used by the kernel).modelist:.textendtext:.dataenddata:.bssendbss:/* stolen from linux-2.6.13.1/arch/i386/boot/compressed/head.S *//* * linux/boot/head.S * * Copyright (C) 1991, 1992, 1993 Linus Torvalds *//* * head.S contains the 32-bit startup code. * * NOTE!!! Startup happens at absolute address 0x00001000, which is also where * the page directory will exist. The startup code will be overwritten by * the page directory. [According to comments etc elsewhere on a compressed * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] * * Page 0 is deliberately kept safe, since System Management Mode code in * laptops may need to access the BIOS data stored there. This is also * useful for future device drivers that either access the BIOS via VM86 * mode. *//* * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */.text#include <linux/linkage.h>#include <asm/segment.h> . = _start + 0x2000 .code32 .align 0x200 .globl startup_32 //#define debug_putchar(x) movw $(x | ((x << 12) & 0xF000) | (((x << 8) & 0x0F00) ^ 0xC00)), (0xB8140 + (((x - 0x30) % 80) * 2))#define debug_putchar(x)startup_32: cld cli movl $(__BOOT_DS), %eax movl %eax, %ds movl %eax, %es movl %eax, %fs movl %eax, %gs movl %eax, %ss debug_putchar('0')// movw $0x0C30, 0xB80A0 /* we use space near the end of real mode IDT for temp stack */ movl $0x400, %esp xorl %eax,%eax/* * Initialize eflags. Some BIOS's leave bits like NT set. This would * confuse the debugger if this code is traced. * XXX - best to initialize before switching to protected mode. */ //pushl $0 pushl %eax # EAX=0 popfl # cli, cld by the way1: incl %eax # check that A20 really IS enabled movl %eax,0x000000 # loop forever if it isn't cmpl %eax,0x100000 je 1b debug_putchar('1')// movw $0x1D31, (0xB80A0 + (1 * 2)) call 1f # just calculate the EIP register1: popl %ebp # EBP=linear address of 1b, i.e., current EIP subl $(1b - startup_32), %ebp # EBP=linear address of startup_32#if 0 # debug, move conventional mem to 0x1000000 pushw %cs pushw %ds pushw %es pushw %ss pushw %fs pushw %gs pushal movl $0x1000000, %edi xorl %esi, %esi movl $0x400000, %ecx cld rep movsl popal popw %gs popw %fs popw %ss popw %es popw %ds popw %cx#endif /* memory layout: * * 0x0600-0x07FF this sector is not used * 0x0800-0x09FF this sector stores command line * 0x0A00-0x0DFF 2 sectors for real mode variables * 0x0E00-0x0FFF the current sector will be copied here * 0x1000-0x8000 the rest sectors * * Note: The first page(4KB) is not used by Linux, so it is a safe * place to store our code and data. */ cld # can be omitted(already done by popfl) pushl %esi # points to boot_params /* move 1 sector of commandline onto 0x00000800-0x000009FF */ movl $0x00000800, %edi movl 0x228(%esi), %esi # 0x228 is offset for cmd_line_ptr movl $0x00000080, %ecx # move 1 sector repz movsl popl %esi # points to boot_params debug_putchar('2') /* move 2-sector real mode variables onto 0x00000A00-0x00000DFF */ movl $0x00000A00, %edi movl $0x00000100, %ecx # move 2 sectors repz movsl debug_putchar('3') /* move 1 sector of the init code here to a safe place 0x00000E00 */ movl $0x00000E00, %edi movl %ebp, %esi # EBP=linear address of startup_32 movl $0x00000080, %ecx # move 1 sector repz movsl debug_putchar('4') /* jump to new code in the sector starting at 0x00000E00 */ /* just to learn various jumps */#if 1 # this way we needn't touch CS register#if 1 # and this way we needn't touch the stack#if 0 # and this even won't touch any registers # but unfortunately we don't know the # relative displacement // jmp (1f - 0x????????)#else # but this way we need to touch a register movl $(1f - startup_32 + 0x00000E00), %eax jmp *%eax # Oh, don't use `jmp *(%eax)' by mistake! # Should use register indirect addressing, # not memory indirect addressing.#endif#else # and, this way we need the stack movl $(1f - startup_32 + 0x00000E00), %eax pushl %eax ret#endif#else # jump to new code. __BOOT_CS is this segment, and still 32 bit ljmp $(__BOOT_CS), $(1f - startup_32 + 0x00000E00)#endif1: debug_putchar('5') /* We are executed in low memory rang 0x0E00 to 0x0FFF, and now * it is safe to copy the rest code to 0x00001000 */ movl $((_dos_start - startup_32 - 0x200) / 4), %ecx repz movsl debug_putchar('6') /* default boot device: DH=partition number, DL=drive number */ movl $0x80, %edx /* At last, move pre_stage2 to 0x00008200 */ movl $0x00008200, %edi movl $0x00020000, %ecx # move 0x80000 bytes(512KB) movl %ebp, %esi # EBP=linear address of startup_32 addl $(pre_stage2_start - startup_32), %esi # ESI points to pre_stage2_start cmpl $0x00008200, %esi jb 1f cld repz movsl jmp 2f1: addl $0x7fffc, %edi addl $0x7fffc, %esi std # downward # remember to clear it later! rep movsl # EDI=0x00008200 cld # now clear it so we are safe2: debug_putchar('7')//---------------------------------------------------------------------------- # resolve the commandline arguments and move preset_menu to 0x00000800 # commandline has been copied to the sector starting at 0x00000800 /* ECX = 0 */ movl $0x00000200, %ecx # find the option in 1 sector //movb $2, %ch # ECX=0x200 movl $0x00000800, %esi # starting at physical address 0x800 /* look for a non-blank char */ cld3: lodsb cmpb $0, %al je 4f # end string, failure cmpb $0x20, %al je 2f cmpb $0x09, %al jne 1f2: loop 3b # load next byte, ECX decreased jmp 4f #; all are blanks, failure1: decl %esi # found, let ESI point to it// incl %ecx /* This is a leading non-blank char. Check if it matches the option. * option_config_file points to constant string "--config-file=" */ movl $(option_config_file - startup_32 + 0xE00), %edi pushl %ecx movl $(option_config_file_end - option_config_file), %ecx movl %esi, %eax # save ESI cld repz cmpsb #; ESI, EDI both changed popl %ecx je 1f # success /* No match. Then look for a blank char. */ movl %eax, %esi # restore ESI incl %esi # let ESI points to the char next to # the leading non-blank char. decl %ecx cld3: lodsb cmpb $0, %al je 4f # end string, failure cmpb $0x20, %al je 2b # Blank found, try again cmpb $0x09, %al je 2b # Blank found, try again loop 3b4: /* failure: the option "--config-file" was not found. */ debug_putchar('8') stc jmp normal_config_file1: debug_putchar('9') /* success: the option "--config-file" was found. */ xorl %ebx, %ebx cmpb $0x22, (%esi) /* 0x22 is the double quote char */ jne 1f incl %esi incl %ebx /* EBX=1 means a leading double quote exists */1: cmpb $0x28, (%esi) /* 0x28 is "(" */ je normal_config_file # CF=0 cmpb $0x2F, (%esi) /* 0x2F is "/" */ je normal_config_file # CF=0 # locate the end of the commandline preset_menu movl $0x000009ff, %ecx # end of the sector subl %esi, %ecx # length of menu movl $0x00000800, %edi testl %ebx, %ebx # quoted? jz 1f # no /* change the double quote to NULL */ pushl %edi pushl %ecx movl %esi, %edi # EDI points to source me
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -