📄 dosstart.s
字号:
/* * dosstart.S -- DOS EXE and Linux kernel startup code for GNU GRUB * Copyright (C) 2003-2007 Tinybit(tinybit@tom.com) * * 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 for License: Since we have copied the Linux kernel code and the * Linux kernel follows GPL2, so only GPL2 is adoptable and it rules here. *//* * This program is used to generate the grub.exe file, which can boot off DOS * directly or, in another way, boot off Linux through KEXEC. * * Use the following shell command to generate the grub.exe file: * * cat dosstart pre_stage2 > grub.exe * */#define ASM_FILE#include <shared.h>#include <stage2_size.h> //#define ABS_PSP(x) (x - _start - 0x100)//#define ABS_PSP(x) (x - _start + 0x0E0)#define ABS_PSP(x) (x - _start - 0x200)#define ABS_START(x) (x - _start - 0x200)//#define ABS_START(x) (x - _start - 0x020)#define ABS_FINAL(x) (x - pre_stage2_start + 0x200)/* HMA_backup immediately follows the main body of stage2, para aligned *///#define HMA_backup ((STAGE2_SIZE + pre_stage2_start - _start - 0x100 + 15) / 16)//#define HMA_backup ((STAGE2_SIZE + pre_stage2_start - _start + 0x0E0 + 15) / 16)#define HMA_backup (ABS_PSP(STAGE2_SIZE + 0x1010 + pre_stage2_start + 15) / 16) .file "dosstart.S" .text /* Tell GAS to generate 16-bit instructions so that this code works in real mode. */ .code16 .globl start, _start//start:_start: /* 1 sector of EXE header is used by DOS. Actually only the leading * 32 bytes are used for EXE header. At offset 0x20(=32) begins the * DOS device driver structure. And at offset 0x1f1(=497) begins * the Linux kernel structure. */ /* * The dos startup code counts N=(pre_stage2_start-_start)/512 sectors: * * 1 sector for DOS EXE header, followed by (N-1) sectors of code. * Of the (N-1) code sectors, the first (N-2) sectors are preparational * sectors, and the last sector is called the FINAL sector. The * FINAL sector contains code that finally launches the stage2 code. * So pay special attention to the FINAL sector. Do not destroy * the FINAL sector upon memory move operations. */ .byte 0x4d, 0x5a /* 'MZ', the EXE magic number. */ /* EXE file last sector in bytes */ .word ((STAGE2_SIZE + 0x1010 + pre_stage2_start - _start) % 512)#define exe_sectors ((STAGE2_SIZE + 0x1010 + pre_stage2_start - _start + 511) / 512 ) .word exe_sectors /* total sectors the EXE file occupies */ .word 0 /* relocation table entries */ .word 0x0002 /* header size in 16-byte paragraphs. */ /* 0x0002 paragraphs == 32 bytes */ .word 0x1000 + 0x0300 + 0x0040 #; MinAlloc paragraphs: #; 64KB for HMA_backup #; 12KB for VCPI page_info #; 1KB for restoring EBDA .word 0x1000 + 0x0300 + 0x0040 #; MaxAlloc paragraphs: #; no more memory needed, so #; MaxAlloc == MinAlloc .word 0x001E /* initial SS, relative to START segment */ .word ABS_START(dos_stack) /* initial SP, rich room for stack */ .word 0 /* checksum, ignored by dos */ .word ABS_START(_dos_start) /* initial IP */ .word 0x001E /* initial CS, relative to START segment */ .word 0x001C /* displacement of the relocation table */ .word 0 /* overlay serial number. 0 for main program */ /* DOS program begins at _dos_start. CS==SS==START, DS==ES==PSP */ /* For DOS device driver, _START + 0x20 locates CS:0000 */#-----------------------------------------------------------------------------# DOS device driver structure begins here#----------------------------------------------------------------------------- . = _start + 0x20#if 0# SKELETON.ASM - A SKELETON DEVICE DRIVER V1.0# (C) COPYRIGHT 1994 G.KLEIN##This file contains structures, sample code and information intended# to aid in building a device driver. It is set up as a skeleton, i.e.# hardly any working code is provided. Only the Initialisation command# is implemented - it displays a signon message and the commandline# it was loaded from (excluding the "device[high]=" part). Sample code# is provided both to let the driver load as to let it unload itself# from memory after the initialisation command is processed. There is# also a bit of code showing how to implement the driver as an EXE file,# with different code depending on weather it is loaded from config.sys# or from the command prompt.#Although the major part of this file contains structures and other info,# is assembles to a "working" device driver. It can be loaded from# config.sys, and displays a signon message. When run from the commandline,# it also displays a (different) message. It has been tested with and# assembles "out of the box" under TASM V2.0 and MASM V5.0.#The contents of this file is copyrighted. It may be used freely for# whatever purpose you see it fit. Although a big effort has been made# to ensure all information in this file is correct, no guarantees can# be given. Any comments you may have on this file or the (correctness of)# the information therein are welcome. Here is how you can reach me:## Fidonet: Gertjan Klein @ 2:280/901.14# Internet: gklein@hacktic.nl (Gertjan Klein)# as of Sept. 1994: gklein@xs4all.nl (Gertjan Klein)######################################################################Some structures describing the request headers for the various commands.# In the comment field, a "<" means this is input to the command, and ">"# means this is output from the command. It is indicated weather the# command applies to block (B) or character (C) device drivers, or both# (B/C). If a command is defined later then version 2.0, the DOS version# in which it first appears is placed in parenthesis. This also applies# to the fields in the request headers.rh0 struc #0 - Initialisation (B/C)rh0_len db ? # < Length of packetrh0_unit db ? #Unusedrh0_cmd db 0 # < Device driver commandrh0_stat dw ? # > Status returned by device driverrh0_rsvd db 8 dup (?) #Reservedrh0_units db ? # > Number of units (B)rh0_break dd ? # < End of driver memory (5.0+) # > Break address (new end drvr mem)rh0_bpb dd ? # < Pointer to cmdline (inc. name) # > Pointer to BPB pointers array (B)rh0_drv_ltr db ? # < First available drive (B, 3.0+)rh0_msgflag dw ? # > 1 To make DOS show errors (5.0+)rh0 endsrh1 struc #1 - Media Check (B)rh1_len db ? # < Length of packetrh1_unit db ? # < Unit coderh1_cmd db 1 # < Device driver commandrh1_stat dw ? # > Status returned by device driverrh1_rsvd db 8 dup (?) #Reservedrh1_media db ? # < Current media descriptorrh1_md_stat db ? # > Media status (changed/not/?)rh1_volID dd ? # > Ptr to Volume ID (3.0+)rh1 endsrh2 struc #2 - Get BPB (B)rh2_len db ? # < Length of packetrh2_unit db ? # < Unit coderh2_cmd db 2 # < Device driver commandrh2_stat dw ? # > Status returned by device driverrh2_rsvd db 8 dup (?) #Reservedrh2_media db ? # < Current media descriptorrh2_buff dd ? # < Pointer to bufferrh2_bpb dd ? # > Pointer to BPBrh2 endsrh3 struc #3 - IOCTL input (B/C)rh3_len db ? # < Length of packetrh3_unit db ? # < Unit code (B)rh3_cmd db 3 # < Device driver commandrh3_stat dw ? # > Status returned by device driverrh3_rsvd db 8 dup (?) #Reservedrh3_media db ? #Unusedrh3_buff dd ? # < Pointer to bufferrh3_count dw ? # < Transfer count (bytes) # > Nr of bytes readrh3 endsrh4 struc #4 - Input (B/C)rh4_len db ? # < Length of packetrh4_unit db ? # < Unit code (B)rh4_cmd db 4 # < Device driver commandrh4_stat dw ? # > Status returned by device driverrh4_rsvd db 8 dup (?) #Reservedrh4_media db ? # < Media descriptor byte (B)rh4_buff dd ? # < Pointer to data transfer arearh4_count dw ? # < Transfer count (B:sectors,C:bytes) # > Nr of sectors/bytes readrh4_start dw ? # < Start sector number (B)rh4_volID dd ? # > Pointer to volume ID (B, 5.0+)rh4_HugeStart dd ? # < 32-bits start sector (B, 5.0+) # (if rh4_count = 0FFFFh)rh4 endsrh5 struc #5 - Non-destructive input (C)rh5_len db ? # < Length of packetrh5_unit db ? #Unusedrh5_cmd db 5 # < Device driver commandrh5_stat dw ? # > Status returned by device driverrh5_rsvd db 8 dup (?) #Reservedrh5_char db ? # > Character returnedrh5 endsrh6 struc #6 - Input status (C)rh6_len db ? # < Length of packetrh6_unit db ? #Unusedrh6_cmd db 6 # < Device driver commandrh6_stat dw ? # > Status returned by device driverrh6_rsvd db 8 dup (?) #Reservedrh6 endsrh7 struc #7 - Input flush (C)rh7_len db ? # < Length of packetrh7_unit db ? #Unusedrh7_cmd db 7 # < Device driver commandrh7_stat dw ? # > Status returned by device driverrh7_rsvd db 8 dup (?) #Reservedrh7 endsrh8 struc #8 - Output (B/C)rh8_len db ? # < Length of packetrh8_unit db ? # < Unit code (B)rh8_cmd db 8 # < Device driver commandrh8_stat dw ? # > Status returned by device driverrh8_rsvd db 8 dup (?) #Reservedrh8_media db ? # < Media descriptor byte (B)rh8_buff dd ? # < Pointer to data transfer arearh8_count dw ? # < Transfer count (B:sectors,C:bytes) # > Nr of sectors/bytes readrh8_start dw ? # < Start sector number (B)rh8_volID dd ? # > Pointer to volume ID (B, 5.0+)rh8_HugeStart dd ? # < 32-bits start sector (B, 5.0+) # (if rh8_count = 0FFFFh)rh8 endsrh9 struc #9 - Output with verify (B/C)rh9_len db ? # < Length of packetrh9_unit db ? # < Unit code (B)rh9_cmd db 9 # < Device driver commandrh9_stat dw ? # > Status returned by device driverrh9_rsvd db 8 dup (?) #Reservedrh9_media db ? # < Media descriptor byte (B)rh9_buff dd ? # < Pointer to data transfer arearh9_count dw ? # < Transfer count (B:sectors,C:bytes) # > Nr of sectors/bytes readrh9_start dw ? # < Start sector number (B)rh9_volID dd ? # > Pointer to volume ID (B, 5.0+)rh9_HugeStart dd ? # < 32-bits start sector (B, 5.0+) # (if rh9_count = 0FFFFh)rh9 endsrh0A struc #0Ah - Output status (C)rh0A_len db ? # < Length of packetrh0A_unit db ? #Unusedrh0A_cmd db 0ah # < Device driver commandrh0A_stat dw ? # > Status returned by device driverrh0A_rsvd db 8 dup (?) #Reservedrh0A endsrh0B struc #0Bh - Output flush (C)rh0B_len db ? # < Length of packetrh0B_unit db ? #Unusedrh0B_cmd db 0bh # < Device driver commandrh0B_stat dw ? # > Status returned by device driverrh0B_rsvd db 8 dup (?) #Reservedrh0B endsrh0C struc #0Ch - IOCTL output (B/C)rh0C_len db ? # < Length of packetrh0C_unit db ? # < Unit code (B)rh0C_cmd db 0ch # < Device driver commandrh0C_stat dw ? # > Status returned by device driverrh0C_rsvd db 8 dup (?) #Reservedrh0C_media db ? #Unusedrh0C_buff dd ? # < Pointer to bufferrh0C_count dw ? # < Transfer count (bytes) # > Nr of bytes writtenrh0C endsrh0D struc #0Dh - Open (B/C) (3.0+)rh0D_len db ? # < Length of packetrh0D_unit db ? # < Unit code (B)rh0D_cmd db 0dh # < Device driver commandrh0D_stat dw ? # > Status returned by device driverrh0D_rsvd db 8 dup (?) #Reservedrh0D endsrh0E struc #0Eh - Close (B/C) (3.0+)rh0E_len db ? # < Length of packetrh0E_unit db ? # < Unit code (B)rh0E_cmd db 0eh # < Device driver commandrh0E_stat dw ? # > Status returned by device driverrh0E_rsvd db 8 dup (?) #Reservedrh0E endsrh0F struc #0Fh - Removable media (B) (3.0+)rh0F_len db ? # < Length of packetrh0F_unit db ? # < Unit coderh0F_cmd db 0fh # < Device driver commandrh0F_stat dw ? # > Status returned by device driverrh0F_rsvd db 8 dup (?) #Reservedrh0F endsrh10 struc #10h - Output until busy (C) (3.0+)rh10_len db ? # < Length of packetrh10_unit db ? #Unusedrh10_cmd db 10h # < Device driver commandrh10_stat dw ? # > Status returned by device driverrh10_rsvd db 8 dup (?) #Reservedrh10_media db ? #Unusedrh10_buff dd ? # < Pointer to bufferrh10_count dw ? # < Transfer count (B:sectors,C:bytes) # > Nr of sectors/bytes writtenrh10 ends#Commands 11h and 12h are undefinedrh13 struc #13h - Generic IOCTL (3.2+:B, 3.3+:B/C)rh13_len db ? # < Length of packetrh13_unit db ? # < Unit code (B)rh13_cmd db 13h # < Device driver commandrh13_stat dw ? # > Status returned by device driverrh13_rsvd db 8 dup (?) #Reservedrh13_major db ? # < Categoryrh13_minor db ? # < Minor functionrh13_SI dw ? # < Contents of SI registerrh13_DI dw ? # < Contents of DI registerrh13_pkt dd ? # < Pointer to generic IOCTL req.rh13 ends#Commands 14 to 16 are undefinedrh17 struc #17h - Get device (B) (3.2+)rh17_len db ? # < Length of packetrh17_unit db ? # < Unit number to check # > Last active drive (or 0)rh17_cmd db 17h # < Device driver commandrh17_stat dw ? # > Status returned by device driverrh17_rsvd db 8 dup (?) #Reservedrh17 endsrh18 struc #18h - Set device (B) (3.2+)rh18_len db ? # < Length of packetrh18_unit db ? # < Unit to make activerh18_cmd db 18h # < Device driver commandrh18_stat dw ? # > Status returned by device driverrh18_rsvd db 8 dup (?) #Reservedrh18 endsrh19 struc #19h - IOCTL query (B/C) (5.0+)rh19_len db ? # < Length of packetrh19_unit db ? # < Unit code (B)rh19_cmd db 19h # < Device driver commandrh19_stat dw ? # > Status returned by device driverrh19_rsvd db 8 dup (?) #Reservedrh19_major db ? # < Categoryrh19_minor db ? # < Minor functionrh19_SI dw ? # < Contents of SI registerrh19_DI dw ? # < Contents of DI registerrh19_pkt dd ? # < Pointer to IOCTL query req.rh19 ends#endifnxtdev: .long -1 #Pointer to next device driver in chainattr: .word 0x8000 #Attribute: character devicestrat: .word strategy - nxtdev #Address of strategy routineintr: .word interrupt - nxtdev #Address of interrupt routinedname: .ascii "GRUB4DOS" #Name of the device driver (C), or # (1 byte:) number of devices (B)#The attribute word is defined as follows:# Bit 0: (C): 1 if driver is stdin# 1: (C): 1 if driver is stdout# (B): 1 if driver supports 32-bit sector addressing# (commands 4, 8 and 9)# 2: (C): 1 if driver is NUL device (only allowed for DOS's own driver)# 3: (C): 1 if driver is clock device# 4: (C): 1 if driver supports fast character I/O (int 29h)# 5: undefined# 6: (C/B): 0 if driver supports commands 17h and 18h and/or 13h# (get/set logical drive and generic IOCTL)# 7: (C/B): 1 if driver supports IOCTL query (command 19h)# 8: undefined# 9: undefined# 10: undefined# 11: (C/B): 1 if driver supports commands 0dh, 0eh and 0fh# (Open/close device and removable media)# 12: (C): 1 if driver supports output until busy (command 10h)# (B): 1 if driver requires first FAT sector for build BPB# (command 2)# 13: undefined# 14: (C/B): 1 if driver supports IOCTL read and write (commands 3# and 0ch)# 15: (C): 1 if driver supports a character device# (B): 0 if driver supports a block deviceReqHeader:RhOffs: .word 0 #Saved offset of request headerRhSeg: .word 0 #Saved segment of request headerstrategy: movw %es, %cs:(RhSeg - nxtdev) #Save request header segment movw %bx, %cs:(RhOffs - nxtdev) #Save request header offset lret #Return to caller#The following command table is initialised to the exit routines to# use when the command is not implemented. In this skeleton, only Init# is implemented. Change the pointers as you add routines.#Normally, at least the following routines are required:# For character device drivers: 0,4,5,6,7,8,9,0ah,0bh# For block devices : 0,1,2,4,8,9//cmdtab: .word Init - nxtdev # 0 Initialisation command// .word Exit_Done - nxtdev # 1 Media_check
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -