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

📄 pxe.s

📁 WinAoE is an open source GPLv3 driver for using AoE (ATA over Ethernet) on Microsoft Windows
💻 S
字号:
/*  Copyright 2006-2008, V.  For contact information, see http://winaoe.org/  This file is part of WinAoE.  WinAoE 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 3 of the License, or  (at your option) any later version.  WinAoE 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 WinAoE.  If not, see <http://www.gnu.org/licenses/>.*/#include "aoe.h"_int:		.byte	0_tag:		.long	0_oldisr:	.long	0_api:		.long	0send:		.org	.+AoEsize, 0receive:	.org	.+AoEsize, 0_undi_get_information:			# 0x000c	.word	0			# PXENV_STATUS Status	.word	0			# UINT16 BaseIo	.word	0			# UINT16 IntNumber	.word	0			# UINT16 MaxTranUnit	.word	0			# UINT16 HwType	.word	0			# UINT16 HwAddrLen	.org	.+16, 0			# MAC_ADDR CurrentNodeAddress	.org	.+16, 0			# MAC_ADDR PermNodeAddress	.word	0			# SEGSEL ROMAddress	.word	0			# UINT16 RxBufCt	.word	0			# UINT16 TxBufCt_get_cached_info:			# 0x0071	.word	0			# PXENV_STATUS Status	.word	3			# UINT16 PacketType	.word	0			# UINT16 BufferSize	.long	0			# SEGOFF16 Buffer	.word	0			# UINT16 BufferLimit_undi_open:				# 0x0006	.word	0			# PXENV_STATUS status	.word	0			# UINT16 OpenFlag	.word	3			# UINT16 PktFilter	.org	.+(2 + (8 * 16)), 0	# t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf_undi_isr_start:			# 0x0014	.word	0			# PXENV_STATUS Status	.word	0			# UINT16 FuncFlag	.word	0			# UINT16 BufferLength	.word	0			# UINT16 FrameLength	.word	0			# UINT16 FrameHeaderLength	.long	0			# SEGOFF16 Frame	.byte	0			# UINT8 ProtType	.byte	0			# UINT8 PktType_undi_isr:				# 0x0014	.word	0			# PXENV_STATUS Status	.word	0			# UINT16 FuncFlag	.word	0			# UINT16 BufferLength	.word	0			# UINT16 FrameLength	.word	0			# UINT16 FrameHeaderLength	.long	0			# SEGOFF16 Frame	.byte	0			# UINT8 ProtType	.byte	0			# UINT8 PktType_undi_transmit_packet:			# 0x0008	.word	0			# PXENV_STATUS Status	.byte	0			# UINT8 Protocol	.byte	0			# UINT8 XmitFlag	.long	(send + AoEdstaddr)	# SEGOFF16 DestAddr	.long	_undi_TBD		# SEGOFF16 TBD	.org	.+(2 * 4), 0		# UINT32 Reserved[2]_undi_TBD:	.word	0			# UINT16 ImmedLength	.long	send			# SEGOFF16 Xmit	.word	0			# UINT16 DataBlkCount	.org	.+(8 * 8), 0		# DataBlk DataBlock[8].globl pxeinitpxeinit:	enter	$0, $0	movw	$0x5650, %ax		# Check for PXE extension	int	$0x1a	cmpw	$0x564e, %ax	je	0f			# jump if PXE found	print	"PXE check failed...\n"	halt0:	lesw	%es:0x28(%bx), %bx	# get !PXE in es:bx	pushl	%es:0x10(%bx)		# get api entry point	popl	%cs:_api	push	$0x0006			# open undi	push	$_undi_open	call	api	cmpw	$0, %ax	je	0f	print	"open undi failed\n"	halt0:	movw	%cs, %cs:_undi_TBD + 4	movw	%cs, %cs:_undi_transmit_packet + 6	movw	%cs, %cs:_undi_transmit_packet + 10	movw	%cs, %cs:_debug_undi_TBD + 4	movw	%cs, %cs:_debug_undi_transmit_packet + 6	movw	%cs, %cs:_debug_undi_transmit_packet + 10	pushw	$0x000c			# get nic information	pushw	$_undi_get_information	call	api	cmpw	$0, %ax	je	0f	print	"get information failed\n"	halt0:	pushw	$0x0071			# get dhcp information	pushw	$_get_cached_info	call	api	cmpw	$0, %ax	je	0f	print	"get dhcp information failed\n"	halt0:	movl	%cs:_undi_get_information + 12, %eax	# client mac (high 4)	movl	%eax, %cs:(send + AoEsrcaddr)	movl	%eax, %cs:_debug_srcaddr	movl	%eax, %cs:_clientmac	movw	%cs:_undi_get_information + 16, %ax	# client mac (low 2)	movw	%ax, %cs:(send + AoEsrcaddr + 4)	movw	%ax, %cs:_debug_srcaddr + 4	movw	%ax, %cs:_clientmac + 4	movw	%cs:_undi_get_information + 4, %ax	# irq	movb	%al, %cs:_irq	movw	$0xa288, %cs:(send + AoEprotocol)	# protocol	movb	$0x10, %cs:(send + AoEver)		# version 1	call	searchrootpath	pushl	%eax	call	readrootpath	leave	ret	$0# api: calls undi api#  (word)bp+6: function#  (word)bp+4: struct adress in cs# returns:#  ax passed on from api call.globl apiapi:	enter	$0, $0	pushfl	pushw	%cs	pushw	4(%bp)	pushw	6(%bp)	lcall	*%cs:_api	addw	$6, %sp	popfl	leave	ret	$4# searchrootpath: search root-path in dhcp packet# returns:#  eax: position of root-path in memorysearchrootpath:	enter	$0, $0	pushw	%cx	pushw	%ds	pushw	%si	ldsw	%cs:(_get_cached_info + 6), %si	# load ds:si with dhcp location	xorb	%ah, %ah	xorw	%cx, %cx	addw	$0xf0, %si		# offset si to point to dhcp options1:	incw	%cx	lodsb	cmpb	$0xff, %al	jne	0f2:	print	"No root-path found in DHCP options...\n"	halt0:	cmpb	$0x11, %al	je	0f	incw	%cx	lodsb	addw	%ax, %cx	addw	%ax, %si	cmpw	$0x1024, %cx	jb	1b	jmp	2b0:	movw	%ds, %ax	shll	$16, %eax	movw	%si, %ax	pop	%si	pop	%ds	pop	%cx	leave	ret	$0# readrootpath: read root-path from dhcp and sets packet data#  (long)bp+4: address of root-pathreadrootpath:	enter	$0, $0	push	%ax	push	%bx	push	%ds	push	%si	mov	4(%bp), %si	mov	6(%bp), %ds	lodsb	xor	%ah, %ah	add	%ax, %si	movb	$0, %ds:(%si)	sub	%ax, %si	call	5f			# read spaces	lodsw				# read "aoe:e"	or	$0x2020, %ax	cmp	$0x6f61, %ax		# 'oa'	jne	9f			# general error	lodsw	or	$0x0020, %ax	cmp	$0x3a65, %ax		# ':e'	jne	9f			# general error	lodsb	or	$0x20, %al	cmp	$'e', %al	jne	9f			# general error	call	6f			# read number	jc	7f			# major error	mov	%ax, %cs:_major	xchg	%ah, %al	mov	%ax, %cs:(send + AoEmajor)	lodsb	cmp	$'.', %al	jne	9f			# general error	call	6f			# read number	jc	8f			# minor error	cmp	$0, %ah	jne	8f			# minor error	mov	%al, %cs:_minor	mov	%al, %cs:(send + AoEminor)	call	5f			# read spaces	lodsb	cmp	$0, %al	jne	9f			# general error	pop	%si	pop	%ds	pop	%bx	pop	%ax	leave	ret	$4# local: read spaces5:	push	%ax0:	lodsb	cmp	$' ', %al	je	0b	dec	%si	pop	%ax	ret# local: read number# returns number in %ax# carry set on error6:	lodsb	cmp	$'0', %al	jne	1f	lodsb	dec	%si	cmp	$'0', %al	jb	0f	cmp	$'9', %al	ja	0f	stc	ret0:	xor	%ax, %ax	clc	ret1:	dec	%si	push	%bx	push	%cx	push	%dx	xor	%ah, %ah	mov	$10, %bx	xor	%cx, %cx	xor	%dx, %dx0:	lodsb	cmp	$'0', %al	jb	1f	cmp	$'9', %al	ja	1f	push	%ax	mov	%cx, %ax	mul	%bx	cmp	$0, %dx	jne	0f	mov	%ax, %cx	pop	%ax	sub	$0x30, %al	add	%ax, %cx	jc	0f	jmp	0b0:	dec	%si	pop	%dx	pop	%cx	pop	%bx	stc	ret	1:	dec	%si	cmp	$0, %cx	jne	0f	pop	%dx	pop	%cx	pop	%bx	stc	ret0:	mov	%cx, %ax	pop	%dx	pop	%cx	pop	%bx	clc	ret	# local: errors7:	print	"root-path major out of range...\n"	halt8:	print	"root-path minor out of range...\n"	halt9:	print	"root-path misformed, should be \"aoe:e<major>.<minor>\"...\n"	halt.globl getdiskparametersgetdiskparameters:	enter	$0, $0	push	%eax	push	%ebx	push	%edx	movl	$0xffffffff, %cs:(send + AoEdstaddr)	# broadcast	movw	$0xffff, %cs:(send + AoEdstaddr + 4)	movb	$0x1, %cs:(send + AoEcount)	movb	$0xec, %cs:(send + AoEcmd)	# IDENTIFY DEVICE	movw	$(AoEsize - 1024), %cs:_undi_TBD	# size	call	requestpacket	mov	%cs:(receive + AoEsrcaddr), %eax	# copy server mac	mov	%eax, %cs:(send + AoEdstaddr)	mov	%eax, %cs:(_servermac)	mov	%cs:(receive + AoEsrcaddr + 4), %ax	mov	%ax, %cs:(send + AoEdstaddr + 4)	mov	%ax, %cs:(_servermac + 4)	mov	%cs:(receive + AoEdata + 200), %eax	# copy max lba	cmp	$0, %eax	jne	0f	print	"Disk size 0?\n"	halt0:	mov	%eax, %cs:_size	movb	$0x1, %cs:(send + AoEcount)	movb	$0x24, %cs:(send + AoEcmd)	# READ SECTOR	movl	$0, %cs:(send + AoElba0)	movw	$0, %cs:(send + AoElba4)	movw	$(AoEsize - 1024), %cs:_undi_TBD	# size	call	requestpacket	mov	%cs:(receive + AoEdata + 510), %ax	cmp	$0xaa55, %ax	je	0f	xor	%ax, %ax	jmp	1f0:	mov	%cs:(receive + AoEdata + 446 + 12), %eax	cmp	$0, %ax	je	0f	mov	%cs:(receive + AoEdata + 446 + 5), %ax	jmp	1f0:	mov	%cs:(receive + AoEdata + 462 + 12), %eax	cmp	$0, %ax	je	0f	mov	%cs:(receive + AoEdata + 462 + 5), %ax	jmp	1f0:	mov	%cs:(receive + AoEdata + 478 + 12), %eax	cmp	$0, %ax	je	0f	mov	%cs:(receive + AoEdata + 478 + 5), %ax	jmp	1f0:	mov	%cs:(receive + AoEdata + 494 + 12), %eax	cmp	$0, %ax	je	1f	mov	%cs:(receive + AoEdata + 494 + 5), %ax1:	cmp	$0, %al	jne	0f	mov	$254, %al0:	inc	%al	mov	%al, %cs:_heads	and	$0x3f, %ah	cmp	$0, %ah	jne	0f	mov	$0x3f, %ah0:	mov	%ah, %cs:_sectors	xor	%ebx, %ebx	xor	%edx, %edx	mul	%ah	mov	%ax, %bx	mov	%cs:_size, %eax	div	%ebx	mov	%eax, %cs:_cylinders	pop	%edx	pop	%ebx	pop	%eax	leave	ret	$0# processsectors: reads or writes sectors#  (word)bp+14: mode (0 = read, 1 = write)#  (long)bp+10: buffer#  (long)bp+6: lba#  (word)bp+4: count.globl processsectorsprocesssectors:	enter	$0, $0	push	%eax	push	%bx	push	%cx	push	%ds	push	%es	push	%si	push	%di	cmpw	$0x7f, 4(%bp)		# check for count > 0x7f (127)	jbe	0f	jmp	1f0:	cmpw	$0, 4(%bp)		# check for a count of 0	jne	2f1:	print	"Invalid sector count ("	push	4(%bp)	call	printnumber	push	$')'	call	printchar	call	line	halt2:	xor	%ax, %ax		# next, do 1 or 2 sectors?	cmpw	$1, 4(%bp)	je	0f	inc	%ax0:	inc	%ax	mov	14(%bp), %bx	movb	$0x24, %cs:(send + AoEcmd)	# 0x24 = READ SECTOR	cmp	$0, %bx	je	0f	addb	$0x10, %cs:(send + AoEcmd)	# 0x34 = WRITE SECTOR0:	pushl	6(%bp)				# sector	popl	%cs:(send + AoElba0)	movw	$0, %cs:(send + AoElba4)	mov	%al, %cs:(send + AoEcount)	movw	$(AoEsize - 1024), %cs:_undi_TBD	# size	cmp	$0, 14(%bp)			# read?	je	1f	mov	$512, %cx	cmpb	$2, %cs:(send + AoEcount)	# 2 sectors?	jne	0f	add	$512, %cx0:	add	%cx, %cs:_undi_TBD	mov	10(%bp), %si	mov	12(%bp), %ds	mov	$(send + AoEdata), %di	push	%cs	pop	%es	cld				# positive direction	rep	movsb			# copy data to packet1:	call	requestpacket	cmp	$1, 14(%bp)		# write?	je	1f	push	%cs	pop	%ds	mov	$(receive + AoEdata), %si	mov	$512, %cx	cmpb	$2, %cs:(send + AoEcount)	# 2 sectors?	jne	0f	add	$512, %cx0:	mov	10(%bp), %di	mov	12(%bp), %es	cld	rep	movsb1:	addl	$2, 6(%bp)		# next sectors	addw	$1024, 10(%bp)		# add 1024 to buffer	subw	$1, 4(%bp)		# count one down	jz	0f			# no more sectors	subw	$1, 4(%bp)		# count down another	jnz	2b			# get more sectors?0:	pop	%di	pop	%si	pop	%es	pop	%ds	pop	%cx	pop	%bx	pop	%eax	leave	ret	$12# requestpacket: sends request and waits for a replyrequestpacket:	enter	$0, $0	push	%eax	push	%ebx	push	%ecx	push	%es	xorb	%bh, %bh	movb	%cs:_irq, %bl	cmpb	$0, %bl	je	1f	movb	$0, %cs:_int	pushw	$0x0000			# set es to vector table segment	popw	%es	cmpb	$7, %bl	jbe	0f	addb	$(0x70 - 8 - 8), %bl0:	addb	$8, %bl	shlw	$2, %bx	pushl	%es:(%bx)	popl	%cs:_oldisr	pushw	%cs	pushw	$isr	popl	%es:(%bx)	xorb	%bh, %bh	movb	%cs:_irq, %bl	cmpb	$7, %bl	jbe	0f	subb	$8, %bl	inb	$0xa1	btrw	%bx, %ax	mov	$2, %bl0:	inb	$0x21	btrw	%bx, %ax	outb	$0x211:	pushl	%cs:_tag	popl	%cs:(send + AoEtag)0:	call	getticks	mov	%eax, %ecx	push	$0x0008			# transmit packet	push	$_undi_transmit_packet	call	api1:	call	getpacket	cmp	$1, %ax	je	0f	call	getticks	sub	$2, %eax	cmp	%eax, %ecx	ja	1b	jmp	0b0:	incl	%cs:_tag	xorb	%bh, %bh	movb	%cs:_irq, %bl	cmpb	$0, %bl	je	2f	xorb	%bh, %bh	movb	%cs:_irq, %bl	cmpb	$7, %bl	jbe	0f	subb	$8, %bl	inb	$0xa1	btsw	%bx, %ax	jmp	1f0:	inb	$0x21	btrw	%bx, %ax	outb	$0x211:	pushw	$0x0000			# set es to vector table segment	popw	%es	cmpb	$7, %bl	jbe	0f	addb	$(0x70 - 8 - 8), %bl0:	addb	$8, %bl	shlw	$2, %bx	pushl	%cs:_oldisr	popl	%es:(%bx)2:	pop	%es	pop	%ecx	pop	%ebx	pop	%eax	leave	ret	$0# getpacket: get a waiting packet, if any# returns:#  ax is 1 if packet receivedgetpacket:	enter	$0, $0        pushl	%ebx	mov	$0, %ax	cmpb	$0, %cs:_irq	je	1f	cmpb	$0, %cs:_int	ja	2f	jmp	3f1:	movw	$1, %cs:_undi_isr + 2	# PXENV_UNDI_ISR_IN_START	push	$0x0014			# undi isr	push	$_undi_isr	call	api	cmp	$0, %cs:_undi_isr + 2	jne	3f			# not ours2:	call	processpacket	cmp	$1, %ax	jne     3f	mov	$0, %ax	cmpw	$0xa288, %cs:receive + AoEprotocol	jne	3f	mov	%cs:receive + AoEtag, %ebx	cmp	%cs:_tag, %ebx	jne	3f	mov	%cs:receive + AoEmajor, %bx	xchg	%bh, %bl	cmp	%cs:_major, %bx	jne	3f	mov	%cs:receive + AoEminor, %bl	cmp	%cs:_minor, %bl	jne	3f	mov	$1, %ax3:	popl	%ebx	leave	ret	$0_in:	.word	0# isr: checks if the interrupt is for usisr:	enter	$0, $0	pushfl	pushal	push	%ds	push	%es	push	%fs	push	%gs	bts	$0, %cs:_in	jnc	1f	mov	$3, %ax	int	$0x10	print	"reentrant\n"	halt	mov	$0x20, %al	cmp	$7, %cs:_irq	jbe	0f	outb	%al, $0xa00:	outb	%al, $0x20	pop	%gs	pop	%fs	pop	%es	pop	%ds	popal	popfl	leave	iret1:	movw	$1, %cs:_undi_isr_start + 2	# PXENV_UNDI_ISR_IN_START	push	$0x0014				# undi isr	push	$_undi_isr_start	call	api	cmp	$0, %ax	je	0f	print	"PXENV_UNDI_ISR_IN_START failed\n"	pushw	%cs:_undi_isr_start	call	printword	call	line	halt0:	cmp	$0, %cs:_undi_isr_start + 2	je	0f				# ours	mov	$3, %ax	int	$0x10	print	"ISR error!\n"	halt	pop	%gs	pop	%fs	pop	%es	pop	%ds	popal	popfl	leave	ljmp	*%cs:_oldisr0:	mov	$0x20, %al	cmp	$7, %cs:_irq	jbe	0f	outb	%al, $0xa00:	outb	%al, $0x20	movb	$1, %cs:_int	movw	$0, %cs:_in	pop	%gs	pop	%fs	pop	%es	pop	%ds	popal	popfl	leave	iret# processpacket: reads packet and checks packet, copy if ok# returns:#  ax = 1 if packet copiedprocesspacket:	enter	$0, $0	push	%bx	push	%cx	push	%ds	push	%es	push	%si	push	%diprint "i"	xorw	%bx, %bx	movw	$2, %cs:_undi_isr + 2	# PXENV_UNDI_ISR_IN_PROCESS	push	$0x0014			# undi isr	push	$_undi_isr	call	api	cmp	$0, %ax	je	0f	print	"PXENV_UNDI_ISR_IN_PROCESS failed\n"	pushw	%cs:_undi_isr	call	printword	call	line	halt0:	cmpw	$0, %cs:_undi_isr + 2	# done	jne	0f	print	"ISR started, but nothing to process?\n"	jmp	9f0:	cmpw	$4, %cs:_undi_isr + 2	# busy	jne	0f	print	"b"	jmp	9f0:	push	%cs	pop	%es	mov	$receive, %di3:	cld	cmpw	$2, %cs:_undi_isr + 2	# transmit	je	1f0:	cmpw	$3, %cs:_undi_isr + 2	# receive	je	0f	print	"Unknown function?\n"	jmp	1f0:print "."	mov	%cs:_undi_isr + 4, %cx	mov	%cs:_undi_isr + 12, %ds	mov	%cs:_undi_isr + 10, %si	rep	movsb	mov	$1, %bx1:	movw	$3, %cs:_undi_isr + 2	# PXENV_UNDI_ISR_IN_GET_NEXT	push	$0x0014			# undi isr	push	$_undi_isr	call	api	cmp	$0, %ax	je	0f	print	"PXENV_UNDI_ISR_IN_GET_NEXT failed\n"	pushw	%cs:_undi_isr	call	printword	call	line	halt0:	cmpw	$4, %cs:_undi_isr + 2	# busy	je	9f	cmpw	$0, %cs:_undi_isr + 2	# done	je	9f	jmp	3b9:print "o"	mov	%bx, %ax	pop	%di	pop	%si	pop	%es	pop	%ds	pop	%cx	pop	%bx	leave	ret	$0

⌨️ 快捷键说明

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