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

📄 pxelinux.asm

📁 Windows上的精简Linux系统
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;unmangle_name:	call strcpy		dec di				; Point to final null byte		ret;; pxenv;; This is the main PXENV+/!PXE entry point, using the PXENV+; calling convention.  This is a separate local routine so; we can hook special things from it if necessary.;pxenv:.jump:		call 0:pxe_thunk		; Default to calling the thunk		cld				; Make sure DF <- 0		ret; Must be after function def due to NASM bugPXENVEntry	equ pxenv.jump+1;; pxe_thunk;; Convert from the PXENV+ calling convention (BX, ES, DI) to the !PXE; calling convention (using the stack.);; This is called as a far routine so that we can just stick it into; the PXENVEntry variable.;pxe_thunk:	push es		push di		push bx.jump:		call 0:0		add sp,byte 6		cmp ax,byte 1		cmc				; Set CF unless ax == 0		retf; Must be after function def due to NASM bugPXEEntry	equ pxe_thunk.jump+1;; getfssec: Get multiple clusters from a file, given the starting cluster.;;	In this case, get multiple blocks from a specific TCP connection.;;  On entry:;	ES:BX	-> Buffer;	SI	-> TFTP socket pointer;	CX	-> 512-byte block count; 0FFFFh = until end of file;  On exit:;	SI	-> TFTP socket pointer (or 0 on EOF);	CF = 1	-> Hit EOF;getfssec:	push si		push fs		mov di,bx		mov bx,si		mov ax,pktbuf_seg		mov fs,ax		movzx ecx,cx		shl ecx,TFTP_BLOCKSIZE_LG2	; Convert to bytes		jz .hit_eof			; Nothing to do?		.need_more:		push ecx		movzx eax,word [bx+tftp_bytesleft]		cmp ecx,eax		jna .ok_size		mov ecx,eax		jcxz .need_packet		; No bytes available?.ok_size:		mov ax,cx			; EAX<31:16> == ECX<31:16> == 0		mov si,[bx+tftp_dataptr]		sub [bx+tftp_bytesleft],cx		fs rep movsb			; Copy from packet buffer		mov [bx+tftp_dataptr],si		pop ecx		sub ecx,eax		jnz .need_more.hit_eof:		pop fs		pop si		; Is there anything left of this?		mov eax,[si+tftp_filesize]		sub eax,[si+tftp_filepos]		jnz .bytes_left	; CF <- 0		cmp [si+tftp_bytesleft],ax		jnz .bytes_left	; CF <- 0		; The socket is closed and the buffer drained		; Close socket structure and re-init for next user		call free_socket		stc.bytes_left:		ret;; No data in buffer, check to see if we can get a packet...;.need_packet:		pop ecx		mov eax,[bx+tftp_filesize]		cmp eax,[bx+tftp_filepos]		je .hit_eof			; Already EOF'd; socket already closed		pushad		push es		mov si,bx		call get_packet		pop es		popad		jmp .need_more;; Get a fresh packet; expects fs -> pktbuf_seg and ds:si -> socket structure;get_packet:		mov ax,ds		mov es,ax	.packet_loop:		; Start by ACKing the previous packet; this should cause the		; next packet to be sent.		mov cx,PKT_RETRY		mov word [PktTimeout],PKT_TIMEOUT.send_ack:	push cx				; <D> Retry count		mov ax,[si+tftp_lastpkt]		call ack_packet			; Send ACK		; We used to test the error code here, but sometimes		; PXE would return negative status even though we really		; did send the ACK.  Now, just treat a failed send as		; a normally lost packet, and let it time out in due		; course of events..send_ok:	; Now wait for packet.		mov dx,[BIOS_timer]		; Get current time		mov cx,[PktTimeout].wait_data:	push cx				; <E> Timeout		push dx				; <F> Old time		mov bx,[si+tftp_pktbuf]		mov [pxe_udp_read_pkt.buffer],bx		mov [pxe_udp_read_pkt.buffer+2],fs		mov [pxe_udp_read_pkt.buffersize],word PKTBUF_SIZE		mov eax,[si+tftp_remoteip]		mov [pxe_udp_read_pkt.sip],eax		mov eax,[MyIP]		mov [pxe_udp_read_pkt.dip],eax		mov ax,[si+tftp_remoteport]		mov [pxe_udp_read_pkt.rport],ax		mov ax,[si+tftp_localport]		mov [pxe_udp_read_pkt.lport],ax		mov di,pxe_udp_read_pkt		mov bx,PXENV_UDP_READ		push si				; <G>		call pxenv		pop si				; <G>		and ax,ax		jz .recv_ok		; No packet, or receive failure		mov dx,[BIOS_timer]		pop ax				; <F> Old time		pop cx				; <E> Timeout		cmp ax,dx			; Same time -> don't advance timeout		je .wait_data			; Same clock tick		loop .wait_data			; Decrease timeout				pop cx				; <D> Didn't get any, send another ACK		shl word [PktTimeout],1		; Exponential backoff		loop .send_ack		jmp kaboom			; Forget it....recv_ok:	pop dx				; <F>		pop cx				; <E>		cmp word [pxe_udp_read_pkt.buffersize],byte 4		jb .wait_data			; Bad size for a DATA packet		mov bx,[si+tftp_pktbuf]		cmp word [fs:bx],TFTP_DATA	; Not a data packet?		jne .wait_data			; Then wait for something else		mov ax,[si+tftp_lastpkt]		xchg ah,al			; Host byte order		inc ax				; Which packet are we waiting for?		xchg ah,al			; Network byte order		cmp [fs:bx+2],ax		je .right_packet		; Wrong packet, ACK the packet and then try again		; This is presumably because the ACK got lost,		; so the server just resent the previous packet		mov ax,[fs:bx+2]		call ack_packet		jmp .send_ok			; Reset timeout.right_packet:	; It's the packet we want.  We're also EOF if the size < blocksize		pop cx				; <D> Don't need the retry count anymore		mov [si+tftp_lastpkt],ax	; Update last packet number		movzx ecx,word [pxe_udp_read_pkt.buffersize]		sub cx,byte 4			; Skip TFTP header		; If this is a zero-length block, don't mess with the pointers,		; since we may have just set up the previous block that way		jz .last_block		; Set pointer to data block		lea ax,[bx+4]			; Data past TFTP header		mov [si+tftp_dataptr],ax		add [si+tftp_filepos],ecx		mov [si+tftp_bytesleft],cx		cmp cx,[si+tftp_blksize]	; Is it a full block?		jb .last_block			; If so, it's not EOF		; If we had the exact right number of bytes, always get		; one more packet to get the (zero-byte) EOF packet and		; close the socket.		mov eax,[si+tftp_filepos]		cmp [si+tftp_filesize],eax		je .packet_loop		ret.last_block:	; Last block - ACK packet immediately		mov ax,[fs:bx+2]		call ack_packet		; Make sure we know we are at end of file		mov eax,[si+tftp_filepos]		mov [si+tftp_filesize],eax			ret;; ack_packet:;; Send ACK packet.  This is a common operation and so is worth canning.;; Entry:;	SI 	= TFTP block;	AX 	= Packet # to ack (network byte order); Exit:;	ZF = 0 -> Error;	All registers preserved;; This function uses the pxe_udp_write_pkt but not the packet_buf.;ack_packet:		pushad		mov [ack_packet_buf+2],ax	; Packet number to ack		mov ax,[si]		mov [pxe_udp_write_pkt.lport],ax		mov ax,[si+tftp_remoteport]		mov [pxe_udp_write_pkt.rport],ax		mov eax,[si+tftp_remoteip]		mov [pxe_udp_write_pkt.sip],eax		xor eax,[MyIP]		and eax,[Netmask]		jz .nogw		mov eax,[Gateway].nogw:		mov [pxe_udp_write_pkt.gip],eax		mov [pxe_udp_write_pkt.buffer],word ack_packet_buf		mov [pxe_udp_write_pkt.buffersize], word 4		mov di,pxe_udp_write_pkt		mov bx,PXENV_UDP_WRITE		call pxenv		cmp ax,byte 0			; ZF = 1 if write OK		popad		ret;; unload_pxe:;; This function unloads the PXE and UNDI stacks and unclaims; the memory.;unload_pxe:		test byte [KeepPXE],01h		; Should we keep PXE around?		jnz reset_pxe		push ds		push es		mov ax,cs		mov ds,ax		mov es,ax		mov si,new_api_unload		cmp byte [APIVer+1],2		; Major API version >= 2?		jae .new_api		mov si,old_api_unload.new_api:		.call_loop:	xor ax,ax		lodsb		and ax,ax		jz .call_done		xchg bx,ax		mov di,pxe_unload_stack_pkt		push di		xor ax,ax		mov cx,pxe_unload_stack_pkt_len >> 1		rep stosw		pop di		call pxenv		jc .cant_free		mov ax,word [pxe_unload_stack_pkt.status]		cmp ax,PXENV_STATUS_SUCCESS		jne .cant_free		jmp .call_loop.call_done:%if USE_PXE_PROVIDED_STACK		; We need to switch to our local stack here...		pusha		pushf		push gs		mov si,sp		mov ax,ss		mov gs,ax		sub ax,[BaseStack+4]		; Are we using the base stack		je .is_base_stack		; (as opposed to the COMBOOT stack)?		lgs si,[SavedSSSP]		; COMBOOT stack.is_base_stack:		mov cx,[InitStack]		mov di,StackBuf		mov [BaseStack],di		mov [BaseStack+4],es		sub cx,si		sub di,cx		mov [SavedSSSP],di		; New SP		mov [SavedSSSP+2],es		gs rep movsb		and ax,ax			; Remember which stack		jne .combootstack		; Update the base stack pointer since it's in use		lss sp,[SavedSSSP]		.combootstack:		pop gs		popf		popa%endif		mov bx,0FF00h		mov dx,[RealBaseMem]		cmp dx,[BIOS_fbm]		; Sanity check		jna .cant_free		inc bx		; Check that PXE actually unhooked the INT 1Ah chain		movzx eax,word [4*0x1a]		movzx ecx,word [4*0x1a+2]		shl ecx,4		add eax,ecx		shr eax,10		cmp ax,dx			; Not in range		jae .ok		cmp ax,[BIOS_fbm]		jae .cant_free		; inc bx.ok:		mov [BIOS_fbm],dx.pop_ret:		pop es		pop ds		ret		.cant_free:		mov si,cant_free_msg		call writestr		push ax		xchg bx,ax		call writehex4		mov al,'-'		call writechr		pop ax		call writehex4		mov al,'-'		call writechr		mov eax,[4*0x1a]		call writehex8		call crlf		jmp .pop_ret		; We want to keep PXE around, but still we should reset		; it to the standard bootup configurationreset_pxe:		push es		push cs		pop es		mov bx,PXENV_UDP_CLOSE		mov di,pxe_udp_close_pkt		call pxenv		pop es		ret;; gendotquad;; Take an IP address (in network byte order) in EAX and; output a dotted quad string to ES:DI.; DI points to terminal null at end of string on exit.;; CX is destroyed.;gendotquad:		push eax		mov cx,4.genchar:		push eax		cmp al,10		; < 10?		jb .lt10		; If so, skip first 2 digits		cmp al,100		; < 100		jb .lt100		; If so, skip first digit		aam 100		; Now AH = 100-digit; AL = remainder		add ah,'0'		mov [es:di],ah		inc di.lt100:		aam 10		; Now AH = 10-digit; AL = remainder		add ah,'0'		mov [es:di],ah				inc di.lt10:		add al,'0'		stosb		mov al,'.'		stosb		pop eax		ror eax,8	; Move next char into LSB		loop .genchar		dec di		mov [es:di], byte 0		pop eax		ret;; parse_dhcp;; Parse a DHCP packet.  This includes dealing with "overloaded"; option fields (see RFC 2132, section 9.3);; This should fill in the following global variables, if the; information is present:;; MyIP		- client IP address; ServerIP	- boot server IP address; Netmask	- network mask; Gateway	- default gateway router IP; UseGW		- zero if ServerIP local, otherwise Gateway; BootFile	- boot file name;; This assumes the DHCP packet is in "trackbuf" and the length; of the packet in in CX on entry.;parse_dhcp:		mov byte [OverLoad],0		; Assume no overload		mov eax, [trackbuf+bootp.yip]		and eax, eax		jz .noyip		cmp al,224			; Class D or higher -> bad		jae .noyip		mov [MyIP], eax.noyip:		mov eax, [trackbuf+bootp.sip]		and eax, eax		jz .nosip		cmp al,224			; Class D or higher -> bad		jae .nosip		mov [ServerIP], eax.nosip:		sub cx, bootp.options		jbe .nooptions		mov si, trackbuf+bootp.option_magic		lodsd		cmp eax, BOOTP_OPTION_MAGIC		jne .nooptions		call parse_dhcp_options.nooptions:		mov si, trackbuf+bootp.bootfile		test byte [OverLoad],1		jz .nofileoverload		mov cx,128		call parse_dhcp_options		jmp short .parsed_file.nofileoverload:		cmp byte [si], 0		jz .parsed_file			; No bootfile name		mov di,BootFile		mov cx,32		rep movsd		xor al,al		stosb				; Null-terminate.parsed_file:		mov si, trackbuf+bootp.sname

⌨️ 快捷键说明

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