⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 first-dos.s

📁 linux下从网卡远程启动
💻 S
📖 第 1 页 / 共 4 页
字号:
; first.S  -  primary boot loader for DOS;; Copyright (C) 1996-1998 Gero Kuhlmann   <gero@gkminix.han.de>; Modifications for booting FreeDOS by Ken Yap <ken_yap@users.sourceforge.net>;; 2003.04.28 Robb Main;  Tweaks & bugfixes to allow use with much larger disk images, remove;  '2 head assumption', use 32-bit GDT, and other 'stuff'.;;  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;  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.#if	!defined(USE_NASM) && !defined(USE_AS86)#define	USE_AS86#endif#ifdef	USE_AS86#define	CON(x)		*x#define	BCON(x)		*x#define	LOC(x)		x#define	BLOC(x)		byte ptr x#define	WLOC(x)		word ptr x#define	JMP(x)		jmp x#define	STRDECL(s)	.ascii	s#define	SEGCS		seg	cs#define	SEGES		seg	es#define	ALIGN(x)	.align	x#define	SPACE(x)	.space	x#endif#ifdef	USE_NASM#define	CON(x)		x#define	BCON(x)		byte x#define	LOC(x)		[x]#define	BLOC(x)		byte [x]#define	WLOC(x)		word [x]#define	JMP(x)		jmp short x#define	STRDECL(s)	db	s#define	SEGCS		cs#define	SEGES		es#define	ALIGN(x)	align x, db 0#define	SPACE(x)	times x db 0#endif#ifndef ASM_DEBUG#undef ASM_DEBUG#endif#include "first-dos.h"#include "version-dos.h"#ifdef	USE_AS86	.text	.org	0#endif#ifdef	USE_NASM	text#endif_start:	mov	dx,ds	mov	ax,cs			; set DS	mov	ds,ax	mov	LOC(oldES),es	mov	LOC(oldDS),dx		; save old register values in case	mov	LOC(oldBP),bp		; we have to return to the boot rom	mov	LOC(oldSI),si	mov	LOC(oldDI),di	mov	bp,sp	mov	ax,[bp+4]	mov	LOC(header+0),ax		; load the address of the boot header	mov	ax,[bp+6]	mov	LOC(header+2),ax	mov	ax,[bp+8]	mov	LOC(bootp+0),ax		; load the address of the bootp block	mov	ax,[bp+10]	mov	LOC(bootp+2),ax; Tell the user who we are and that we started running	mov	si,CON(sigmsg)	call	prnstr; Check if the boot image header is correct.	les	bx,LOC(header)	mov	si,CON(bmerr)		; prepare for correct error message	SEGES	mov	ax,[bx+BOOT_HD_MAGIC+0]	cmp	ax,LOC(bmagic+0)	; compare boot rom magic numbers	jne	doerr1	SEGES	mov	ax,[bx+BOOT_HD_MAGIC+2]	cmp	ax,LOC(bmagic+2)	jne	doerr1	mov	si,CON(vmerr)		; prepare for correct error message	SEGES	mov	al,[bx+BOOT_HD_LENGTH]	mov	cl,CON(4)	shr	al,cl	and	al,CON(0x0F)	cmp	al,CON(VENDOR_SIZE)	; check vendor ID size	jne	doerr1	xor	di,didovmag:	mov	al,[di+vmagic]		; check vendor ID	or	al,al	jz	getrd			; vendor ID ok, continue	SEGES	cmp	al,[bx+di+BOOT_HD_VENDOR]	jne	doerr1	inc	di	JMP(dovmag)doerr1:	call	prnstr			; in case of error return to the	mov	si,LOC(oldSI)		; boot rom with registers set	mov	di,LOC(oldDI)		; correctly	mov	bp,LOC(oldBP)	mov	es,LOC(oldES)	mov	ds,LOC(oldDS)	retf; Next get the address of the ramdisk and its size.getrd:	mov	si,CON(recerr)	mov	al,CON(VENDOR_RAMDISK)	call	fndldr				; find load record for ramdisk	mov	ax,es	or	ax,di	jz	doerr1	SEGES	mov	al,[di+BOOT_LD_FLAGS]		; get load record flags	test	al,CON(BOOT_FLAG_B0 + BOOT_FLAG_B1)	; check that it has a	jnz	doerr1				; correct flag	SEGES	mov	ax,[di+BOOT_LD_ADDR+0]		; get base adress of ramdisk	SEGES	mov	bx,[di+BOOT_LD_ADDR+2]	mov	LOC(rdaddr+0),ax	mov	LOC(rdaddr+2),bx	SEGES	mov	ax,[di+BOOT_LD_MLENGTH+0]	; get ramdisk size	SEGES	mov	bx,[di+BOOT_LD_MLENGTH+2]	add	ax,CON(0x03ff)			; round to nearest kb	adc	bx,BCON(0)	mov	cl,CON(10)	shr	ax,cl				; convert into kb	mov	cl,CON(6)	shl	bx,cl	or	ax,bx	mov	LOC(rdsize),ax; Get the disk geometry out of the vendor information block in the; load record	SEGES	mov	bl,[di+BOOT_LD_LENGTH]	and	bl,CON(0x0f)	xor	bh,bh				; compute pointer to	shl	bx,CON(1)			; vendor block	shl	bx,CON(1)	SEGES	mov	ax,[di+bx+BOOT_LD_SECNUM]	; get number of sectors	mov	LOC(secnumlo),ax	SEGES	mov	ax,[di+bx+BOOT_LD_SECNUM+2]	; get number of sectors	mov	LOC(secnumhi),ax	SEGES	mov	ax,[di+bx+BOOT_LD_HEADS]	; get head count	mov	LOC(heads),al	SEGES	mov	ax,[di+bx+BOOT_LD_SPT]		; get sectors per track	mov	LOC(secptk),al	SEGES	mov	ax,[di+bx+BOOT_LD_CYL]		; get number of cylinders	mov	LOC(cylnum),ax	SEGES	mov	al,[di+bx+BOOT_LD_NOHD]		; get no-hard-disk flag	mov	LOC(nohd),al	SEGES	mov	al,[di+bx+BOOT_LD_DRIVE]		; get ram disk drive id	mov	LOC(drvid),al; Set the address of the BIOS disk status byte	mov	bx,CON(BIOS_FDSTAT)	cmp	al,CON(0x80)	jb	setsts	mov	bx,CON(BIOS_HDSTAT)setsts:	mov	LOC(statof),bx; Get system configuration from BIOS	push	ax	int	0x11	mov	LOC(syscnf),ax	pop	ax; Get the number of floppy or hard disk drives in the system and set; the DOS disk parameter block	cmp	al,BCON(0x80)	jae	getnm2	mov	ah,CON(0x08)	xor	dl,dl	int	0x13			; get the number of floppy disk	jc	getnm1			; drives from the BIOS	or	dl,dl	jnz	gotnum	inc	dl			; indicate at least one drive	JMP(gotnum)getnm1:	mov	dx,LOC(syscnf)		; if int 13h didnt work try it with	test	dl,CON(0x01)		; the mainboard dip switch config	jz	getnm3	mov	cl,CON(6)	shr	dl,cl	and	dl,CON(0x03)		; determine number of floppy disk	inc	dl			; drives	JMP(gotnum)getnm2:	mov	ah,CON(0x08)	mov	dl,CON(0x80)	int	0x13			; get the number of hard disk	jc	getnm3			; drives from the BIOS	inc	dl	JMP(gotnum); The next line was mov dl,1 in netboot-0.8.1. This was probably an error.getnm3:	mov	dl,CON(1)		; we have at least one drivegotnum:	mov	LOC(drvnum),dl		; save number of disk drives	call	setdpb			; set disk parameter block; Now get the boot sector of the ramdisk and check that its correct. If; we are simulating a hard disk the boot sector contains the partition; table, which we have to analyze. Then load the partitions boot sector.	mov	ax,CON(TEMP_SEGMENT)	mov	es,ax			; pointer to temporary buffer	xor	bx,bx	xor	dx,dx			; first sector	xor	ax,ax	xor	ch,ch			; indicate read	mov	cl,1			; one sector	call	rwsect			; read boot sector		mov	si,CON(rderr)	jc	doerr2	cmp	BLOC(drvid),CON(0x80)	; if the ram disk is simulates a	jb	chkbot			; floppy, there is no partition table	mov	si,CON(dskerr)		; prepare for correct error message	SEGES	cmp	BLOC(PART_STATUS),CON(PART_ACTIVE)	jne	doerr2		SEGES	cmp	BLOC(PART_TYPE),CON(PART_FAT16)	je	partok		SEGES	cmp	BLOC(PART_TYPE),CON(PART_FAT12)	jne	doerr2partok:	SEGES	mov	dx,[PART_ABS_SECT+2]	; get number of first sector	SEGES	mov	ax,[PART_ABS_SECT+0]	xor	ch,ch			; indicate read	mov	cl,1			; one sector	call	rwsect			; read boot sector	mov	si,CON(rderr)	jc	doerr2#ifndef	HD_PARM_CHECK	JMP(dobotp)#endifchkbot:	mov	si,CON(dskerr)		; prepare for correct error message	mov	al,LOC(drvid)	SEGES	cmp	BLOC(DISK_BOOT),al	; check boot disk number	jne	doerr2	SEGES	cmp	WLOC(DISK_BPS),CON(SECT_SIZE)	; check sector size	jne	doerr2	SEGES	cmp	WLOC(DISK_HEADS),BCON(16)	; check number of heads	jg	doerr2	SEGES	mov	ax,LOC(DISK_SPT)	; check number of sectors per track	cmp	al,LOC(secptk)	je	dobotpdoerr2:		call	prnstr			; in case of error return to the#if 1	push	ax	mov	ah,0			; wait for a keypress, so user	int	0x16			; can read the error message	pop	ax#endif	mov	si,LOC(oldSI)		; boot rom with registers set	mov	di,LOC(oldDI)		; correctly	mov	bp,LOC(oldBP)	mov	es,LOC(oldES)	mov	ds,LOC(oldDS)	retf; Save the BOOTP record for later retrieval by a DOS program.dobotp:	cld	xor	dx,dx	les	di,LOC(bootp)	mov	ax,es	or	ax,di	jz	dobot9	SEGES	mov	al,[di+BOOTP_OP]		; op code must indicate reply	cmp	al,CON(BOOTP_REPLY)	jne	dobot9			; it isnt	add	di,CON(BOOTP_VEND)	mov	bx,di	mov	si,CON(pmagic)		; compare vendor IDdobot1:	mov	di,bx	mov	cx,CON(BOOTP_MAGIC_LEN)	repe	cmpsb	jz	dobot2			; vendor ID is valid	add	si,cx#ifdef	USE_AS86	cmp	byte ptr[si],CON(0)	; check next vendor ID#endif#ifdef	USE_NASM	cmp	byte [si],CON(0)	; check next vendor ID#endif	jne	dobot1dobot9:	JMP(nobot2)			; vendor ID not founddoerr6:	JMP(doerr2)dobot2:	sub	si,BCON(BOOTP_MAGIC_LEN)	sub	si,CON(pmagic)	mov	ax,si	push	ds	mov	bx,ds	mov	es,bx	mov	di,CON(btpnew)	lds	si,LOC(bootp)	mov	bx,si	mov	dx,CON(BOOTP_SIZE)	or	ax,ax			; if not RFC vendor ID the bootp	jnz	dobot7			; record has fixed length	xor	cx,cx	add	si,CON(BOOTP_VEND + BOOTP_MAGIC_LEN)dobot3:	lodsb	cmp	al,CON(BOOTP_RFC_NOP)	; handle NOP tag	jnz	dobot4	inc	cx	cmp	cx,BCON(16)		; more than 16 NOP tags is VERY unusual	jae	dobot7			; so the bootp record maybe broken	JMP(dobot3)			; loop to next tagnobot2:	JMP(nobotp)dobot4:	cmp	al,CON(BOOTP_RFC_END)	; handle END tag	jnz	dobot6	mov	dx,si	sub	dx,bx			; compute length of bootp record	cmp	dx,CON(BOOTP_SIZE)	jae	dobot7	mov	dx,CON(BOOTP_SIZE)	; use minimum size	JMP(dobot7)dobot6:	lodsb				; handle all other tags	mov	cl,al	xor	ch,ch	add	si,cx			; jump to next tag	xor	cx,cx			; reset NOP counter	JMP(dobot3)			; proceed with next tagdobot7:	mov	si,CON(btperr)	mov	ax,CON(btpnew)		; bootp record cannot be larger	add	ax,dx			; than the current segment	jc	doerr6	mov	cx,dx	mov	si,bx			; restore source pointer	rep	movsb				; save the bootp record	pop	dsnobotp:	mov	LOC(btplen),dx		; set length of bootp record; Everything is right, so we can now move the resident section to the; end of the conventional memory, thus overwriting the bootrom data; area. Therefore there is no chance of returning to the bootrom from; now on.; Note that the resident section doesnt start at offset 0, so we have; to set the segment address to somewhere lower.#ifdef ASM_DEBUG	mov	si,CON(debug1)	call	prnstr#endif	cli	mov	ax,CON(TEMP_SEGMENT) 	; set new stack	mov	ss,ax	mov	sp,CON(0xFFF0)	cld		int	0x12			; get memory size in kB#ifdef	FREEDOS	push	ax			; save mem size in kB#endif	/* FREEDOS */	mov	cl,CON(6)	shl	ax,cl			; compute last usable segment	mov	bx,CON(btpnew)	add	bx,LOC(btplen)	mov	dx,bx	mov	cl,CON(4)	shr	bx,cl			; compute size of code segment in	inc	bx			; paragraphs#ifdef	FREEDOS	push	bx			; save size in paragraphs#endif	/* FREEDOS */	sub	ax,bx			; compute new code segment	mov	LOC(resseg),ax	mov	es,ax			; set source and destination ptrs	mov	si,CON(start_resident)	mov	di,si	mov	cx,dx	sub	cx,si			; compute size of resident area	rep	movsb				; move it#ifdef	FREEDOS; New code for FreeDOS, adjust the value of the top of memory returned by; int 0x12. Currently there is no code to restore the original size	pop	bx			; restore size in paragraphs	add	bx,BCON(63) 		; round up to next kB	mov	cl,CON(6)		; divide by 64	shr	bx,cl	pop	ax			; restore size in kB	sub	ax,bx	mov	bx,CON(0x40)	mov	es,bx	SEGES	mov	LOC(0x13),ax		; store at 0x40:0x13 for int 12h; End of new code#endif	/* FREEDOS */; Setup all interrupt vectors	mov	bx,LOC(resseg)	push	ds	mov	ds,bx	xor	ax,ax	mov	es,ax	SEGES	mov	ax,LOC(I13_INT+0)	mov	LOC(old13h+0),ax	SEGES	mov	ax,LOC(I13_INT+2)	mov	LOC(old13h+2),ax	SEGES	mov	ax,LOC(I2F_INT+0)	mov	LOC(old2Fh+0),ax	SEGES	mov	ax,LOC(I2F_INT+2)	mov	LOC(old2Fh+2),ax	SEGES	mov	ax,LOC(IF1_INT+0)	mov	LOC(oldF1h+0),ax	SEGES	mov	ax,LOC(IF1_INT+2)	mov	LOC(oldF1h+2),ax	SEGES	mov	ax,LOC(IF8_INT+0)	mov	LOC(oldF8h+0),ax	SEGES	mov	ax,LOC(IF8_INT+2)	mov	LOC(oldF8h+2),ax	pop	ds	SEGES	mov	LOC(I13_INT+2),bx	; interrupt vector 13h	SEGES	mov	WLOC(I13_INT+0),CON(int13)	SEGES	mov	LOC(I2F_INT+2),bx	; interrupt vector 2Fh	SEGES	mov	WLOC(I2F_INT+0),CON(int2F)	SEGES	mov	LOC(IF8_INT+2),bx	; interrupt vector F8h	SEGES	mov	WLOC(IF8_INT+0),CON(intF8)	mov	di,CON(IF1_INT)	mov	si,CON(if1sig)		; interrupt vector F1h	mov	cx,CON(4)		; contains the string "NetB"	rep				; to provide as an installation

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -