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

📄 pxelinux.asm

📁 Windows上的精简Linux系统
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;;	On exit, if found:;		CF = 0, ES:BX -> !PXE structure;	Otherwise CF = 1, all registers saved;	memory_scan_for_pxe_struct:		push ds		pusha		mov ax,cs		mov ds,ax		mov si,trymempxe_msg		call writestr		mov ax,[BIOS_fbm]	; Starting segment		shl ax,(10-4)		; Kilobytes -> paragraphs;		mov ax,01000h		; Start to look here		dec ax			; To skip inc ax.mismatch:		inc ax		cmp ax,0A000h		; End of memory		jae .not_found		call writehex4		mov si,fourbs_msg		call writestr		mov es,ax		mov edx,[es:0]		cmp edx,'!PXE'		jne .mismatch		movzx cx,byte [es:4]	; Length of structure		cmp cl,08h		; Minimum length		jb .mismatch		push ax		xor ax,ax		xor si,si.checksum:	es lodsb		add ah,al		loop .checksum		pop ax		jnz .mismatch		; Checksum must == 0.found:		mov bp,sp		xor bx,bx		mov [bp+8],bx		; Save BX into stack frame (will be == 0)		mov ax,es		call writehex4		call crlf		popa		pop ds		clc		ret.not_found:	mov si,notfound_msg		call writestr		popa		pop ds		stc		ret;; memory_scan_for_pxenv_struct:;;	If none of the standard methods find the PXENV+ structure, look for it;	by scanning memory.;;	On exit, if found:;		CF = 0, ES:BX -> PXENV+ structure;	Otherwise CF = 1, all registers saved;	memory_scan_for_pxenv_struct:		pusha		mov si,trymempxenv_msg		call writestr;		mov ax,[BIOS_fbm]	; Starting segment;		shl ax,(10-4)		; Kilobytes -> paragraphs		mov ax,01000h		; Start to look here		dec ax			; To skip inc ax.mismatch:		inc ax		cmp ax,0A000h		; End of memory		jae .not_found		mov es,ax		mov edx,[es:0]		cmp edx,'PXEN'		jne .mismatch		mov dx,[es:4]		cmp dx,'V+'		jne .mismatch		movzx cx,byte [es:8]	; Length of structure		cmp cl,26h		; Minimum length		jb .mismatch		xor ax,ax		xor si,si.checksum:	es lodsb		add ah,al		loop .checksum		and ah,ah		jnz .mismatch		; Checksum must == 0.found:		mov bp,sp		mov [bp+8],bx		; Save BX into stack frame		mov ax,bx		call writehex4		call crlf		clc		ret.not_found:	mov si,notfound_msg		call writestr		popad		stc		ret;; searchdir:;;	Open a TFTP connection to the server ;;	     On entry:;		DS:DI	= filename;	     If successful:;		ZF clear;		SI	= socket pointer;		DX:AX	= file length in bytes;	     If unsuccessful;		ZF set;searchdir:		push es		mov ax,ds		mov es,ax		mov si,di		push bp		mov bp,sp		call allocate_socket		jz .error		mov ax,PKT_RETRY	; Retry counter		mov word [PktTimeout],PKT_TIMEOUT	; Initial timeout	.sendreq:	push ax			; [bp-2]  - Retry counter		push si			; [bp-4]  - File name 		push bx			; [bp-6]  - TFTP block		mov bx,[bx]		push bx			; [bp-8]  - TID (local port no)		mov eax,[ServerIP]	; Server IP		mov [pxe_udp_write_pkt.status],byte 0		mov [pxe_udp_write_pkt.sip],eax		mov eax,[UseGW]		mov [pxe_udp_write_pkt.gip],eax		mov [pxe_udp_write_pkt.lport],bx		mov ax,[ServerPort]		mov [pxe_udp_write_pkt.rport],ax		mov di,packet_buf		mov [pxe_udp_write_pkt.buffer],di		mov ax,TFTP_RRQ		; TFTP opcode		stosw		push si			; Add common prefix		mov si,PathPrefix		call strcpy		dec di		pop si		call strcpy		; Filename		mov si,tftp_tail		mov cx,tftp_tail_len		rep movsb		sub di,packet_buf	; Get packet size		mov [pxe_udp_write_pkt.buffersize],di		mov di,pxe_udp_write_pkt		mov bx,PXENV_UDP_WRITE		call pxenv		jc .failure		cmp word [pxe_udp_write_pkt.status],byte 0		jne .failure		;		; Danger, Will Robinson!  We need to support timeout		; and retry lest we just lost a packet...		;		; Packet transmitted OK, now we need to receive.getpacket:	push word [PktTimeout]	; [bp-10]		push word [BIOS_timer]	; [bp-12].pkt_loop:	mov bx,[bp-8]		; TID		mov di,packet_buf		mov word [pxe_udp_read_pkt.status],0		mov [pxe_udp_read_pkt.buffer],di		mov [pxe_udp_read_pkt.buffer+2],ds		mov word [pxe_udp_read_pkt.buffersize],packet_buf_size		mov eax,[MyIP]		mov [pxe_udp_read_pkt.dip],eax		mov [pxe_udp_read_pkt.lport],bx		mov di,pxe_udp_read_pkt		mov bx,PXENV_UDP_READ		call pxenv		and ax,ax		jz .got_packet			; Wait for packet.no_packet:		mov dx,[BIOS_timer]		cmp dx,[bp-12]		je .pkt_loop		mov [bp-12],dx		dec word [bp-10]		; Timeout		jnz .pkt_loop		pop ax	; Adjust stack		pop ax		shl word [PktTimeout],1		; Exponential backoff		jmp .failure		.got_packet:		mov si,[bp-6]			; TFTP pointer		mov bx,[bp-8]			; TID		mov eax,[ServerIP]		cmp [pxe_udp_read_pkt.sip],eax	; This is technically not to the TFTP spec?		jne .no_packet		mov [si+tftp_remoteip],eax		; Got packet - reset timeout		mov word [PktTimeout],PKT_TIMEOUT		pop ax	; Adjust stack		pop ax		mov ax,[pxe_udp_read_pkt.rport]		mov [si+tftp_remoteport],ax		; filesize <- -1 == unknown		mov dword [si+tftp_filesize], -1		; Default blksize unless blksize option negotiated		mov word [si+tftp_blksize], TFTP_BLOCKSIZE		mov cx,[pxe_udp_read_pkt.buffersize]		sub cx,2		; CX <- bytes after opcode		jb .failure		; Garbled reply		mov si,packet_buf		lodsw		cmp ax, TFTP_ERROR		je .bailnow		; ERROR reply: don't try again		cmp ax, TFTP_OACK		jne .no_tsize		; Now we need to parse the OACK packet to get the transfer		; size.  SI -> first byte of options; CX -> byte count.parse_oack:		jcxz .no_tsize			; No options acked.get_opt_name:		mov di,si		mov bx,si.opt_name_loop:	lodsb		and al,al		jz .got_opt_name		or al,20h			; Convert to lowercase		stosb		loop .opt_name_loop		; We ran out, and no final null		jmp .err_reply.got_opt_name:	; si -> option value		dec cx				; bytes left in pkt		jz .err_reply			; Option w/o value		; Parse option pointed to by bx; guaranteed to be		; null-terminated.		push cx		push si		mov si,bx			; -> option name		mov bx,tftp_opt_table		mov cx,tftp_opts.opt_loop:		push cx		push si		mov di,[bx]			; Option pointer		mov cx,[bx+2]			; Option len		repe cmpsb		pop si		pop cx		je .get_value			; OK, known option		add bx,6		loop .opt_loop		pop si		pop cx		jmp .err_reply			; Non-negotiated option returned.get_value:	pop si				; si -> option value		pop cx				; cx -> bytes left in pkt		mov bx,[bx+4]			; Pointer to data target		add bx,[bp-6]			; TFTP socket pointer		xor eax,eax		xor edx,edx.value_loop:	lodsb		and al,al		jz .got_value		sub al,'0'		cmp al, 9		ja .err_reply			; Not a decimal digit		imul edx,10		add edx,eax		mov [bx],edx		loop .value_loop		; Ran out before final null, accept anyway		jmp short .done_pkt.got_value:		dec cx		jnz .get_opt_name		; Not end of packet		; ZF == 1		; Success, done!.done_pkt:		pop si			; Junk			pop si			; We want the packet ptr in SI		mov eax,[si+tftp_filesize]		cmp eax,-1		jz .no_tsize		mov edx,eax		shr edx,16		; DX:AX == EAX		and eax,eax		; Set ZF depending on file size		pop bp			; Junk		pop bp			; Junk (retry counter)		jz .error_si		; ZF = 1 need to free the socket		pop bp		pop es		ret.no_tsize:.err_reply:	; Option negotiation error.  Send ERROR reply.		; ServerIP and gateway are already programmed in		mov si,[bp-6]		mov ax,[si+tftp_remoteport]		mov word [pxe_udp_write_pkt.rport],ax		mov word [pxe_udp_write_pkt.buffer],tftp_opt_err		mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len		mov di,pxe_udp_write_pkt		mov bx,PXENV_UDP_WRITE		call pxenv		; Write an error message and explode		mov si,err_oldtftp		call writestr		jmp kaboom.bailnow:	mov word [bp-2],1	; Immediate error - no retry.failure:	pop bx			; Junk		pop bx		pop si		pop ax		dec ax			; Retry counter		jnz .sendreq		; Try again.error:		mov si,bx		; Socket pointer.error_si:				; Socket pointer already in SI		call free_socket	; ZF <- 1, SI <- 0		pop bp		pop es		ret;; allocate_socket: Allocate a local UDP port structure;;		If successful:;		  ZF set;		  BX     = socket pointer;               If unsuccessful:;                 ZF clear;allocate_socket:		push cx		mov bx,Sockets		mov cx,MAX_SOCKETS.check:		cmp word [bx], byte 0		je .found		add bx,tftp_port_t_size		loop .check		xor cx,cx			; ZF = 1		pop cx		ret		; Allocate a socket number.  Socket numbers are made		; guaranteed unique by including the socket slot number		; (inverted, because we use the loop counter cx); add a		; counter value to keep the numbers from being likely to		; get immediately reused.		;		; The NextSocket variable also contains the top two bits		; set.  This generates a value in the range 49152 to		; 57343..found:		dec cx		push ax		mov ax,[NextSocket]		inc ax		and ax,((1 << (13-MAX_SOCKETS_LG2))-1) | 0xC000		mov [NextSocket],ax		shl cx,13-MAX_SOCKETS_LG2		add cx,ax			; ZF = 0		xchg ch,cl			; Convert to network byte order		mov [bx],cx			; Socket in use		pop ax		pop cx		ret;; Free socket: socket in SI; return SI = 0, ZF = 1 for convenience;free_socket:		push es		pusha		xor ax,ax		mov es,ax		mov di,si		mov cx,tftp_clear_words		rep stosw		popa		pop es		xor si,si		ret;; strcpy: Copy DS:SI -> ES:DI up to and including a null byte;strcpy:		push ax.loop:		lodsb		stosb		and al,al		jnz .loop		pop ax		ret;; writechr:	Write a single character in AL to the console without;		mangling any registers.  This does raw console writes,;		since some PXE BIOSes seem to interfere regular console I/O.;writechr:		push ds		push cs		pop ds		call write_serial	; write to serial port if needed		pushfd		pushad		mov bh,[BIOS_page]		push ax                mov ah,03h              ; Read cursor position                int 10h		pop ax		cmp al,8		je .bs		cmp al,13		je .cr		cmp al,10		je .lf		push dx                mov bh,[BIOS_page]		mov bl,07h		; White on black		mov cx,1		; One only		mov ah,09h		; Write char and attribute		int 10h		pop dx		inc dl		cmp dl,[VidCols]		jna .curxyok		xor dl,dl.lf:		inc dh		cmp dh,[VidRows]		ja .scroll.curxyok:	mov bh,[BIOS_page]		mov ah,02h		; Set cursor position		int 10h			.ret:		popad		popfd		pop ds		ret.scroll:	dec dh		mov bh,[BIOS_page]		mov ah,02h		int 10h		mov ax,0601h		; Scroll up one line		mov bh,[ScrollAttribute]		xor cx,cx		mov dx,[ScreenSize]	; The whole screen		int 10h		jmp short .ret.cr:		xor dl,dl		jmp short .curxyok.bs:		sub dl,1		jnc .curxyok		mov dl,[VidCols]		sub dh,1		jnc .curxyok		xor dh,dh		jmp short .curxyok;; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed;	       to by ES:DI; ends on encountering any whitespace.;;	       This verifies that a filename is < FILENAME_MAX characters;	       and doesn't contain whitespace, and zero-pads the output buffer,;	       so "repe cmpsb" can do a compare.;mangle_name:		mov cx,FILENAME_MAX-1.mn_loop:		lodsb		cmp al,' '			; If control or space, end		jna .mn_end		stosb		loop .mn_loop.mn_end:		inc cx				; At least one null byte		xor ax,ax			; Zero-fill name		rep stosb			; Doesn't do anything if CX=0		ret				; Done;; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled;                filename to the conventional representation.  This is needed;                for the BOOT_IMAGE= parameter for the kernel.;                NOTE: A 13-byte buffer is mandatory, even if the string is;                known to be shorter.;;                DS:SI -> input mangled file name;                ES:DI -> output buffer;;                On return, DI points to the first byte after the output name,;                which is set to a null byte.

⌨️ 快捷键说明

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