📄 asm.s
字号:
/* * GRUB -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * Note: These functions defined in this file may be called from C. * Be careful of that you must not modify some registers. Quote * from gcc-2.95.2/gcc/config/i386/i386.h: 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved. The latter must include the registers where values are returned and the register where structure-value addresses are passed. Aside from that, you can include as many other registers as you like. ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } */#define ASM_FILE#include "shared.h"#ifdef STAGE1_5# define ABS(x) ((x) - EXT_C(main) + 0x2200)#else# define ABS(x) ((x) - EXT_C(main) + 0x8200)#endif .file "asm.S" .text /* Tell GAS to generate 16-bit instructions so that this code works in real mode. */ .code16#ifndef STAGE1_5 /* * In stage2, do not link start.S with the rest of the source * files directly, so define the start symbols here just to * force ld quiet. These are not referred anyway. */ .globl start, _startstart:_start:#endif /* ! STAGE1_5 */ ENTRY(main) /* * Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and * at 0x0:0x2200 in stage1.5. */ ljmp $0, $ABS(codestart) /* control byte * bit 0 = 1: disable the "unconditional command-line entrance" feature * bit 1 = 1: disable keyboard intervention in boot process */ . = EXT_C(main) + 0x5 .byte 0 /* * Compatibility version number * * These MUST be at byte offset 6 and 7 of the executable * DO NOT MOVE !!! */ . = EXT_C(main) + 0x6 .byte COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR /* * This is a special data area 8 bytes from the beginning. */ . = EXT_C(main) + 0x8VARIABLE(install_partition) .long 0xFFFFFF/* This variable is here only because of a historical reason. */VARIABLE(saved_entryno)#if defined(STAGE1_5) /* || ! defined(PRESET_MENU_STRING) */ .long 0#else/* Note: GRUB for DOS uses this for the commandline preset_menu. * A preset_menu can be embedded in the commandline of GRUB.EXE. * This new preset_menu overrides the built-in preset_menu. * If the variable is not touched, and the first byte at config_file is 0, * then the new menu at 0x0800 will work. * If the variable here is cleared to 0, or the first byte at config_file is * not 0, then the built-in preset_menu will work. * * Do NOT change this variable to other value than 0. */ .long preset_menu#endifVARIABLE(stage2_id) .byte STAGE2_IDVARIABLE(force_lba) .byte 0VARIABLE(version_string) .string VERSIONVARIABLE(config_file)#ifndef STAGE1_5 .string "/boot/grub/menu.lst"#else /* STAGE1_5 */ .long 0xffffffff .string "/boot/grub/stage2"#endif /* STAGE1_5 */ /* * Leave some breathing room for the config file name. */ . = EXT_C(main) + 0x6C #; bss starting address#ifndef STAGE1_5#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) //.word (__bss_start - main) & 0x0F, (__bss_start - main) >> 4 .long __bss_start#elif defined(HAVE_USCORE_EDATA_SYMBOL) //.word (_edata - main) & 0x0F, (_edata - main) >> 4 .long _edata#elif defined(HAVE_EDATA_SYMBOL) //.word (edata - main) & 0x0F, (edata - main) >> 4 .long edata#else#error no bss starting address#endif#endif . = EXT_C(main) + 0x70/* the real mode code continues... */codestart: cli /* we're not safe here! */ cld /* set up %ds, %ss, and %es */ xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movl $STACKOFF, %esp sti /* added 2008-08-04 */#ifndef STAGE1_5 movb 0x0410, %al movb %al, ABS(floppies_orig) movb 0x0475, %al movb %al, ABS(harddrives_orig) //movb $((int13_handler_end - int13_handler + 0x3ff) / 0x400), ABS(int13_handler) movl 0x54, %eax movl %eax, ABS(ROM_int15) movl 0x4C, %eax movl %eax, ABS(ROM_int13) movl %eax, ABS(ROM_int13_dup) cmpl $0xC0000000, %eax jnb 1f cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax jb 1f andl $0x3FFFFF, %eax cmpl $0x100, %eax jnz 1f movw 0x413, %ax /* Memory size in Kb */ shlw $6, %ax /* Memory size in paragragh */ cmpw 0x4E, %ax /* 0000:004E=current int 13 segment */ jne 1f /* not hooked */ movw %ax, %ds /* DS=current int13 code segment */ /* check our int13 signature "$INT13SFGRUB4DOS" */ cmpl $0x544E4924, 0x103 /* $INT */ jnz 2f cmpl $0x46533331, 0x107 /* 13SF */ jnz 2f cmpl $0x42555247, 0x10B /* GRUB */ jnz 2f cmpl $0x534F4434, 0x10F /* 4DOS */ jnz 2f movl (ROM_int13 - int13_handler), %eax /* 0x1C=ROM int 13 */ cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax jb 2f /* not our handler */ movl (ROM_int15 - int13_handler), %eax /* 0x0C=ROM int 15 */ cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax jb 2f /* not our handler */ /* restore old emu data, except the first byte of handler size. */ movw $(0x140 - 1), %cx movw $1, %si /* DS=current int13 code segment */ movw $ABS(int13_handler + 1), %di /* ES=0 */ repz movsb /* initialize bios_drive_map with hooked_drive_map */ movw $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2), %cx movw $ABS(hooked_drive_map), %si /* CS=0 */ movw $ABS(bios_drive_map), %di /* ES=0 */ cs repz movsw //xorw %ax, %ax //movw %ax, %ds /* DS=0 */ //jmp 3f2: xorw %ax, %ax movw %ax, %ds /* DS=0 */1: //movl ABS(ROM_int15), %eax //cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax //jnb 3f //movl 0x0054, %eax //movl %eax, ABS(ROM_int15)//3: /* check the BIOS type (currently only for Bochs) */ movw $0xF000, %ax movw %ax, %es /* ES=0xF000 */ movw $0xFF00, %di movw $ABS(bochs_copygrght_string), %si movw $0x22, %cx repz cmpsw setz ABS(bios_id) /* 1 for bochs, 0 for unknown. */ xorw %ax, %ax movw %ax, %es /* ES=0 */#endif /* STAGE1_5 *///#ifndef SUPPORT_DISKLESS// /*// * Save the sector number of the second sector (i.e. this sector)// * in INSTALL_SECOND_SECTOR. See also "stage2/start.S".// */// ADDR32 movl %ebp, EXT_C(install_second_sector)//#endif /* the active mouse will hang the machine */#if 0 cli pushal pushw %ds pushw %es pushw %cs call 1f popw %es popw %ds popal jmp 2f1: pushw $0xADDA //ljmp $0xF000, $0x98E1 ljmp $0xF000, $0xA5F22: ljmp $0xF000, $0xFFF0#endif pushw %dx /* DL=boot drive */ /* qemu-0.8.0 could hang on mouse init here. */#if 0 /* reset mouse */ movw $0xC201, %ax int $0x15#endif#if 0 /* disable mouse */ movw $0xC200, %ax xorw %bx, %bx /* BH=0 means disable */ int $0x15#endif#if 0 /* set mouse handler address */ movw $0xC207, %ax xorw %bx, %bx /* ES:BX=0000:0000 to cancel the handler */ int $0x15#endif#if 0 /* disable monitor clock (Watch-Dog) */ movw $0xC300, %ax int $0x15#endif#if 0 /* restart all adaptors */ movb $0xFF, %al outb %al, $0x96 xorw %cx, %cx1: loop 1b movb $0xF0, %al outb %al, $0x96 xorw %cx, %cx1: loop 1b movb $0x00, %al outb %al, $0x96 xorw %cx, %cx1: loop 1b /* initialize all adaptors */ movw $0xC000, %bx2: movw %bx, %ds xorw %si, %si lodsw cmpw $0xAA55, %ax jne 1f xorw %ax, %ax lodsb #; ROM size in sectors addw $3, %ax andw $0xFFFC, %ax subw $4, %ax shlw $5, %ax pushaw pushw %bx pushw $3 movw %sp, %bp lcall *(%bp) popw %bx popw %bx popaw1: addw $0x80, %ax addw %ax, %bx cmpw $0xF000, %bx jb 2b #endif xorw %ax, %ax movw %ax, %ds movw %ax, %es#if 0 /* cancel alarm clock */ movb $0x07, %ah int $0x1A#endif#if 0 /* commented out 2008-06-11 */ /* clear VDS */ andb $0xD7, 0x47B#endif#ifndef STAGE1_5 sti movw $1, %bx /* BL=1, BH=0 */ testb $0x02, ABS(main) + 5 /* disable keyboard intervention? */ jnz 4f /* yes */ movl 0x46c, %eax /* initial tick */ addl $5, %eax /* wait 0.27 seconds */ pushl %eax2: /* checkkey 'c' */ pushw %bx movb $0x01, %ah /* checkkey */ int $0x16 popw %bx jz 1f /* no keypress */ /* getkey */ pushw %bx movb $0x00, %ah /* getkey */ int $0x16 popw %bx cmpw $KEY_IC, %ax /* insert char */ jne 3f movb $1, %bh /* DEBUG_KEY pressed */3: orb $0x20, %al cmpb $0x63, %al /* is "C"? */ jne 2b /* no, get next key */ /* "C" is pressed. */ /* check the DUCE indicator */ cmpl $0x45435544, 0x5FC //jz 1f jz 2b testb $0x01, ABS(main) + 5 /* 0x8205 */ jnz 2b /* Bypass all config files */ movb $0, %bl jmp 2b1: popl %eax pushl %eax movl 0x46c, %ecx /* current tick */ cmpl %eax, %ecx jnb 1f subl $5, %eax cmpl %eax, %ecx jnb 2b cmpl $5, %ecx jb 2b1: popl %eax4: movb %bh, debug_boot#endif popw %dx /* DL=boot drive */ //cli// pushw %bx#ifndef SUPPORT_DISKLESS /* save boot drive reference */ ADDR32 movb %dl, EXT_C(boot_drive)// testb %bh, %bh /* debug_boot? */// jz 1f// movw $ABS(reset_disk_string),%si// call print_message /* will not change DX *///1:// xorw %ax, %ax// /* reset disk system (%ah = 0) *///#ifdef STAGE1_5// int $0x13//#else// call safe_int13//#endif// movw $ABS(reset_disk_failure_string),%si// jc 1f// movw $ABS(reset_disk_success_string),%si//1:// popw %bx// pushw %bx// testb %bh, %bh /* debug_boot? */// jz 1f// call print_message /* will not change DX *///1:#endif// popw %bx xorw %ax, %ax movw %ax, %ds movw %ax, %es testb $0x02, ABS(main) + 5 /* disable keyboard intervention? */ jnz 4f /* yes */ pushw %bx /* clear keyboard buffer */2: movb $0x01, %ah /* checkkey */ int $0x16 jz 1f /* no keypress */ movb $0x00, %ah /* getkey */ int $0x16 jmp 2b1: popw %bx4: /* transition to protected mode */ DATA32 call EXT_C(real_to_prot) /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32#ifndef STAGE1_5 testb %bl, %bl jnz 1f movl $0, EXT_C(use_config_file)1: /* before clearing the bss, we move preset_menu to 0x800 */ movl preset_menu, %eax#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) cmpl $__bss_start, %eax#elif defined(HAVE_USCORE_EDATA_SYMBOL) cmpl $_edata, %eax#elif defined(HAVE_EDATA_SYMBOL) cmpl $edata, %eax#else#error no bss starting address#endif jnz 1f /* use old bootp for diskless */ xorl %eax, %eax cmpb %al, config_file /* AL == 0 */ jnz 2f movl saved_entryno, %ebx testl %ebx, %ebx jnz 3f /* use menu embedded in commnad-line of grub.exe */2: /* use builtin preset_menu */ /* set the starting address of the preset_menu */ #if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) movl $__bss_start, %esi#elif defined(HAVE_USCORE_EDATA_SYMBOL) movl $_edata, %esi#elif defined(HAVE_EDATA_SYMBOL) movl $edata, %esi#else#error no bss starting address#endif cld addl $16, %esi /* skip 4 bytes of B0 02 1A CE */ /* skip 4 bytes of reserved */ /* skip 4 bytes of reserved */ /* skip 4 bytes of zeroes */ movl $0x400, %ecx /* move 4KB of the menu ... */ movl $0x800, %edi /* ... to 0x800 */ repz movsl3: movl $0x0800, preset_menu /* use new menu at 0x800 */1:#endif /* !STAGE1_5 */ /* if force_cdrom_as_boot_device==0, we are running by configfile, so we do not clear bss */ cmpl $0, EXT_C(force_cdrom_as_boot_device) je 1f /* clean out the bss */ /* set %edi to the bss starting address */#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) movl $__bss_start, %edi#elif defined(HAVE_USCORE_EDATA_SYMBOL) movl $_edata, %edi#elif defined(HAVE_EDATA_SYMBOL) movl $edata, %edi#else#error no bss starting address#endif /* set %ecx to the bss end */ #if defined(HAVE_END_SYMBOL) movl $end, %ecx#elif defined(HAVE_USCORE_END_SYMBOL) movl $_end, %ecx#else#error no bss ending address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -